From: Frank Brehm Date: Tue, 19 Mar 2019 11:10:53 +0000 (+0100) Subject: Reading forge cache file X-Git-Tag: 1.6.4^2~17 X-Git-Url: https://git.uhu-banane.net/?a=commitdiff_plain;h=5cb9d6e9c4a783e87778980213c6c8331e273a4b;p=pixelpark%2Fpuppetmaster-webhooks.git Reading forge cache file --- diff --git a/lib/webhooks/forge/mod_dict.py b/lib/webhooks/forge/mod_dict.py index e42fa3c..483341f 100644 --- a/lib/webhooks/forge/mod_dict.py +++ b/lib/webhooks/forge/mod_dict.py @@ -24,11 +24,11 @@ from collections import MutableMapping from functools import cmp_to_key # Third party modules - +import six from six import reraise # Own modules -from fb_tools.common import to_bool, to_bytes +from fb_tools.common import to_bool, to_bytes, pp from fb_tools.obj import FbBaseObject from .mod_info import ForgeModuleInfo @@ -37,7 +37,7 @@ from ..errors import BaseHookError from ..xlate import XLATOR -__version__ = '0.2.2' +__version__ = '0.3.0' LOG = logging.getLogger(__name__) @@ -51,6 +51,39 @@ class ForgeModuleDictError(BaseHookError): pass +# ============================================================================= +class DatafileNotExistingError(ForgeModuleDictError, IOError): + + # ------------------------------------------------------------------------- + def __init__(self, data_file): + + msg = _("Data file of forge modules cache is not existing") + super(DatafileNotExistingError, self).__init__( + errno.ENOENT, msg, str(data_file)) + + +# ============================================================================= +class DatafileIsDirError(ForgeModuleDictError, IOError): + + # ------------------------------------------------------------------------- + def __init__(self, data_file): + + msg = _("Data file of forge modules cache is a directory") + super(DatafileIsDirError, self).__init__( + errno.EISDIR, msg, str(data_file)) + + +# ============================================================================= +class DatafileAccessError(ForgeModuleDictError, IOError): + + # ------------------------------------------------------------------------- + def __init__(self, data_file): + + msg = _("Data file of forge modules cache is not readable") + super(DatafileAccessError, self).__init__( + errno.EACCES, msg, str(data_file)) + + # ============================================================================= class ParentNotExistingError(ForgeModuleDictError, IOError): @@ -106,6 +139,14 @@ class ForgeModuleDict(MutableMapping, FbBaseObject): default_data_dir = root_path / 'var' / 'lib' / 'webhooks' default_data_file = Path('forge-modules.js') default_json_indent = 4 + default_charset = 'utf-8' + + open_args = {} + if six.PY3: + open_args = { + 'encoding': default_charset, + 'errors': 'surrogateescape', + } # ------------------------------------------------------------------------- # __init__() method required to create instance from class. @@ -241,6 +282,8 @@ class ForgeModuleDict(MutableMapping, FbBaseObject): res['json_indent'] = self.json_indent res['simulate'] = self.simulate res['sort_by_name'] = self.sort_by_name + res['default_charset'] = self.default_charset + res['open_args'] = self.open_args res['items'] = {} res['keys'] = [] for full_name in self.keys(): @@ -480,6 +523,25 @@ class ForgeModuleDict(MutableMapping, FbBaseObject): res[full_name] = self._map[full_name].to_data() return res + # ------------------------------------------------------------------------- + def from_data(self, data): + """Converting the given dict (read from a cache file) and re-instantiate + the appropriate module infos.""" + + if self.verbose > 1: + LOG.debug(_("Converting Python objects into a dict of {} objects.").format( + 'ForgeModuleInfo')) + + self.clear() + for full_name in data.keys(): + mdata = data[full_name] + mod = ForgeModuleInfo.from_data( + mdata, appname=self.appname, verbose=self.verbose, base_dir=self.base_dir) + self.append(mod) + + if self.verbose > 3: + LOG.debug("Re-instantiated forge module infos:\n" + pp(self.as_dict())) + # ------------------------------------------------------------------------- def write_file(self, output_file=None): @@ -544,6 +606,40 @@ class ForgeModuleDict(MutableMapping, FbBaseObject): src=str(tmp_file), tgt=str(output_file))) tmp_file.rename(output_file) + # ------------------------------------------------------------------------- + def read_file(self, data_file=None): + + if data_file is None: + data_file = self.data_file + if not data_file.is_absolute(): + data_file = self.data_dir / self.data_file + data_file = Path(os.path.abspath(str(data_file))) + fd = None + + if not data_file.exists(): + raise DatafileNotExistingError(data_file) + if data_file.is_dir(): + raise DatafileIsDirError(data_file) + if not os.access(str(data_file), os.R_OK): + raise DatafileAccessError(data_file) + + LOG.info(_("Trying to read {!r} ...").format(str(data_file))) + + file_content = None + if six.PY3: + with open(str(data_file), 'r', **self.open_args) as fh: + file_content = fh.read() + else: + with open(str(data_file), 'r') as fh: + file_content = fh.read() + + if self.verbose > 1: + LOG.debug(_("Deserialize file content to Python objects.")) + data = json.loads(file_content) + if self.verbose > 3: + LOG.debug(_("File content as Python objects:") + '\n' + pp(data)) + + self.from_data(data) # ============================================================================= if __name__ == "__main__": diff --git a/lib/webhooks/show_modules.py b/lib/webhooks/show_modules.py index 44dfc79..40cc33a 100644 --- a/lib/webhooks/show_modules.py +++ b/lib/webhooks/show_modules.py @@ -24,6 +24,7 @@ from . import __version__ from .errors import BaseHookError, UncriticalHookError from .base_app import BaseHookApp +from .forge.mod_dict import ForgeModuleDictError from .xlate import XLATOR LOG = logging.getLogger(__name__) @@ -190,6 +191,14 @@ class ShowModulesApp(BaseHookApp): self.print_out("#" * len_title) self.print_out('') + self.init_puppet_environments() + self.collect_local_modules() + + if not self.read_forge_cache(): + self.exit(7) + return + return + module_infos = [] try: module_infos = self.read_cache_file() @@ -198,6 +207,18 @@ class ShowModulesApp(BaseHookApp): else: self.output_modules(module_infos) + # ------------------------------------------------------------------------- + def read_forge_cache(self): + + self.init_forge_module_dict() + try: + self.forge_modules.read_file() + except ForgeModuleDictError as e: + LOG.error(_("Got a {cn} reading input data as JSON: {e}").format( + cn=e.__class__.__name__, e=e)) + return False + return True + # ------------------------------------------------------------------------- def output_modules(self, module_infos):