diff --git a/aminator/config.py b/aminator/config.py index 31e993c2..6ed757c9 100644 --- a/aminator/config.py +++ b/aminator/config.py @@ -207,6 +207,28 @@ 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, config): + if not hasattr(config.context, "plugin_override"): + return + + config_dict = {} + for override in config.context.plugin_override: + 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 +257,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..af5bcd05 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) + 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: