]> Frank Brehm's Git Trees - pixelpark/puppetmaster-webhooks.git/commitdiff
Start reading Puppetfiles
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 23 Aug 2018 13:35:17 +0000 (15:35 +0200)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 23 Aug 2018 13:35:17 +0000 (15:35 +0200)
lib/webhooks/get_forge_modules.py
lib/webhooks/module_info.py

index a7ec0e3e07c4492aa1763d7d933d137118993eed..1d39f0a3fbd22e5aa1ac26f2ddab614e5dafabcf 100644 (file)
@@ -53,6 +53,9 @@ class GetForgeModulesApp(BaseHookApp):
     default_http_timeout = 30
     max_http_timeout = 600
 
+    re_comment = re.compile(r'^\s*#')
+    re_comma_at_end = re.compile(r',\s*$')
+
     open_args = {}
     if six.PY3:
         open_args = {
@@ -154,7 +157,59 @@ class GetForgeModulesApp(BaseHookApp):
     # -------------------------------------------------------------------------
     def collect_local_modules(self):
 
-        pass
+        self.modules = {}
+
+        for env in self.environments:
+            self.read_puppetfile(env)
+
+    # -------------------------------------------------------------------------
+    def read_puppetfile(self, env):
+
+        puppetfile = os.path.join(self.puppet_root_env_dir, env, 'Puppetfile')
+        if self.verbose > 1:
+            LOG.debug("Searching {!r} ...".format(puppetfile))
+        if not os.path.exists(puppetfile):
+            LOG.warn("Could not find {!r}.".format(puppetfile))
+            return
+        if not os.access(puppetfile, os.R_OK):
+            LOG.warn("No read access to {!r}.".format(puppetfile))
+            return
+
+        LOG.debug("Reading {!r} ...".format(puppetfile))
+
+        with open(puppetfile, 'r', **self.open_args) as fh:
+            if self.verbose > 3:
+                LOG.debug("Class of opened file: {!r}".format(fh.__class__.__name__))
+            prev_line = ''
+            for line in fh.readlines():
+
+                line = line.strip()
+                if not line:
+                    continue
+                if self.re_comment.match(line):
+                    continue
+
+                if self.verbose > 3:
+                    LOG.debug("Read line {!r}...".format(line))
+
+                prev_line += line
+                if self.re_comma_at_end.search(line):
+                    continue
+
+                if self.verbose > 2:
+                    LOG.debug("Evaluating line {!r}...".format(prev_line))
+                module_info = ModuleInfo.init_from_puppetfile_line(
+                    appname=self.appname, verbose=self.verbose, base_dir=self.base_dir,
+                    line=prev_line, env=env)
+
+                prev_line = ''
+
+            if prev_line:
+                if self.verbose > 2:
+                    LOG.debug("Evaluating line {!r}...".format(prev_line))
+                module_info = ModuleInfo.init_from_puppetfile_line(
+                    appname=self.appname, verbose=self.verbose, base_dir=self.base_dir,
+                    line=prev_line, env=env)
 
     # -------------------------------------------------------------------------
     def init_puppet_environments(self):
index 261ab5ebf49d11e017560d550c083cc6bd90cdd7..b8326c091d98ec739a3894c11a82f274a994d36b 100644 (file)
@@ -22,7 +22,7 @@ from .common import pp, to_str
 from .obj import BaseObjectError
 from .obj import BaseObject
 
-__version__ = '0.1.0'
+__version__ = '0.2.0'
 
 LOG = logging.getLogger(__name__)
 
@@ -38,6 +38,7 @@ class ModuleInfo(BaseObject):
     """Class for encapsulating information about a Puppet module."""
 
     re_split_name = re.compile(r'^\s*([a-z0-9]+)[-/_](\S+)\s*$', re.IGNORECASE)
+    re_mod_pf_line = re.compile(r'\s*mod\s+\'([^\']+)\'\s*,\s*(\S+.*)\s*$', re.IGNORECASE)
 
     # -------------------------------------------------------------------------
     def __init__(
@@ -69,7 +70,7 @@ class ModuleInfo(BaseObject):
 
         if _full_name:
 
-            match = re_split_name.match(_full_name)
+            match = self.re_split_name.match(_full_name)
             if not match:
                 raise ModuleInfoError(
                     "Could not analyze given full module name {!r}.".format(
@@ -140,6 +141,55 @@ class ModuleInfo(BaseObject):
         else:
             self._full_name_orig = None
 
+    # -------------------------------------------------------------------------
+    def as_dict(self, short=True):
+        """
+        Transforms the elements of the object into a dict
+
+        @return: structure as dict
+        @rtype:  dict
+        """
+
+        res = super(ModuleInfo, self).as_dict()
+
+        res['name'] = self.name
+        res['vendor'] = self.vendor
+        res['full_name'] = self.full_name
+        res['full_name_orig'] = self.full_name_orig
+
+        return res
+
+    # -------------------------------------------------------------------------
+    @classmethod
+    def init_from_puppetfile_line(
+        cls, line, env, appname=None, verbose=0, base_dir=None):
+
+        match = cls.re_mod_pf_line.search(line)
+        if not match:
+            if verbose > 2:
+                LOG.debug("Line {!r} is not a module definition line.".format(line))
+            return None
+
+        fullname_orig = match.group(1)
+        mod_def = match.group(2)
+        module_info = None
+
+        try:
+            module_info = cls(
+                appname=appname, verbose=verbose, base_dir=base_dir,
+                full_name=fullname_orig,
+            )
+        except ModuleInfoError as e:
+            LOG.warn("{c}: {e}".format(c=e.__class__.__name__, e=e))
+            return None
+
+        module_info.initialized = True
+
+        if verbose > 2:
+            LOG.debug("Initialized {c} object:\n{s}".format(
+                c=module_info.__class__.__name__, s=pp(module_info.as_dict())))
+
+        return module_info
 
 # =============================================================================