From 10a49532ae459ee1b1cc45b3b72072d8bdd37310 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 5 Jan 2016 11:25:21 +0200 Subject: [PATCH 1/4] Add / replace functionality to augeas transform paths to overwrite old narrower scope if needed --- .../letsencrypt_apache/parser.py | 64 ++++++++++++++++--- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/letsencrypt-apache/letsencrypt_apache/parser.py b/letsencrypt-apache/letsencrypt_apache/parser.py index 593c807cc..04b61b2d4 100644 --- a/letsencrypt-apache/letsencrypt_apache/parser.py +++ b/letsencrypt-apache/letsencrypt_apache/parser.py @@ -35,6 +35,7 @@ class ApacheParser(object): # https://httpd.apache.org/docs/2.4/mod/core.html#define # https://httpd.apache.org/docs/2.4/mod/core.html#ifdefine # This only handles invocation parameters and Define directives! + self.parser_paths = {} self.variables = {} if version >= (2, 4): self.update_runtime_variables() @@ -471,16 +472,61 @@ class ApacheParser(object): :param str filepath: Apache config file path """ + use_new, remove_old = self._check_path_actions(filepath) # Test if augeas included file for Httpd.lens # Note: This works for augeas globs, ie. *.conf - inc_test = self.aug.match( - "/augeas/load/Httpd/incl [. ='%s']" % filepath) - if not inc_test: - # Load up files - # This doesn't seem to work on TravisCI - # self.aug.add_transform("Httpd.lns", [filepath]) - self._add_httpd_transform(filepath) - self.aug.load() + if use_new: + inc_test = self.aug.match( + "/augeas/load/Httpd/incl [. ='%s']" % filepath) + if not inc_test: + # Load up files + # This doesn't seem to work on TravisCI + # self.aug.add_transform("Httpd.lns", [filepath]) + if remove_old: + self._remove_httpd_transform(filepath) + self._add_httpd_transform(filepath) + self.aug.load() + + def _check_path_actions(self, filepath): + """Determine actions to take with a new augeas path + + This helper function will return a tuple that defines + if we should try to append the new filepath to augeas + parser paths, and / or remove the old one with more + narrow matching. + + :param str filepath: filepath to check the actions for + + """ + + try: + use_new = False + remove_old = False + new_file_match = os.path.basename(filepath) + existing_match = self.parser_paths[os.path.dirname(filepath)] + if existing_match == new_file_match: + # True here to let augeas verify that the path is parsed + use_new = True + elif new_file_match == "*": + use_new = True + remove_old = True + except KeyError: + use_new = True + return use_new, remove_old + + def _remove_httpd_transform(self, filepath): + """Remove path from Augeas transform + + :param str filepath: filepath to remove + """ + + remove_basename = self.parser_paths[os.path.dirname(filepath)] + remove_dirname = os.path.dirname(filepath) + remove_path = remove_dirname + "/" + remove_basename + remove_inc = self.aug.match( + "/augeas/load/Httpd/incl [. ='%s']" % remove_path) + self.aug.remove(remove_inc[0]) + self.parser_paths.pop(remove_dirname) def _add_httpd_transform(self, incl): """Add a transform to Augeas. @@ -502,6 +548,8 @@ class ApacheParser(object): # Augeas uses base 1 indexing... insert at beginning... self.aug.set("/augeas/load/Httpd/lens", "Httpd.lns") self.aug.set("/augeas/load/Httpd/incl", incl) + # Add included path to paths dictionary + self.parser_paths[os.path.dirname(incl)] = os.path.basename(incl) def standardize_excl(self): """Standardize the excl arguments for the Httpd lens in Augeas. From 63f311eea492433b5a12ac685907b5d49105c44f Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 5 Jan 2016 13:16:49 +0200 Subject: [PATCH 2/4] Refactored the checking method to be easier to read --- letsencrypt-apache/letsencrypt_apache/parser.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/letsencrypt-apache/letsencrypt_apache/parser.py b/letsencrypt-apache/letsencrypt_apache/parser.py index 04b61b2d4..23ca05ae0 100644 --- a/letsencrypt-apache/letsencrypt_apache/parser.py +++ b/letsencrypt-apache/letsencrypt_apache/parser.py @@ -500,18 +500,19 @@ class ApacheParser(object): """ try: - use_new = False - remove_old = False new_file_match = os.path.basename(filepath) existing_match = self.parser_paths[os.path.dirname(filepath)] - if existing_match == new_file_match: - # True here to let augeas verify that the path is parsed - use_new = True - elif new_file_match == "*": + if existing_match == "*": + use_new = False + else: use_new = True + if new_file_match == "*": remove_old = True + else: + remove_old = False except KeyError: use_new = True + remove_old = False return use_new, remove_old def _remove_httpd_transform(self, filepath): From 32d5375b9bb101f7e9239627c2ccb17a728046da Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 5 Jan 2016 13:21:18 +0200 Subject: [PATCH 3/4] Change test to check out adding a file not already in the augeas paths --- letsencrypt-apache/letsencrypt_apache/tests/parser_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/letsencrypt-apache/letsencrypt_apache/tests/parser_test.py b/letsencrypt-apache/letsencrypt_apache/tests/parser_test.py index b871f89b7..9b78bf6d6 100644 --- a/letsencrypt-apache/letsencrypt_apache/tests/parser_test.py +++ b/letsencrypt-apache/letsencrypt_apache/tests/parser_test.py @@ -36,7 +36,7 @@ class BasicParserTest(util.ParserTest): """ file_path = os.path.join( - self.config_path, "sites-available", "letsencrypt.conf") + self.config_path, "not-parsed-by-default", "letsencrypt.conf") self.parser._parse_file(file_path) # pylint: disable=protected-access From ffeef67e542dfb170d051d60b3e519fa689bbe03 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Tue, 5 Jan 2016 14:36:42 +0200 Subject: [PATCH 4/4] Use lists to handle multiple different matching wildcards in same directory --- .../letsencrypt_apache/parser.py | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/letsencrypt-apache/letsencrypt_apache/parser.py b/letsencrypt-apache/letsencrypt_apache/parser.py index 23ca05ae0..82effad2b 100644 --- a/letsencrypt-apache/letsencrypt_apache/parser.py +++ b/letsencrypt-apache/letsencrypt_apache/parser.py @@ -501,8 +501,8 @@ class ApacheParser(object): try: new_file_match = os.path.basename(filepath) - existing_match = self.parser_paths[os.path.dirname(filepath)] - if existing_match == "*": + existing_matches = self.parser_paths[os.path.dirname(filepath)] + if "*" in existing_matches: use_new = False else: use_new = True @@ -521,12 +521,13 @@ class ApacheParser(object): :param str filepath: filepath to remove """ - remove_basename = self.parser_paths[os.path.dirname(filepath)] + remove_basenames = self.parser_paths[os.path.dirname(filepath)] remove_dirname = os.path.dirname(filepath) - remove_path = remove_dirname + "/" + remove_basename - remove_inc = self.aug.match( - "/augeas/load/Httpd/incl [. ='%s']" % remove_path) - self.aug.remove(remove_inc[0]) + for name in remove_basenames: + remove_path = remove_dirname + "/" + name + remove_inc = self.aug.match( + "/augeas/load/Httpd/incl [. ='%s']" % remove_path) + self.aug.remove(remove_inc[0]) self.parser_paths.pop(remove_dirname) def _add_httpd_transform(self, incl): @@ -550,7 +551,12 @@ class ApacheParser(object): self.aug.set("/augeas/load/Httpd/lens", "Httpd.lns") self.aug.set("/augeas/load/Httpd/incl", incl) # Add included path to paths dictionary - self.parser_paths[os.path.dirname(incl)] = os.path.basename(incl) + try: + self.parser_paths[os.path.dirname(incl)].append( + os.path.basename(incl)) + except KeyError: + self.parser_paths[os.path.dirname(incl)] = [ + os.path.basename(incl)] def standardize_excl(self): """Standardize the excl arguments for the Httpd lens in Augeas.