diff options
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/TemplateHelper.py')
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/TemplateHelper.py | 120 |
1 files changed, 85 insertions, 35 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py index 2c0ee03e0..6d92bb530 100644 --- a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py +++ b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py @@ -1,26 +1,23 @@ import re import imp import sys +import glob import logging +import Bcfg2.Server.Lint import Bcfg2.Server.Plugin logger = logging.getLogger(__name__) -class HelperModule(Bcfg2.Server.Plugin.SpecificData): - _module_name_re = re.compile(r'([^/]+?)\.py') - - def __init__(self, name, specific, encoding): - Bcfg2.Server.Plugin.SpecificData.__init__(self, name, specific, - encoding) - match = self._module_name_re.search(self.name) - if match: - self._module_name = match.group(1) - else: - self._module_name = name +module_pattern = r'(?P<filename>(?P<module>[^\/]+)\.py)$' +module_re = re.compile(module_pattern) + +class HelperModule(Bcfg2.Server.Plugin.FileBacked): + def __init__(self, name, fam=None): + Bcfg2.Server.Plugin.FileBacked.__init__(self, name, fam=fam) + self._module_name = module_re.search(self.name).group('module') self._attrs = [] - def handle_event(self, event): - Bcfg2.Server.Plugin.SpecificData.handle_event(self, event) + def Index(self): try: module = imp.load_source(self._module_name, self.name) except: @@ -34,32 +31,29 @@ class HelperModule(Bcfg2.Server.Plugin.SpecificData): self.name) return + newattrs = [] for sym in module.__export__: if sym not in self._attrs and hasattr(self, sym): logger.warning("TemplateHelper: %s: %s is a reserved keyword, " "skipping export" % (self.name, sym)) - setattr(self, sym, getattr(module, sym)) + continue + try: + setattr(self, sym, getattr(module, sym)) + newattrs.append(sym) + except AttributeError: + logger.warning("TemplateHelper: %s: %s exports %s, but has no " + "such attribute" % (self.name, sym)) # remove old exports - for sym in set(self._attrs) - set(module.__export__): + for sym in set(self._attrs) - set(newattrs): delattr(self, sym) - self._attrs = module.__export__ + self._attrs = newattrs -class HelperSet(Bcfg2.Server.Plugin.EntrySet): +class HelperSet(Bcfg2.Server.Plugin.DirectoryBacked): ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\.py[co])$") - - def __init__(self, path, fam, encoding, plugin_name): - fpattern = '[0-9A-Za-z_\-]+\.py' - self.plugin_name = plugin_name - Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, - HelperModule, encoding) - fam.AddMonitor(path, self) - - def HandleEvent(self, event): - if (event.filename != self.path and - not self.ignore.match(event.filename)): - return self.handle_event(event) + patterns = module_re + __child__ = HelperModule class TemplateHelper(Bcfg2.Server.Plugin.Plugin, @@ -71,13 +65,69 @@ class TemplateHelper(Bcfg2.Server.Plugin.Plugin, def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Connector.__init__(self) + self.helpers = HelperSet(self.data, core.fam) + + def get_additional_data(self, _): + return dict([(h._module_name, h) + for h in self.helpers.entries.values()]) + + +class TemplateHelperLint(Bcfg2.Server.Lint.ServerlessPlugin): + """ find duplicate Pkgmgr entries with the same priority """ + def __init__(self, *args, **kwargs): + Bcfg2.Server.Lint.ServerlessPlugin.__init__(self, *args, **kwargs) + hm = HelperModule("foo.py") + self.reserved_keywords = dir(hm) + + def Run(self): + for fname in os.listdir(os.path.join(self.config['repo'], + "TemplateHelper")): + helper = os.path.join(self.config['repo'], "TemplateHelper", + fname) + if not module_re.search(helper) or not self.HandlesFile(helper): + continue + self.check_helper(helper) + + def check_helper(self, helper): + module_name = module_re.search(helper).group(1) try: - self.helpers = HelperSet(self.data, core.fam, core.encoding, - self.name) + module = imp.load_source(module_name, helper) except: - raise Bcfg2.Server.Plugin.PluginInitError + err = sys.exc_info()[1] + self.LintError("templatehelper-import-error", + "Failed to import %s: %s" % + (helper, err)) + return - def get_additional_data(self, metadata): - return dict([(h._module_name, h) - for h in list(self.helpers.entries.values())]) + if not hasattr(module, "__export__"): + self.LintError("templatehelper-no-export", + "%s has no __export__ list" % helper) + return + elif not isinstance(module.__export__, list): + self.LintError("templatehelper-nonlist-export", + "__export__ is not a list in %s" % helper) + return + + for sym in module.__export__: + if not hasattr(module, sym): + self.LintError("templatehelper-nonexistent-export", + "%s: exported symbol %s does not exist" % + (helper, sym)) + elif sym in self.reserved_keywords: + self.LintError("templatehelper-reserved-export", + "%s: exported symbol %s is reserved" % + (helper, sym)) + elif sym.startswith("_"): + self.LintError("templatehelper-underscore-export", + "%s: exported symbol %s starts with underscore" % + (helper, sym)) + + @classmethod + def Errors(cls): + return {"templatehelper-import-error":"error", + "templatehelper-no-export":"error", + "templatehelper-nonlist-export":"error", + "templatehelper-nonexistent-export":"error", + "templatehelper-reserved-export":"error", + "templatehelper-underscore-export":"warning"} |