diff --git a/patroni/api.py b/patroni/api.py index 56cbcc4f..d2f52d03 100644 --- a/patroni/api.py +++ b/patroni/api.py @@ -84,35 +84,20 @@ class RestApiHandler(BaseHTTPRequestHandler): patroni = self.server.patroni cluster = patroni.dcs.cluster - def is_synchronous(): - return (cluster.is_synchronous_mode() and cluster.sync - and cluster.sync.sync_standby == patroni.postgresql.name) + replica_status_code = 200 if not patroni.noloadbalance and response.get('role') == 'replica' else 503 + status_code = 503 - def is_balanceable_replica(): - return response.get('role') == 'replica' and not patroni.noloadbalance - - if cluster: # dcs available - if patroni.ha.is_leader(): - status_code = 200 if 'master' in path else 503 - elif 'role' not in response: - status_code = 503 - elif response['role'] == 'master': # running as master but without leader lock!!!! - status_code = 503 - elif path in ('/sync', '/synchronous'): - status_code = 200 if is_balanceable_replica() and is_synchronous() else 503 - elif path in ('/async', '/asynchronous'): - status_code = 200 if is_balanceable_replica() and not is_synchronous() else 503 - elif response['role'] in path: # response['role'] != 'master' - status_code = 503 if patroni.noloadbalance else 200 - else: - status_code = 503 - elif 'role' in response and response['role'] in path: - status_code = 503 if response['role'] != 'master' and patroni.noloadbalance else 200 - elif patroni.ha.restart_scheduled() and patroni.postgresql.role == 'master' and 'master' in path: - # exceptional case for master node when the postgres is being restarted via API - status_code = 200 - else: - status_code = 503 + if 'master' in path: + status_code = 200 if patroni.ha.is_leader() else 503 + elif 'replica' in path: + status_code = replica_status_code + elif cluster: # dcs is available + is_synchronous = cluster.is_synchronous_mode() and cluster.sync \ + and cluster.sync.sync_standby == patroni.postgresql.name + if path in ('/sync', '/synchronous') and is_synchronous: + status_code = replica_status_code + elif path in ('/async', '/asynchronous') and not is_synchronous: + status_code = replica_status_code if write_status_code_only: # when haproxy sends OPTIONS request it reads only status code and nothing more message = self.responses[status_code][0] diff --git a/tests/test_api.py b/tests/test_api.py index ae0f1632..04979151 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -155,6 +155,7 @@ class TestRestApiHandler(unittest.TestCase): with patch.object(RestApiHandler, 'get_postgresql_status', Mock(return_value={'role': 'replica'})): MockRestApiServer(RestApiHandler, 'GET /synchronous') with patch.object(RestApiHandler, 'get_postgresql_status', Mock(return_value={'role': 'replica'})): + MockPatroni.dcs.cluster.sync.sync_standby = '' MockRestApiServer(RestApiHandler, 'GET /asynchronous') MockPatroni.ha.is_leader = Mock(return_value=True) MockRestApiServer(RestApiHandler, 'GET /replica')