From e10873dd9c09cd15ec4dcd7fce17cf8e53fc7ae9 Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Tue, 31 May 2016 15:49:55 +0200 Subject: [PATCH] RestApiHandler._patch_config returns True if configuration was changed --- patroni/api.py | 20 ++++++++++++++------ tests/test_api.py | 10 +++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/patroni/api.py b/patroni/api.py index ad688f57..18eb21eb 100644 --- a/patroni/api.py +++ b/patroni/api.py @@ -110,13 +110,22 @@ class RestApiHandler(BaseHTTPRequestHandler): @staticmethod def _patch_config(config, data): + is_changed = False for name, value in data.items(): - if isinstance(value, dict) and name in config: - RestApiHandler._patch_config(config[name], value) - elif value is None: - config.pop(name, None) + if value is None: + if config.pop(name, None) is not None: + is_changed = True + elif name in config: + if isinstance(value, dict): + if RestApiHandler._patch_config(config[name], value): + is_changed = True + elif str(config[name]) != str(value): + config[name] = value + is_changed = True else: config[name] = value + is_changed = True + return is_changed @check_auth def do_PATCH_config(self): @@ -124,8 +133,7 @@ class RestApiHandler(BaseHTTPRequestHandler): request = json.loads(self.rfile.read(content_length).decode('utf-8')) cluster = self.server.patroni.ha.dcs.get_cluster() data = cluster.config.data.copy() - RestApiHandler._patch_config(data, request) - if data != cluster.config.data: + if RestApiHandler._patch_config(data, request): self.server.patroni.ha.dcs.set_config_value(json.dumps(data, separators=(',', ':')), cluster.config.index) self._write_json_response(200, data) else: diff --git a/tests/test_api.py b/tests/test_api.py index 44dfead1..fe569836 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,3 +1,4 @@ +import json import psycopg2 import unittest @@ -123,11 +124,14 @@ class TestRestApiHandler(unittest.TestCase): @patch.object(MockHa, 'dcs') def test_do_PATCH_config(self, mock_dcs): - mock_dcs.get_cluster.return_value.config = \ - ClusterConfig.from_node(1, '{"postgresql": {"use_slots": false, "parameters": {"wal_level": "logical"}}}') + config = {'postgresql': {'use_slots': False, 'use_pg_rewind': True, 'parameters': {'wal_level': 'logical'}}} + mock_dcs.get_cluster.return_value.config = ClusterConfig.from_node(1, json.dumps(config)) request = 'PATCH /config HTTP/1.0' + self._authorization + '\nContent-Length: ' self.assertIsNotNone(MockRestApiServer(RestApiHandler, request + '2\n\n{}')) - MockRestApiServer(RestApiHandler, request + '59\n\n{"ttl":5,"use_slots":true,"postgresql":{"parameters":null}}') + config['ttl'] = 5 + config['postgresql'].update({'use_slots': True, "parameters": None}) + config = json.dumps(config) + MockRestApiServer(RestApiHandler, request + str(len(config)) + '\n\n' + config) @patch.object(MockPatroni, 'sighup_handler', Mock(side_effect=Exception)) def test_do_POST_reload(self):