summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2013-02-22 04:10:44 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2013-02-22 06:18:10 +0100
commit4b0e3c79152f53656f5ea2b7a00d921a0e7e6596 (patch)
treee47d113bd1d56d440bd56b99a2cd8e2ada151c50
parent37e830a004e3749526eb5aafcec56a1f25ad0b5a (diff)
downloadbcfg2-4b0e3c79152f53656f5ea2b7a00d921a0e7e6596.tar.gz
bcfg2-4b0e3c79152f53656f5ea2b7a00d921a0e7e6596.tar.bz2
bcfg2-4b0e3c79152f53656f5ea2b7a00d921a0e7e6596.zip
Server/Plugins/TemplateHelper: backported TemplateHelper from 1.3debian/1.2.3-5
-rw-r--r--debian/changelog6
-rw-r--r--src/lib/Server/Plugins/TemplateHelper.py154
-rw-r--r--src/lib/Server/Plugins/__init__.py1
3 files changed, 161 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index d06347378..1d0ca0f58 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+bcfg2 (1.2.3-5) unstable; urgency=low
+
+ * Server/Plugins/TemplateHelper: backported TemplateHelper from 1.3
+
+ -- Alexander Sulfrian <alex@spline.inf.fu-berlin.de> Fri, 22 Feb 2013 04:07:35 +0100
+
bcfg2 (1.2.3-4) unstable; urgency=low
* Client: always actions do not modify hosts
diff --git a/src/lib/Server/Plugins/TemplateHelper.py b/src/lib/Server/Plugins/TemplateHelper.py
new file mode 100644
index 000000000..3cdedb0ea
--- /dev/null
+++ b/src/lib/Server/Plugins/TemplateHelper.py
@@ -0,0 +1,154 @@
+""" A plugin to provide helper classes and functions to templates """
+
+import re
+import imp
+import sys
+import logging
+import Bcfg2.Server.Lint
+import Bcfg2.Server.Plugin
+
+LOGGER = logging.getLogger(__name__)
+
+MODULE_RE = re.compile(r'(?P<filename>(?P<module>[^\/]+)\.py)$')
+
+
+def safe_module_name(module):
+ """ Munge the name of a TemplateHelper module to avoid collisions
+ with other Python modules. E.g., if someone has a helper named
+ 'ldap.py', it should not be added to ``sys.modules`` as ``ldap``,
+ but rather as something more obscure. """
+ return '__TemplateHelper_%s' % module
+
+
+class HelperModule(object):
+ """ Representation of a TemplateHelper module """
+
+ def __init__(self, name, fam=None):
+ self.name = name
+ self.fam = fam
+
+ #: The name of the module as used by get_additional_data().
+ #: the name of the file with .py stripped off.
+ self._module_name = MODULE_RE.search(self.name).group('module')
+
+ #: The attributes exported by this module
+ self._attrs = []
+
+ def HandleEvent(self, event=None):
+ """ HandleEvent is called whenever the FAM registers an event.
+
+ :param event: The event object
+ :type event: Bcfg2.Server.FileMonitor.Event
+ :returns: None
+ """
+ if event and event.code2str() not in ['exists', 'changed', 'created']:
+ return
+
+ try:
+ module = imp.load_source(safe_module_name(self._module_name),
+ self.name)
+ except: # pylint: disable=W0702
+ err = sys.exc_info()[1]
+ LOGGER.error("TemplateHelper: Failed to import %s: %s" %
+ (self.name, err))
+ return
+
+ if not hasattr(module, "__export__"):
+ LOGGER.error("TemplateHelper: %s has no __export__ list" %
+ 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))
+ continue
+ try:
+ setattr(self, sym, getattr(module, sym))
+ newattrs.append(sym)
+ except AttributeError:
+ LOGGER.warning("TemplateHelper: %s exports %s, but has no "
+ "such attribute" % (self.name, sym))
+ # remove old exports
+ for sym in set(self._attrs) - set(newattrs):
+ delattr(self, sym)
+
+ self._attrs = newattrs
+
+
+class TemplateHelper(Bcfg2.Server.Plugin.Plugin,
+ Bcfg2.Server.Plugin.Connector,
+ Bcfg2.Server.Plugin.DirectoryBacked):
+ """ A plugin to provide helper classes and functions to templates """
+ name = 'TemplateHelper'
+ __author__ = 'chris.a.st.pierre@gmail.com'
+ ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\.py[co])$")
+ patterns = MODULE_RE
+ __child__ = HelperModule
+
+ def __init__(self, core, datastore):
+ Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
+ Bcfg2.Server.Plugin.Connector.__init__(self)
+ Bcfg2.Server.Plugin.DirectoryBacked.__init__(self, self.data, core.fam)
+
+ def get_additional_data(self, _):
+ return dict([(h._module_name, h) # pylint: disable=W0212
+ for h in self.entries.values()])
+
+
+class TemplateHelperLint(Bcfg2.Server.Lint.ServerPlugin):
+ """ find duplicate Pkgmgr entries with the same priority """
+ def __init__(self, *args, **kwargs):
+ Bcfg2.Server.Lint.ServerPlugin.__init__(self, *args, **kwargs)
+ self.reserved_keywords = dir(HelperModule("foo.py"))
+
+ def Run(self):
+ for helper in self.core.plugins['TemplateHelper'].entries.values():
+ if self.HandlesFile(helper):
+ self.check_helper(helper.name)
+
+ def check_helper(self, helper):
+ """ check a helper module for export errors """
+ module_name = MODULE_RE.search(helper).group(1)
+
+ try:
+ module = imp.load_source(safe_module_name(module_name), helper)
+ except: # pylint: disable=W0702
+ err = sys.exc_info()[1]
+ self.LintError("templatehelper-import-error",
+ "Failed to import %s: %s" %
+ (helper, err))
+ return
+
+ 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"}
diff --git a/src/lib/Server/Plugins/__init__.py b/src/lib/Server/Plugins/__init__.py
index c69c37452..b39793290 100644
--- a/src/lib/Server/Plugins/__init__.py
+++ b/src/lib/Server/Plugins/__init__.py
@@ -29,6 +29,7 @@ __all__ = [
'Svcmgr',
'Svn',
'TCheetah',
+ 'TemplateHelper',
'Trigger',
'SGenshi',
'TGenshi',