From a55cbff865a6fcc808a629ba80eed3e4942a8204 Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Tue, 31 May 2016 16:13:32 +0200 Subject: [PATCH] Compare configuration objects "smart" and "deep" --- patroni/config.py | 7 ++++--- patroni/utils.py | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/patroni/config.py b/patroni/config.py index 485aa335..d4a186b9 100644 --- a/patroni/config.py +++ b/patroni/config.py @@ -6,6 +6,7 @@ import yaml from copy import deepcopy from patroni.postgresql import Postgresql +from patroni.utils import deep_compare logger = logging.getLogger(__name__) @@ -94,7 +95,7 @@ class Config(object): logger.error('Can not remove temporary file %s', tmpfile) def set_dynamic_configuration(self, configuration): - if self._dynamic_configuration != configuration: + if not deep_compare(self._dynamic_configuration, configuration): try: self.__effective_configuration = self._build_effective_configuration(configuration, self._local_configuration) @@ -108,10 +109,10 @@ class Config(object): if self.config_file: try: configuration = self._load_config_file() - if self._local_configuration != configuration: + if not deep_compare(self._local_configuration, configuration): new_configuration = self._build_effective_configuration(self._dynamic_configuration, configuration) if dry_run: - return new_configuration != self.__effective_configuration + return not deep_compare(new_configuration, self.__effective_configuration) self._local_configuration = configuration self.__effective_configuration = new_configuration return True diff --git a/patroni/utils.py b/patroni/utils.py index 0969d458..d5e8bc41 100644 --- a/patroni/utils.py +++ b/patroni/utils.py @@ -33,6 +33,32 @@ def calculate_ttl(expiration): return int((expiration - now).total_seconds()) +def deep_compare(obj1, obj2): + """ + >>> deep_compare({'1': None}, {}) + False + >>> deep_compare({'1': {}}, {'1': None}) + False + >>> deep_compare({'1': [1]}, {'1': [2]}) + False + >>> deep_compare({'1': 2}, {'1': '2'}) + True + >>> deep_compare({'1': {'2': [3, 4]}}, {'1': {'2': [3, 4]}}) + True + """ + + if set(list(obj1.keys())) != set(list(obj2.keys())): # Objects have different sets of keys + return False + + for key, value in obj1.items(): + if isinstance(value, dict): + if not (isinstance(obj2[key], dict) and deep_compare(value, obj2[key])): + return False + elif str(value) != str(obj2[key]): + return False + return True + + def set_ignore_sigterm(value=True): global __ignore_sigterm __ignore_sigterm = value