diff --git a/docs/releases.rst b/docs/releases.rst index d2f65f96..7e04dff4 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -3,6 +3,20 @@ Release notes ============= +Version 1.4.1 +------------- + +**Fixes in patronictl** + +- Don't show current leader in suggested list of members to failover to. (Alexander Kukushkin) + + patronictl failover could still work when there is leader in the cluster and it should be excluded from the list of member where it is possible to failover to. + +- Make patronictl switchover compatible with the old Patroni api (Alexander) + + In case if POST /switchover REST API call has failed with status code 501 it will do it once again, but to /failover endpoint. + + Version 1.4 ----------- diff --git a/patroni/ctl.py b/patroni/ctl.py index c9454023..dc339e7c 100644 --- a/patroni/ctl.py +++ b/patroni/ctl.py @@ -546,15 +546,14 @@ def _do_failover_or_switchover(obj, action, cluster_name, master, candidate, for dcs = get_dcs(obj, cluster_name) cluster = dcs.get_cluster() - if action == 'switchover': - if cluster.leader is None: - raise PatroniCtlException('This cluster has no master') + if action == 'switchover' and cluster.leader is None: + raise PatroniCtlException('This cluster has no master') - if master is None: - if force: - master = cluster.leader.member.name - else: - master = click.prompt('Master', type=str, default=cluster.leader.member.name) + if master is None: + if force or action == 'failover': + master = cluster.leader and cluster.leader.name + else: + master = click.prompt('Master', type=str, default=cluster.leader.member.name) if master is not None and cluster.leader and cluster.leader.member.name != master: raise PatroniCtlException('Member {0} is not the leader of cluster {1}'.format(master, cluster_name)) @@ -610,6 +609,11 @@ def _do_failover_or_switchover(obj, action, cluster_name, master, candidate, for member = cluster.leader.member if cluster.leader else cluster.get_member(candidate, False) r = request_patroni(member, 'post', action, failover_value, auth_header(obj)) + + # probably old patroni, which doesn't support switchover yet + if r.status_code == 501 and action == 'switchover' and 'Server does not support this operation' in r.text: + r = request_patroni(member, 'post', 'failover', failover_value, auth_header(obj)) + if r.status_code in (200, 202): logging.debug(r) cluster = dcs.get_cluster() diff --git a/patroni/version.py b/patroni/version.py index 0f663085..8e3c933c 100644 --- a/patroni/version.py +++ b/patroni/version.py @@ -1 +1 @@ -__version__ = '1.4' +__version__ = '1.4.1' diff --git a/tests/test_ctl.py b/tests/test_ctl.py index db79607e..46987769 100644 --- a/tests/test_ctl.py +++ b/tests/test_ctl.py @@ -129,6 +129,11 @@ class TestCtl(unittest.TestCase): result = self.runner.invoke(ctl, ['switchover', 'dummy'], input='leader\nother\n\ny') assert 'Switchover failed' in result.output + mocked.return_value.status_code = 501 + mocked.return_value.text = 'Server does not support this operation' + result = self.runner.invoke(ctl, ['switchover', 'dummy'], input='leader\nother\n\ny') + assert 'Switchover failed' in result.output + # No members available mock_get_dcs.return_value.get_cluster = get_cluster_initialized_with_only_leader result = self.runner.invoke(ctl, ['switchover', 'dummy'], input='leader\nother\n\ny')