]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Comparing existing files with theitr new versions
authorFrank Brehm <frank.brehm@pixelpark.com>
Tue, 8 Aug 2017 14:01:04 +0000 (16:01 +0200)
committerFrank Brehm <frank.brehm@pixelpark.com>
Tue, 8 Aug 2017 14:01:04 +0000 (16:01 +0200)
pp_lib/config_named_app.py

index 47b676093060c0bea906279e101bffc19a1b5009..42812cea8ac2947beed6542ae1df40ab19668004 100644 (file)
@@ -39,7 +39,7 @@ from .cfg_app import PpCfgAppError, PpConfigApplication
 
 from .pidfile import PidFileError, InvalidPidFileError, PidFileInUseError, PidFile
 
-__version__ = '0.6.1'
+__version__ = '0.6.2'
 LOG = logging.getLogger(__name__)
 
 
@@ -94,6 +94,9 @@ class PpConfigNamedApp(PpConfigApplication):
     re_ipv4_zone = re.compile(r'^((?:\d+\.)+)in-addr\.arpa\.$')
     re_ipv6_zone = re.compile(r'^((?:[\da-f]\.)+)ip6\.arpa\.$')
 
+    re_block_comment = re.compile(r'/\*.*?\*/', re.MULTILINE | re.DOTALL)
+    re_line_comment = re.compile(r'(?://|#).*$', re.MULTILINE)
+
     open_args = {}
     if six.PY3:
         open_args = {
@@ -277,6 +280,11 @@ class PpConfigNamedApp(PpConfigApplication):
         self.temp_log_cfg_file = None
         self.temp_zones_cfg_file = None
 
+        self.reload_necessary = False
+        self.restart_necessary = False
+
+        self.files2replace = {}
+
         self.acls = {
             'allow-notify': ['dnsmaster.pixelpark.com'],
             'allow-transfer': ['dnsmaster.pixelpark.com'],
@@ -799,6 +807,7 @@ class PpConfigNamedApp(PpConfigApplication):
             self.get_api_zones()
             self.init_temp_objects()
             self.create_temp_files()
+            self.compare_files()
 
         finally:
             if self.tempdir:
@@ -817,8 +826,6 @@ class PpConfigNamedApp(PpConfigApplication):
         self.generate_log_cfg_file()
         self.generate_slave_cfg_file()
 
-        time.sleep(2)
-
     # -------------------------------------------------------------------------
     def init_temp_objects(self):
         """Init temporary objects and properties."""
@@ -1368,6 +1375,103 @@ class PpConfigNamedApp(PpConfigApplication):
 
         return ':'.join(tokens)
 
+    # -------------------------------------------------------------------------
+    def compare_files(self):
+
+        LOG.info("Comparing generated files with existing ones.")
+
+        if not self.files_equal_content(self.temp_named_conf, self.named_conf):
+            self.reload_necessary = True
+            self.restart_necessary = True
+            self.files2replace[self.named_conf] = self.temp_named_conf
+
+        if not self.files_equal_content(self.temp_acl_cfg_file, self.named_acl_cfg_file):
+            self.reload_necessary = True
+            self.files2replace[self.named_acl_cfg_file] = self.temp_acl_cfg_file
+
+        if not self.files_equal_content(self.temp_log_cfg_file, self.named_log_cfg_file):
+            self.reload_necessary = True
+            self.restart_necessary = True
+            self.files2replace[self.named_log_cfg_file] = self.temp_log_cfg_file
+
+        if not self.files_equal_content(self.temp_zones_cfg_file, self.named_zones_cfg_file):
+            self.reload_necessary = True
+            self.files2replace[self.named_zones_cfg_file] = self.temp_zones_cfg_file
+
+        if self.verbose > 1:
+            LOG.debug("Files to replace:\n{}".format(pp(self.files2replace)))
+
+    # -------------------------------------------------------------------------
+    def files_equal_content(self, file_src, file_tgt):
+
+        LOG.debug("Comparing {!r} with {!r} ...".format(file_src, file_tgt))
+
+        if not file_src:
+            raise PpConfigNamedError("Source file not defined.")
+        if not file_tgt:
+            raise PpConfigNamedError("Target file not defined.")
+
+        if not os.path.exists(file_src):
+            raise PpConfigNamedError("Source file {!r} does not exists.".format(file_src))
+        if not os.path.isfile(file_src):
+            raise PpConfigNamedError("Source file {!r} is not a regular file.".format(file_src))
+
+        if not os.path.exists(file_tgt):
+            LOG.debug("Target file {!r} does not exists.".format(file_tgt))
+            return False
+        if not os.path.isfile(file_tgt):
+            raise PpConfigNamedError("Target file {!r} is not a regular file.".format(file_tgt))
+
+        content_src = ''
+        if self.verbose > 2:
+            LOG.debug("Reading {!r} ...".format(file_src))
+        with open(file_src, 'r', **self.open_args) as fh:
+            content_src = fh.read()
+        lines_str_src = self.re_block_comment.sub('', content_src)
+        lines_str_src = self.re_line_comment.sub('', lines_str_src)
+        lines_src = []
+        for line in lines_str_src.splitlines():
+            line = line.strip()
+            if line:
+                lines_src.append(line)
+        if self.verbose > 3:
+            LOG.debug("Cleaned version of {!r}:\n{}".format(
+                file_src, '\n'.join(lines_src)))
+
+        content_tgt = ''
+        if self.verbose > 2:
+            LOG.debug("Reading {!r} ...".format(file_tgt))
+        with open(file_tgt, 'r', **self.open_args) as fh:
+            content_tgt = fh.read()
+        lines_str_tgt = self.re_block_comment.sub('', content_tgt)
+        lines_str_tgt = self.re_line_comment.sub('', lines_str_tgt)
+        lines_tgt = []
+        for line in lines_str_tgt.splitlines():
+            line = line.strip()
+            if line:
+                lines_tgt.append(line)
+        if self.verbose > 3:
+            LOG.debug("Cleaned version of {!r}:\n{}".format(
+                file_tgt, '\n'.join(lines_tgt)))
+
+        if len(lines_src) != len(lines_tgt):
+            LOG.debug((
+                "Source file {!r} has different number essential lines ({}) than "
+                "the target file {!r} ({} lines).").format(
+                file_src, len(lines_src), file_tgt, len(lines_tgt)))
+            return False
+
+        i = 0
+        while i < len(lines_src):
+            if lines_src[i] != lines_tgt[i]:
+                LOG.debug((
+                    "Source file {!r} has a different content than "
+                    "the target file {!r}.").format(file_src, lines_tgt))
+                return False
+            i += 1
+
+        return True
+
 # =============================================================================
 
 if __name__ == "__main__":