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.py153
1 files changed, 58 insertions, 95 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
index db7370f01..047fc062e 100644
--- a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
+++ b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py
@@ -3,11 +3,10 @@
import re
import imp
import sys
-import logging
-import Bcfg2.Server.Lint
-import Bcfg2.Server.Plugin
-
-LOGGER = logging.getLogger(__name__)
+import lxml.etree
+from Bcfg2.Server.Plugin import Plugin, Connector, DirectoryBacked, \
+ TemplateDataProvider, DefaultTemplateDataProvider
+from Bcfg2.Logger import Debuggable
MODULE_RE = re.compile(r'(?P<filename>(?P<module>[^\/]+)\.py)$')
@@ -20,12 +19,12 @@ def safe_module_name(module):
return '__TemplateHelper_%s' % module
-class HelperModule(object):
+class HelperModule(Debuggable):
""" Representation of a TemplateHelper module """
- def __init__(self, name, fam=None):
+ def __init__(self, name):
+ Debuggable.__init__(self)
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.
@@ -34,6 +33,14 @@ class HelperModule(object):
#: The attributes exported by this module
self._attrs = []
+ #: The attributes added to the template namespace by this module
+ self.defaults = []
+
+ default_prov = DefaultTemplateDataProvider()
+ self.reserved_defaults = default_prov.get_template_data(
+ lxml.etree.Element("Path", name="/dummy"),
+ None, None).keys() + ["path"]
+
def HandleEvent(self, event=None):
""" HandleEvent is called whenever the FAM registers an event.
@@ -49,120 +56,76 @@ class HelperModule(object):
self.name)
except: # pylint: disable=W0702
err = sys.exc_info()[1]
- LOGGER.error("TemplateHelper: Failed to import %s: %s" %
- (self.name, err))
+ self.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)
+ self.logger.error("TemplateHelper: %s has no __export__ list" %
+ self.name)
return
newattrs = []
- for sym in module.__export__:
+ for sym in module.__export__ + getattr(module, "__default__", []):
+ if sym in newattrs:
+ # already added to attribute list
+ continue
if sym not in self._attrs and hasattr(self, sym):
- LOGGER.warning("TemplateHelper: %s: %s is a reserved keyword, "
- "skipping export" % (self.name, sym))
+ self.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))
+ self.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
+ self.defaults = []
+ for sym in getattr(module, "__default__", []):
+ if sym in self.reserved_defaults:
+ self.logger.warning(
+ "TemplateHelper: %s: %s is a reserved keyword, not adding "
+ "as default" % (self.name, sym))
+ self.defaults.append(sym)
+
-class TemplateHelper(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Connector,
- Bcfg2.Server.Plugin.DirectoryBacked):
+class TemplateHelper(Plugin, Connector, DirectoryBacked, TemplateDataProvider):
""" A plugin to provide helper classes and functions to templates """
__author__ = 'chris.a.st.pierre@gmail.com'
ignore = re.compile(r'^(\.#.*|.*~|\..*\.(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 __init__(self, core):
+ Plugin.__init__(self, core)
+ Connector.__init__(self)
+ DirectoryBacked.__init__(self, self.data)
+ TemplateDataProvider.__init__(self)
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):
- """ ``bcfg2-lint`` plugin to ensure that all :ref:`TemplateHelper
- <server-plugins-connectors-templatehelper>` modules are valid.
- This can check for:
-
- * A TemplateHelper module that cannot be imported due to syntax or
- other compile-time errors;
- * A TemplateHelper module that does not have an ``__export__``
- attribute, or whose ``__export__`` is not a list;
- * Bogus symbols listed in ``__export__``, including symbols that
- don't exist, that are reserved, or that start with underscores.
- """
-
- 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.name):
- self.check_helper(helper.name)
-
- def check_helper(self, helper):
- """ Check a single helper module.
-
- :param helper: The filename of the helper module
- :type helper: string
- """
- 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"}
+ def get_template_data(self, *_):
+ rv = dict()
+ source = dict()
+ for helper in self.entries.values():
+ for key in helper.defaults:
+ if key not in rv:
+ rv[key] = getattr(helper, key)
+ source[key] = helper
+ else:
+ self.logger.warning(
+ "TemplateHelper: Duplicate default variable %s "
+ "provided by both %s and %s" %
+ (key, helper.name, source[key].name))
+ return rv