summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/TemplateHelper.py')
-rw-r--r--src/lib/Bcfg2/Server/Plugins/TemplateHelper.py120
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"}