diff options
author | Jan Cholasta <jcholast@redhat.com> | 2016-06-21 12:07:21 +0200 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2016-06-28 13:30:49 +0200 |
commit | 4284d4fb4da1049c8b9f23d838f963b301aef97d (patch) | |
tree | 26b1a69fc7438923fea34daf50140a1058af1fac /ipalib/plugable.py | |
parent | 79d1f5833547044a7cb2700454cacb2a0976dd5f (diff) | |
download | freeipa-4284d4fb4da1049c8b9f23d838f963b301aef97d.tar.gz freeipa-4284d4fb4da1049c8b9f23d838f963b301aef97d.tar.xz freeipa-4284d4fb4da1049c8b9f23d838f963b301aef97d.zip |
plugable: support plugin versioning
Allow multiple incompatible versions of a plugin using the same name. The
current plugins are assumed to be version '1'.
The unique identifier of plugins was changed from plugin name to plugin
name and version. By default, the highest version available at build time
is used. If the plugin is an unknown remote plugin, version of '1' is used
by default.
https://fedorahosted.org/freeipa/ticket/4427
Reviewed-By: David Kupka <dkupka@redhat.com>
Diffstat (limited to 'ipalib/plugable.py')
-rw-r--r-- | ipalib/plugable.py | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 575e9bd63..d55a8f7a4 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -25,6 +25,7 @@ you are unfamiliar with this Python feature, see http://docs.python.org/ref/sequence-types.html """ +from distutils.version import LooseVersion import operator import sys import threading @@ -47,7 +48,7 @@ from ipapython.ipa_log_manager import ( log_mgr, LOGGING_FORMAT_FILE, LOGGING_FORMAT_STDERR) -from ipapython.version import VERSION, API_VERSION +from ipapython.version import VERSION, API_VERSION, DEFAULT_PLUGINS if six.PY3: unicode = str @@ -125,6 +126,8 @@ class Plugin(ReadOnly): Base class for all plugins. """ + version = '1' + def __init__(self, api): assert api is not None self.__api = api @@ -141,6 +144,12 @@ class Plugin(ReadOnly): name = classproperty(__name_getter) @classmethod + def __full_name_getter(cls): + return '{}/{}'.format(cls.name, cls.version) + + full_name = classproperty(__full_name_getter) + + @classmethod def __bases_getter(cls): return cls.__bases__ @@ -278,6 +287,7 @@ class APINameSpace(collections.Mapping): if self.__plugins is not None and self.__plugins_by_key is not None: return + default_map = self.__api._API__default_map plugins = set() key_dict = self.__plugins_by_key = {} @@ -286,9 +296,12 @@ class APINameSpace(collections.Mapping): continue plugins.add(plugin) key_dict[plugin] = plugin - key_dict[plugin.name] = plugin + key_dict[plugin.name, plugin.version] = plugin + key_dict[plugin.full_name] = plugin + if plugin.version == default_map.get(plugin.name, '1'): + key_dict[plugin.name] = plugin - self.__plugins = sorted(plugins, key=operator.attrgetter('name')) + self.__plugins = sorted(plugins, key=operator.attrgetter('full_name')) def __len__(self): self.__enumerate() @@ -326,6 +339,7 @@ class API(ReadOnly): super(API, self).__init__() self.__plugins = set() self.__plugins_by_key = {} + self.__default_map = {} self.__instances = {} self.__next = {} self.__done = set() @@ -645,7 +659,7 @@ class API(ReadOnly): ) # Check override: - prev = self.__plugins_by_key.get(plugin.name) + prev = self.__plugins_by_key.get(plugin.full_name) if prev: if not override: # Must use override=True to override: @@ -668,7 +682,7 @@ class API(ReadOnly): # The plugin is okay, add to sub_d: self.__plugins.add(plugin) - self.__plugins_by_key[plugin.name] = plugin + self.__plugins_by_key[plugin.full_name] = plugin def finalize(self): """ @@ -680,6 +694,22 @@ class API(ReadOnly): self.__doing('finalize') self.__do_if_not_done('load_plugins') + for plugin in self.__plugins: + if not self.env.validate_api: + if plugin.full_name not in DEFAULT_PLUGINS: + continue + else: + try: + default_version = self.__default_map[plugin.name] + except KeyError: + pass + else: + version = LooseVersion(plugin.version) + default_version = LooseVersion(default_version) + if version < default_version: + continue + self.__default_map[plugin.name] = plugin.version + production_mode = self.is_production_mode() for base in self.bases: |