From bf59efca2d92a9ebff282569ef2fef2939a22920 Mon Sep 17 00:00:00 2001 From: Andrew Matheny Date: Thu, 26 Sep 2013 19:28:27 +0000 Subject: [PATCH 1/3] Initial attempt at plugin overrides --- aminator/config.py | 21 +++++++++++++++++++++ aminator/core.py | 13 +++++++++---- aminator/plugins/__init__.py | 10 +++++++++- aminator/plugins/base.py | 11 +++++++++-- aminator/plugins/blockdevice/linux.py | 4 ++-- aminator/plugins/blockdevice/virtio.py | 4 ++-- aminator/plugins/cloud/ec2.py | 8 ++++---- 7 files changed, 56 insertions(+), 15 deletions(-) diff --git a/aminator/config.py b/aminator/config.py index 31e993c2..8022b5a0 100644 --- a/aminator/config.py +++ b/aminator/config.py @@ -207,6 +207,25 @@ def from_defaults(cls, namespace=None, name=None, *args, **kwargs): resource_path = os.path.join(RSRC_DEFAULT_CONF_DIR, resource_file) return super(PluginConfig, cls).from_defaults(namespace=namespace, name=resource_path, *args, **kwargs) + @staticmethod + def set_overrides(plugins, overrides): + config_dict = {} + for override in overrides: + split = override.split('=', 1) + value = split[1].strip('"\'') + plugin_name = ".".join(split[0].split(".")[0:-1]) + prop = split[0].split(".")[-1] + log.debug("setting plugin config for %s to %s for %s" % (plugin_name, value, prop)) + if plugin_name not in config_dict: config_dict[plugin_name] = {} + config_dict[plugin_name][prop] = value + + for plugin in plugins: + if plugin.obj.full_name in config_dict: + plugin.obj.override_config(config_dict[plugin.obj.full_name]) + #for attr in dir(): + # log.debug("plugin.obj.%s = %s" % (attr, getattr(plugin.obj._config, attr))) + #break + class Argparser(object): """ Argument parser class. Holds the keys to argparse """ @@ -235,6 +254,8 @@ def add_base_arguments(parser, config): help='For Debugging. Preserve build chroot on error') parser.add_config_arg('--verify-https', action='store_true', config=config.context, help='Specify if one wishes for plugins to verify SSL certs when hitting https URLs') + parser.add_config_arg('-o', '--plugin-override', action='append', config=config.context, + help='Override a plugin option typically stored in it\' YAML config') parser.add_argument('--version', action='version', version='%(prog)s {0}'.format(aminator.__version__)) parser.add_argument('--debug', action='store_true', help='Verbose debugging output') diff --git a/aminator/core.py b/aminator/core.py index 456c58d9..1743500b 100644 --- a/aminator/core.py +++ b/aminator/core.py @@ -26,7 +26,7 @@ import logging import os -from aminator.config import init_defaults, configure_datetime_logfile +from aminator.config import init_defaults, configure_datetime_logfile, PluginConfig from aminator.environment import Environment from aminator.plugins import PluginManager from aminator.util.linux import mkdir_p @@ -43,14 +43,19 @@ def __init__(self, config=None, parser=None, plugin_manager=PluginManager, envir config, parser = init_defaults(debug=debug) self.config = config self.parser = parser - log.debug('Configuration loaded') if not envname: envname = self.config.environments.default - self.plugin_manager = plugin_manager(self.config, self.parser, plugins=self.config.environments[envname]) - log.debug('Plugins loaded') + plugin_entries = self.config.environments[envname] + self.plugin_manager = plugin_manager(self.config, self.parser, plugins=plugin_entries) + log.debug('Configuration loaded') self.parser.parse_args() log.debug('Args parsed') + plugins = [self.plugin_manager.find_by_kind(entry, plugin_entries[entry]) for entry in plugin_entries] + PluginConfig.set_overrides(plugins, self.config.context.plugin_override) + self.plugin_manager.configure_plugins(self.config, plugin_entries) + log.debug('Plugins loaded') + log.debug('Creating initial folder structure if needed') mkdir_p(self.config.log_root) mkdir_p(os.path.join(self.config.aminator_root, self.config.lock_dir)) diff --git a/aminator/plugins/__init__.py b/aminator/plugins/__init__.py index 8c111746..e0925480 100644 --- a/aminator/plugins/__init__.py +++ b/aminator/plugins/__init__.py @@ -61,7 +61,15 @@ def __init__(self, config, parser, plugins=None): for name, plugin in self._registry[entry_point].by_name.iteritems(): if not plugins or plugins[entry_point.split('.')[-1]] == name: - plugin.obj.configure(config, parser) + plugin.obj.initialize(config, parser) + log.debug('Initialized plugin {0}.{1}'.format(entry_point, name)) + + def configure_plugins(self, config, plugins=None): + for kind, plugin_info in config.plugins.entry_points.iteritems(): + entry_point = plugin_info.entry_point + for name, plugin in self._registry[entry_point].by_name.iteritems(): + if not plugins or plugins[entry_point.split('.')[-1]] == name: + plugin.obj.configure() log.debug('Loaded plugin {0}.{1}'.format(entry_point, name)) def find_by_entry_point(self, entry_point, name): diff --git a/aminator/plugins/base.py b/aminator/plugins/base.py index 8a58282b..b44a3bb6 100644 --- a/aminator/plugins/base.py +++ b/aminator/plugins/base.py @@ -65,15 +65,21 @@ def name(self): def full_name(self): return '{0}.{1}'.format(self.entry_point, self.name) - def configure(self, config, parser): - """ Configure the plugin and contribute to command line args """ + def configure(self): + """ Configure the plugin""" log.debug("Configuring plugin {0} for entry point {1}".format(self.name, self.entry_point)) + + def initialize(self, config, parser): self._config = config self._parser = parser self.load_plugin_config() if self.enabled: self.add_plugin_args() + def override_config(self, overrides): + key = self.full_name + self._config.plugins[key] = PluginConfig.dict_merge(self._config.plugins[key], overrides) + def add_plugin_args(self): pass @@ -101,3 +107,4 @@ def load_plugin_config(self): PluginConfig.from_files(plugin_conf_files)) # allow plugins to be disabled by configuration. Especially important in cases where command line args conflict self.enabled = self._config.plugins[key].get('enabled', True) + diff --git a/aminator/plugins/blockdevice/linux.py b/aminator/plugins/blockdevice/linux.py index 85b44915..9b69afa2 100644 --- a/aminator/plugins/blockdevice/linux.py +++ b/aminator/plugins/blockdevice/linux.py @@ -43,8 +43,8 @@ class LinuxBlockDevicePlugin(BaseBlockDevicePlugin): _name = 'linux' - def configure(self, config, parser): - super(LinuxBlockDevicePlugin, self).configure(config, parser) + def configure(self): + super(LinuxBlockDevicePlugin, self).configure() block_config = self._config.plugins[self.full_name] diff --git a/aminator/plugins/blockdevice/virtio.py b/aminator/plugins/blockdevice/virtio.py index 94b067e3..82cb02b0 100644 --- a/aminator/plugins/blockdevice/virtio.py +++ b/aminator/plugins/blockdevice/virtio.py @@ -37,8 +37,8 @@ class VirtioBlockDevicePlugin(LinuxBlockDevicePlugin): _name = 'virtio' - def configure(self, config, parser): - super(VirtioBlockDevicePlugin, self).configure(config, parser) + def configure(self): + super(VirtioBlockDevicePlugin, self).configure() block_config = self._config.plugins[self.full_name] diff --git a/aminator/plugins/cloud/ec2.py b/aminator/plugins/cloud/ec2.py index a5fef190..5645f536 100644 --- a/aminator/plugins/cloud/ec2.py +++ b/aminator/plugins/cloud/ec2.py @@ -100,13 +100,13 @@ def add_plugin_args(self, *args, **kwargs): cloud.add_argument('--boto-debug', dest='boto_debug', help='Boto debug output', action=conf_action(config=context.cloud, action='store_true')) - def configure(self, config, parser): - super(EC2CloudPlugin, self).configure(config, parser) - host = config.context.web_log.get('host', False) + def configure(self): + super(EC2CloudPlugin, self).configure() + host = self._config.context.web_log.get('host', False) if not host: md = get_instance_metadata() pub, ipv4 = 'public-hostname', 'local-ipv4' - config.context.web_log['host'] = md[pub] if pub in md else md[ipv4] + self._config.context.web_log['host'] = md[pub] if pub in md else md[ipv4] def connect(self, **kwargs): if self._connection: From f925d0d2c725cd6882d1880dbb4c4394bdcfba8c Mon Sep 17 00:00:00 2001 From: Andrew Matheny Date: Thu, 26 Sep 2013 19:59:41 +0000 Subject: [PATCH 2/3] Fixes bug when no overrides are specified --- aminator/config.py | 7 +++++-- aminator/core.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/aminator/config.py b/aminator/config.py index 8022b5a0..d5766193 100644 --- a/aminator/config.py +++ b/aminator/config.py @@ -208,9 +208,12 @@ def from_defaults(cls, namespace=None, name=None, *args, **kwargs): return super(PluginConfig, cls).from_defaults(namespace=namespace, name=resource_path, *args, **kwargs) @staticmethod - def set_overrides(plugins, overrides): + def set_overrides(plugins, config): + if not hasattr(config.context, "plugin_overrides"): + return + config_dict = {} - for override in overrides: + for override in config.context.plugin_overrides: split = override.split('=', 1) value = split[1].strip('"\'') plugin_name = ".".join(split[0].split(".")[0:-1]) diff --git a/aminator/core.py b/aminator/core.py index 1743500b..af5bcd05 100644 --- a/aminator/core.py +++ b/aminator/core.py @@ -52,7 +52,7 @@ def __init__(self, config=None, parser=None, plugin_manager=PluginManager, envir log.debug('Args parsed') plugins = [self.plugin_manager.find_by_kind(entry, plugin_entries[entry]) for entry in plugin_entries] - PluginConfig.set_overrides(plugins, self.config.context.plugin_override) + PluginConfig.set_overrides(plugins, self.config) self.plugin_manager.configure_plugins(self.config, plugin_entries) log.debug('Plugins loaded') From cfdcef9be03415dbac1a3a6135b520567242ae0c Mon Sep 17 00:00:00 2001 From: Andrew Matheny Date: Thu, 26 Sep 2013 20:27:54 +0000 Subject: [PATCH 3/3] Fix typo in last commit --- aminator/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aminator/config.py b/aminator/config.py index d5766193..6ed757c9 100644 --- a/aminator/config.py +++ b/aminator/config.py @@ -209,11 +209,11 @@ def from_defaults(cls, namespace=None, name=None, *args, **kwargs): @staticmethod def set_overrides(plugins, config): - if not hasattr(config.context, "plugin_overrides"): + if not hasattr(config.context, "plugin_override"): return config_dict = {} - for override in config.context.plugin_overrides: + for override in config.context.plugin_override: split = override.split('=', 1) value = split[1].strip('"\'') plugin_name = ".".join(split[0].split(".")[0:-1])