From bc0f9f522ebad5c7cf2b95b9721ade62481059b7 Mon Sep 17 00:00:00 2001 From: Polina Bungina Date: Thu, 27 Jul 2023 20:46:36 +0200 Subject: [PATCH] Refactor do_POST_failover checks --- patroni/api.py | 25 +++++++++++++------------ tests/test_api.py | 1 + 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/patroni/api.py b/patroni/api.py index b9626ecf..0702cff9 100644 --- a/patroni/api.py +++ b/patroni/api.py @@ -1018,24 +1018,25 @@ class RestApiHandler(BaseHTTPRequestHandler): logger.info("received %s request with leader=%s candidate=%s scheduled_at=%s", action, leader, candidate, scheduled_at) - if action == 'failover': - if not candidate: - data = 'Failover could be performed only to a specific candidate' - elif scheduled_at: - data = "Failover can't be scheduled" + if action == 'failover' and not candidate: + data = 'Failover could be performed only to a specific candidate' elif action == 'switchover' and not leader: data = 'Switchover could be performed only from a specific leader' if not data and scheduled_at: - if not leader: - data = 'Scheduled {0} is possible only from a specific leader'.format(action) - if not data and global_config.is_paused: - data = "Can't schedule {0} in the paused state".format(action) - if not data: + if action == 'failover': + data = "Failover can't be scheduled" + elif global_config.is_paused: + data = "Can't schedule switchover in the paused state" + else: (status_code, data, scheduled_at) = self.parse_schedule(scheduled_at, action) if not data and global_config.is_paused and not candidate: - data = action.title() + ' is possible only to a specific candidate in a paused state' + data = 'Switchover is possible only to a specific candidate in a paused state' + + if action == 'failover' and leader: + logger.warning('received failover request with leader specifed - performing switchover') + action = 'switchover' if not data and not scheduled_at: data = self.is_failover_possible(cluster, leader, candidate, action) @@ -1052,7 +1053,7 @@ class RestApiHandler(BaseHTTPRequestHandler): status_code, data = self.poll_failover_result(cluster.leader and cluster.leader.name, candidate, action) else: - data = 'failed to write {0} key into DCS'.format(action) + data = 'failed to write failover key into DCS' status_code = 503 # pyright thinks ``status_code`` can be ``None`` because ``parse_schedule`` call may return ``None``. However, # if that's the case, ``status_code`` will be overwritten somewhere between ``parse_schedule`` and diff --git a/tests/test_api.py b/tests/test_api.py index f9d0b1c1..837cdbaf 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -580,6 +580,7 @@ class TestRestApiHandler(unittest.TestCase): post = 'POST /failover HTTP/1.0' + self._authorization + '\nContent-Length: ' MockRestApiServer(RestApiHandler, post + '14\n\n{"leader":"1"}') MockRestApiServer(RestApiHandler, post + '37\n\n{"candidate":"2","scheduled_at": "1"}') + MockRestApiServer(RestApiHandler, post + '30\n\n{"leader":"1","candidate":"2"}') @patch.object(MockHa, 'is_leader', Mock(return_value=True)) def test_do_POST_citus(self):