Refactoring from patronicli to patronictl

This commit is contained in:
Feike Steenbergen
2015-11-13 12:55:38 +01:00
parent 92b23a2018
commit dcb5113f9d
4 changed files with 32 additions and 25 deletions
+3 -2
View File
@@ -13,8 +13,9 @@ RUN apt-get update -y
RUN apt-get upgrade -y
ENV PGVERSION 9.4
RUN apt-get install python python-psycopg2 python-yaml python-requests python-boto postgresql-${PGVERSION} python-dnspython python-kazoo python-pip -y
RUN pip install python-etcd
RUN apt-get install python python-yaml python-requests python-boto postgresql-${PGVERSION} python-dnspython python-kazoo python-pip -y
RUN apt-get install python-dev postgresql-server-dev-${PGVERSION} -y
RUN pip install python-etcd psycopg2
ENV PATH /usr/lib/postgresql/${PGVERSION}/bin:$PATH
+22 -16
View File
@@ -1,5 +1,5 @@
'''
Patroni Command Line Client
Patroni Control
'''
import click
@@ -16,8 +16,8 @@ import logging
from .etcd import Etcd
CONFIG_DIR_PATH = click.get_app_dir('patroni')
CONFIG_FILE_PATH = os.path.join(CONFIG_DIR_PATH, 'patronicli.yaml')
LOGLEVEL = 'DEBUG'
CONFIG_FILE_PATH = os.path.join(CONFIG_DIR_PATH, 'patronictl.yaml')
LOGLEVEL = 'INFO'
def parse_dcs(dcs):
@@ -86,7 +86,7 @@ option_force = click.option('--force', is_flag=True, help='Do not ask for confir
@click.group()
@click.pass_context
def cli(ctx):
def ctl(ctx):
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=LOGLEVEL)
@@ -99,6 +99,13 @@ def get_dcs(config, scope):
raise Exception('Can not find suitable configuration of distributed configuration store')
def get_patroni(member, endpoint):
url = urlparse(member.api_url)
logging.debug(url)
r = requests.get('{}://{}/{}'.format(url.scheme, url.netloc, endpoint))
return r
def post_patroni(member, endpoint, content, headers={'Content-Type': 'application/json'}):
url = urlparse(member.api_url)
logging.debug(url)
@@ -137,7 +144,7 @@ def watching(w, watch):
yield 0
@cli.command('remove', help='Remove cluster from DCS')
@ctl.command('remove', help='Remove cluster from DCS')
@click.argument('cluster_name')
@option_config_file
@option_format
@@ -168,12 +175,12 @@ def remove(config_file, cluster_name, format, dcs):
raise Exception("You did not specify the current master of the cluster")
if isinstance(dcs, Etcd):
dcs.client.delete(dcs._base_path, recursive=True)
dcs.ctlent.delete(dcs._base_path, recursive=True)
else:
raise Exception("We have not implemented this for DCS of type {}", type(dcs))
def wait_for_master(dcs, timeout=30):
def wait_for_leader(dcs, timeout=30):
t_stop = time.time() + timeout
timeout /= 2
@@ -217,7 +224,7 @@ def empty_post_to_members(cluster_name, member_names, config_file, dcs, force, e
click.echo('Succesful {} on member {}'.format(endpoint, mn))
@cli.command('restart', help='Restart cluster member')
@ctl.command('restart', help='Restart cluster member')
@click.argument('cluster_name')
@click.argument('member_names', nargs=-1)
@option_config_file
@@ -227,7 +234,7 @@ def restart(cluster_name, member_names, config_file, dcs, force):
empty_post_to_members(cluster_name, member_names, config_file, dcs, force, 'restart')
@cli.command('reinit', help='Reinitialize cluster member')
@ctl.command('reinit', help='Reinitialize cluster member')
@click.argument('cluster_name')
@click.argument('member_names', nargs=-1)
@option_config_file
@@ -237,7 +244,7 @@ def reinit(cluster_name, member_names, config_file, dcs, force):
empty_post_to_members(cluster_name, member_names, config_file, dcs, force, 'reinitialize')
@cli.command('failover', help='Failover to a replica')
@ctl.command('failover', help='Failover to a replica')
@click.argument('cluster_name')
@click.option('--master', help='The name of the current master', default=None)
@click.option('--candidate', help='The name of the candidate', default=None)
@@ -249,7 +256,7 @@ def failover(config_file, cluster_name, master, candidate, force, dcs):
We want to trigger a failover for the specified cluster name.
We verify that the cluster name, master name and candidate name are correct.
If so, we trigger a failover and keep the client up to date.
If so, we trigger a failover and keep the ctlent up to date.
"""
config = load_config(config_file, dcs)
dcs = get_dcs(config, cluster_name)
@@ -268,13 +275,12 @@ def failover(config_file, cluster_name, master, candidate, force, dcs):
raise Exception('Member {} is not the leader of cluster {}'.format(master, cluster_name))
candidate_names = [str(m.name) for m in cluster.members if m.name != master]
## We sort the names for consistent output to the client
# We sort the names for consistent output to the ctlent
candidate_names.sort()
if len(candidate_names) == 0:
raise Exception('No candidates found to failover to')
if candidate is None and not force:
candidate = click.prompt('Candidate '+str(candidate_names), type=str, default='')
@@ -312,7 +318,7 @@ def failover(config_file, cluster_name, master, candidate, force, dcs):
click.echo(timestamp()+' Initialized failover from master {}'.format(master))
# The failover process should within a minute update the failover key, we will keep watching it until it changes
# or we timeout
cluster = wait_for_master(dcs, timeout=60)
cluster = wait_for_leader(dcs, timeout=60)
click.echo(timestamp()+' Failover completed in {:0.1f} seconds, new leader is {}'.format(
time.time() - t_started, str(cluster.leader.member.name)))
@@ -340,7 +346,7 @@ def output_members(cluster, name=None, format='pretty'):
print_output(['Cluster', 'Member', 'Leader'], rows, {'Cluster': 'l', 'Member': 'l'}, format)
@cli.command('list', help='List the Patroni members for a given Patroni')
@ctl.command('list', help='List the Patroni members for a given Patroni')
@click.argument('cluster_names', nargs=-1)
@option_config_file
@option_format
@@ -364,7 +370,7 @@ def timestamp():
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
@cli.command('configure', help='Create configuration file')
@ctl.command('configure', help='Create configuration file')
@click.option('--config-file', '-c', help='Configuration file', prompt='Configuration file', default=CONFIG_FILE_PATH)
@click.option('--dcs', '-d', help='The DCS connect url', prompt='DCS connect url', default='etcd://localhost:4001')
@click.option('--namespace', '-n', help='The namespace', prompt='Namespace', default='/service/')
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python
from patroni.cli import cli
from patroni.ctl import ctl
if __name__ == '__main__':
cli()
ctl()
+5 -5
View File
@@ -5,10 +5,10 @@ import os
import pytest
from click.testing import CliRunner
from patroni.cli import cli, members, store_config, load_config, output_members
from patroni.ctl import ctl, members, store_config, load_config, output_members
from test_ha import get_cluster_initialized_with_leader
CONFIG_FILE_PATH = './test-cli.yaml'
CONFIG_FILE_PATH = './test-ctl.yaml'
def test_output_members():
@@ -34,12 +34,12 @@ def test_rw_config():
load_config(CONFIG_FILE_PATH, None)
def test_cli():
def test_ctl():
runner = CliRunner()
runner.invoke(cli, ['list'])
runner.invoke(ctl, ['list'])
result = runner.invoke(cli, ['--help'])
result = runner.invoke(ctl, ['--help'])
assert 'Usage:' in result.output