]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Reading metadata of all modules
authorFrank Brehm <frank.brehm@pixelpark.com>
Wed, 15 Aug 2018 10:11:37 +0000 (12:11 +0200)
committerFrank Brehm <frank.brehm@pixelpark.com>
Wed, 15 Aug 2018 10:11:37 +0000 (12:11 +0200)
pp_lib/check_puppet_env_app.py

index df5bc8d954da5453bccc8aa829ecdb45d5c5dce1..52a0fdd38951f6fc85e87f18016df8e94cd21b2f 100644 (file)
@@ -39,7 +39,7 @@ from .merge import merge_structure
 
 from .app import PpApplication
 
-__version__ = '0.2.1'
+__version__ = '0.3.1'
 LOG = logging.getLogger(__name__)
 
 
@@ -59,6 +59,13 @@ class CheckPuppetEnvApp(PpApplication):
 
     default_puppet_root_env_dir = os.sep + os.path.join('etc', 'puppetlabs', 'code', 'environments')
 
+    open_args = {}
+    if six.PY3:
+        open_args = {
+            'encoding': 'utf-8',
+            'errors': 'surrogateescape',
+        }
+
     # -------------------------------------------------------------------------
     def __init__(
         self, appname=None, verbose=0, version=__version__, base_dir=None,
@@ -74,6 +81,8 @@ class CheckPuppetEnvApp(PpApplication):
         self.environments = []
         self.env_name = None
         self.env_dir = None
+        self.modules_root_dir = None
+        self.modules = {}
 
         super(CheckPuppetEnvApp, self).__init__(
             appname=appname, verbose=verbose, version=version, base_dir=base_dir,
@@ -91,23 +100,23 @@ class CheckPuppetEnvApp(PpApplication):
 
         self.post_init()
 
-#    # -------------------------------------------------------------------------
-#    def as_dict(self, short=True):
-#        """
-#        Transforms the elements of the object into a dict
-#
-#        @param short: don't include local properties in resulting dict.
-#        @type short: bool
-#
-#        @return: structure as dict
-#        @rtype:  dict
-#        """
-#
-#        res = super(CheckPuppetEnvApp, self).as_dict(short=short)
-#        res['cfg_dir'] = self.cfg_dir
-#
-#        return res
-#
+    # -------------------------------------------------------------------------
+    def as_dict(self, short=True):
+        """
+        Transforms the elements of the object into a dict
+
+        @param short: don't include local properties in resulting dict.
+        @type short: bool
+
+        @return: structure as dict
+        @rtype:  dict
+        """
+
+        res = super(CheckPuppetEnvApp, self).as_dict(short=short)
+        res['open_args'] = self.open_args
+
+        return res
+
     # -------------------------------------------------------------------------
     def init_arg_parser(self):
         """
@@ -245,6 +254,8 @@ class CheckPuppetEnvApp(PpApplication):
 
         self.perform_arg_parser()
         self.init_logging()
+        self.modules_root_dir = os.path.join(self.env_dir, 'modules')
+
         self.initialized = True
 
     # -------------------------------------------------------------------------
@@ -253,8 +264,96 @@ class CheckPuppetEnvApp(PpApplication):
         Main application routine.
         """
 
-        LOG.info("I'm walkin, yes indeed, I'm walkin ...")
+        self.collect_modules()
+
+    # -------------------------------------------------------------------------
+    def collect_modules(self):
+
+        LOG.info("Collecting all modules from {!r} ...".format(self.modules_root_dir))
+        self.modules = {}
+
+        if not os.path.exists(self.modules_root_dir):
+            LOG.error("Directory {!r} does not exists.".format(self.modules_root_dir))
+            self.exit(7)
 
+        if not os.path.isdir(self.modules_root_dir):
+            LOG.error("Path {!r} is not a directory".format(self.modules_root_dir))
+            self.exit(7)
+
+        pattern = os.path.join(self.modules_root_dir, '*')
+        if self.verbose > 2:
+            LOG.debug("Globbing pattern for module directories: {!r}".format(pattern))
+        for module_dir in glob.glob(pattern):
+            module_info = self.get_module_info(module_dir)
+            if module_info:
+                base_name = module_info['base_name']
+                self.modules[base_name] = module_info
+
+        if self.verbose > 2:
+            LOG.debug("Found module information:\n{}".format(pp(self.modules)))
+
+    # -------------------------------------------------------------------------
+    def get_module_info(self, module_dir):
+
+        if self.verbose > 2:
+            LOG.debug("Get module information from {!r}.".format(module_dir))
+
+        if not os.path.exists(module_dir):
+            LOG.warn("Directory {!r} does not exists.".format(module_dir))
+            return None
+
+        if not os.path.isdir(module_dir):
+            LOG.warn("Path {!r} is not a directory".format(module_dir))
+            return None
+
+        module_info = {}
+        module_info['base_name'] = os.path.basename(module_dir)
+        metadata_file = os.path.join(module_dir, 'metadata.json')
+        if not os.path.exists(metadata_file):
+            LOG.warn("Metadatafile {!r} does not exists.".format(metadata_file))
+            return None
+        if not os.path.isfile(metadata_file):
+            LOG.warn("Metadatafile {!r} is not a regular file.".format(metadata_file))
+            return None
+        if not os.access(metadata_file, os.R_OK):
+            LOG.warn("Metadatafile {!r} is readable.".format(metadata_file))
+            return None
+        if self.verbose > 2:
+            LOG.debug("Reading and evaluating {!r}.".format(metadata_file))
+        meta_info = {}
+
+        try:
+            with open(metadata_file, 'r', **self.open_args) as fh:
+                meta_info = json.load(fh)
+        except json.JSONDecodeError as e:
+            LOG.warn((
+                "Could not interprete {f!r} (line {l}, column {c}) "
+                "as a regular JSON file: {e}").format(
+                f=metadata_file, l=e.lineno, c=e.colno, e=e.msg))
+            return None
+
+        module_info['name'] = None
+        module_info['vendor'] = None
+        module_info['dependencies'] = {}
+        if 'name'in meta_info:
+            module_info['name'] = meta_info['name']
+            pat_vendor = r'^(\S+)[-_/]' + re.escape(module_info['base_name']) + r'$'
+            match = re.match(pat_vendor, module_info['name'])
+            if match:
+                module_info['vendor'] = match.group(1)
+
+        if 'dependencies' in meta_info:
+            for dep in meta_info['dependencies']:
+                if 'name' in dep:
+                    dep_info = {
+                        'name': dep['name'],
+                        'version': None
+                    }
+                    if 'version_requirement' in dep:
+                        dep_info['version'] = dep['version_requirement']
+                    module_info['dependencies'][dep['name']] = dep_info
+
+        return module_info
 
 # =============================================================================