From a57d26e10aac0b8d539243f9919a18b2fb929f69 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Thu, 30 Oct 2014 03:30:07 +0100 Subject: Lint: fix default value for lint_plugins This is a bit tricky because we need the enabled server plugins for the default value. To have these available before parsing lint_plugins the server plugins needs to be parsed during early parsing mode. Additional there are lint plugins that has no matching server plugin. To identify them, this adds a reference from the lint plutins to the name of the matching server plugins in the member variable __serverplugin__. If this variable is None the plugin is always used. If a lint plugin could not be imported (maybe because of a missing dependency) the plugin is ignored and not considered as a default value. --- src/lib/Bcfg2/Server/Lint/__init__.py | 71 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 30 deletions(-) (limited to 'src/lib/Bcfg2/Server/Lint/__init__.py') diff --git a/src/lib/Bcfg2/Server/Lint/__init__.py b/src/lib/Bcfg2/Server/Lint/__init__.py index 1358a46fb..526bdf159 100644 --- a/src/lib/Bcfg2/Server/Lint/__init__.py +++ b/src/lib/Bcfg2/Server/Lint/__init__.py @@ -14,6 +14,7 @@ import Bcfg2.Options import Bcfg2.Server.Core import Bcfg2.Server.Plugins from Bcfg2.Compat import walk_packages +from Bcfg2.Options import _debug def _ioctl_GWINSZ(fd): # pylint: disable=C0103 @@ -48,6 +49,11 @@ def get_termsize(): class Plugin(object): """ Base class for all bcfg2-lint plugins """ + #: Name of the matching server plugin or None if there is no + #: matching one. If this is None the lint plugin will only loaded + #: by default if the matching server plugin is enabled, too. + __serverplugin__ = None + options = [Bcfg2.Options.Common.repository] def __init__(self, errorhandler=None, files=None): @@ -291,19 +297,41 @@ class ServerPlugin(Plugin): # pylint: disable=W0223 class LintPluginAction(Bcfg2.Options.ComponentAction): - """ We want to load all lint plugins that pertain to server - plugins. In order to do this, we hijack the __call__() method of - this action and add all of the server plugins on the fly """ - + """ Option parser action to load lint plugins """ bases = ['Bcfg2.Server.Lint'] - def __call__(self, parser, namespace, values, option_string=None): - plugins = getattr(Bcfg2.Options.setup, "plugins", []) - for lint_plugin in walk_packages(path=__path__): - if lint_plugin[1] in plugins: - values.append(lint_plugin[1]) - Bcfg2.Options.ComponentAction.__call__(self, parser, namespace, values, - option_string) + +class LintPluginOption(Bcfg2.Options.Option): + """ Option class for the lint_plugins """ + + def early_parsing_hook(self, namespace): + """ + We want a usefull default for the enabled lint plugins. + Therfore we use all importable plugins, that either pertain + with enabled server plugins or that has no matching plugin. + """ + + plugins = [p.__name__ for p in namespace.plugins] + for loader, name, _is_pkg in walk_packages(path=__path__): + try: + module = loader.find_module(name).load_module(name) + plugin = getattr(module, name) + if plugin.__serverplugin__ is None or \ + plugin.__serverplugin__ in plugins: + _debug("Automatically adding lint plugin %s" % + plugin.__name__) + self.default.append(plugin.__name__) + except ImportError: + pass + + +class _EarlyOptions(object): + """ We need the server.plugins options in an early parsing hook + for determining the default value for the lint_plugins. So we + create a component that is parsed before the other options. """ + + parse_first = True + options = [Bcfg2.Options.Common.plugins] class CLI(object): @@ -313,7 +341,7 @@ class CLI(object): '--lint-config', default='/etc/bcfg2-lint.conf', action=Bcfg2.Options.ConfigFileAction, help='Specify bcfg2-lint configuration file'), - Bcfg2.Options.Option( + LintPluginOption( "--lint-plugins", cf=('lint', 'plugins'), default=[], type=Bcfg2.Options.Types.comma_list, action=LintPluginAction, help='bcfg2-lint plugin list'), @@ -328,28 +356,11 @@ class CLI(object): def __init__(self): parser = Bcfg2.Options.get_parser( description="Manage a running Bcfg2 server", - components=[self]) + components=[self, _EarlyOptions]) parser.parse() self.logger = logging.getLogger(parser.prog) - # automatically add Lint plugins for loaded server plugins - for plugin in Bcfg2.Options.setup.plugins: - try: - Bcfg2.Options.setup.lint_plugins.append( - getattr( - __import__("Bcfg2.Server.Lint.%s" % plugin.__name__, - fromlist=[plugin.__name__]), - plugin.__name__)) - self.logger.debug("Automatically adding lint plugin %s" % - plugin.__name__) - except ImportError: - # no lint plugin for this server plugin - self.logger.debug("No lint plugin for %s" % plugin.__name__) - except AttributeError: - self.logger.error("Failed to load plugin %s: %s" % - (plugin.__name__, sys.exc_info()[1])) - self.logger.debug("Running lint with plugins: %s" % [p.__name__ for p in Bcfg2.Options.setup.lint_plugins]) -- cgit v1.2.3-1-g7c22