From 4284d4fb4da1049c8b9f23d838f963b301aef97d Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Tue, 21 Jun 2016 12:07:21 +0200 Subject: 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 --- makeapi | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'makeapi') diff --git a/makeapi b/makeapi index 8e66eec3c..1b7c958d4 100755 --- a/makeapi +++ b/makeapi @@ -26,6 +26,7 @@ from __future__ import print_function import importlib +import itertools import sys import os import re @@ -246,7 +247,7 @@ def make_api(): """ fd = open(API_FILE, 'w') for cmd in api.Command(): - fd.write('command: %s\n' % cmd.name) + fd.write('command: %s\n' % cmd.full_name) fd.write('args: %d,%d,%d\n' % (len(cmd.args), len(cmd.options), len(cmd.output))) for a in cmd.args(): fd.write('arg: %s\n' % param_repr(a)) @@ -254,6 +255,14 @@ def make_api(): fd.write('option: %s\n' % param_repr(o)) for o in sorted(cmd.output(), key=operator.attrgetter('name')): fd.write('output: %s\n' % param_repr(o)) + for plugin in sorted(itertools.chain(api.Command(), api.Object()), + key=operator.attrgetter('full_name')): + try: + default_plugin = api.Command[plugin.name] + except KeyError: + default_plugin = api.Object[plugin.name] + if plugin is default_plugin: + fd.write('default: %s\n' % plugin.full_name) for name, version in sorted( capabilities.items(), key=operator.itemgetter(1, 0)): fd.write('capability: %s %s\n' % (name, version)) @@ -335,6 +344,7 @@ def validate_api(): # First run through the file and compare it to the API existing_cmds = [] existing_capabilities = set() + existing_defaults = set() cmd = None for line in lines: line = line.strip() @@ -417,6 +427,33 @@ def validate_api(): output = find_name(line) print("Option '%s' in command '%s' in API file not found" % (output, name)) rval |= API_FILE_DIFFERENCE + if line.startswith('default:'): + default = line.replace('default: ', '') + existing_defaults.add(default) + default_name = None + for namespace in (api.Command, api.Object): + try: + default_name = namespace[default].name + except KeyError: + pass + else: + break + else: + print("Plugin %s in API file, not in ipalib" % default) + rval |= API_FILE_DIFFERENCE + if default_name is not None: + try: + expected_default = namespace[default_name].full_name + except KeyError: + print("Default version of plugin %s in API file not " + "found" % default_name) + rval |= API_FILE_DIFFERENCE + else: + if default != expected_default: + print("Default version of plugin %s in API file " + "doesn't match. Got %s, expected %s." % + (default_name, default, expected_default)) + rval |= API_FILE_DIFFERENCE if line.startswith('capability:'): cap, version = line.replace('capability: ', '').split(' ', 1) existing_capabilities.add(cap) @@ -440,10 +477,18 @@ def validate_api(): # Now look for new commands not in the current API for cmd in api.Command(): - if cmd.name not in existing_cmds: - print("Command %s in ipalib, not in API" % cmd.name) + if cmd.full_name not in existing_cmds: + print("Command %s in ipalib, not in API" % cmd.full_name) rval |= API_NEW_COMMAND + for namespace in (api.Command, api.Object): + for plugin in namespace(): + if plugin.name in namespace and namespace[plugin.name] is cmd: + if plugin.full_name not in existing_defaults: + print("Default version of command %s in ipalib, not in " + "API" % plugin.name) + rval |= API_FILE_DIFFERENCE + for cap in capabilities: if cap not in existing_capabilities: print("Capability %s in ipalib, not in API" % cap) -- cgit