From 91237c2baa4b7e1076678c98a6884fe87d2aa724 Mon Sep 17 00:00:00 2001 From: Istvan Imre Date: Wed, 15 Feb 2017 12:34:14 +0100 Subject: [PATCH] External OpenStack action mapping file support Release note and command line parameter added. From now it is optional to list openstack modules in mapping file which you would not include into supported action set. Change-Id: I5ab01395c507fc857dca7cf08ab344a07def0dcf --- .../openstack/action_generator/base.py | 8 +-- mistral/config.py | 12 +++++ mistral/db/sqlalchemy/migration/cli.py | 2 + .../resources/openstack/test_mapping.json | 6 +++ .../unit/actions/openstack/test_generator.py | 51 +++++++++++++++++++ ...tion_mapping_support-5cec5d9d5192feb7.yaml | 9 ++++ tools/sync_db.py | 3 +- 7 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 mistral/tests/resources/openstack/test_mapping.json create mode 100644 releasenotes/notes/external_openstack_action_mapping_support-5cec5d9d5192feb7.yaml diff --git a/mistral/actions/openstack/action_generator/base.py b/mistral/actions/openstack/action_generator/base.py index 49b41476..0995a017 100644 --- a/mistral/actions/openstack/action_generator/base.py +++ b/mistral/actions/openstack/action_generator/base.py @@ -23,12 +23,8 @@ from mistral.actions import action_generator from mistral.utils import inspect_utils as i_u from mistral import version -os_actions_mapping_path = cfg.StrOpt('openstack_actions_mapping_path', - default='actions/openstack/mapping.json') - - CONF = cfg.CONF -CONF.register_opt(os_actions_mapping_path) + LOG = logging.getLogger(__name__) @@ -84,7 +80,7 @@ class OpenStackActionGenerator(action_generator.ActionGenerator): @classmethod def create_actions(cls): mapping = get_mapping() - method_dict = mapping[cls.action_namespace] + method_dict = mapping.get(cls.action_namespace, {}) action_classes = [] diff --git a/mistral/config.py b/mistral/config.py index 4ed2f536..21c4d3eb 100644 --- a/mistral/config.py +++ b/mistral/config.py @@ -259,6 +259,18 @@ keycloak_oidc_opts = [ ) ] +# note: this command line option is used only from sync_db and +# mistral-db-manage +os_actions_mapping_path = cfg.StrOpt( + 'openstack_actions_mapping_path', + short='m', + metavar='MAPPING_PATH', + default='actions/openstack/mapping.json', + help='Path to openstack action mapping json file.' + 'It could be relative to mistral package ' + 'directory or absolute.' +) + CONF = cfg.CONF API_GROUP = 'api' diff --git a/mistral/db/sqlalchemy/migration/cli.py b/mistral/db/sqlalchemy/migration/cli.py index e7f1e3cb..172c0475 100644 --- a/mistral/db/sqlalchemy/migration/cli.py +++ b/mistral/db/sqlalchemy/migration/cli.py @@ -23,6 +23,7 @@ from oslo_utils import importutils import six import sys +from mistral import config from mistral.services import action_manager from mistral.services import workflows @@ -113,6 +114,7 @@ command_opt = cfg.SubCommandOpt('command', handler=add_command_parsers) CONF.register_cli_opt(command_opt) +CONF.register_cli_opt(config.os_actions_mapping_path) def main(): diff --git a/mistral/tests/resources/openstack/test_mapping.json b/mistral/tests/resources/openstack/test_mapping.json new file mode 100644 index 00000000..b09f0436 --- /dev/null +++ b/mistral/tests/resources/openstack/test_mapping.json @@ -0,0 +1,6 @@ +{ + "_comment": "Mapping OpenStack action namespaces to all its actions. Each action name is mapped to python-client method name in this namespace.", + "nova": { + "servers_get": "servers.get" + } +} diff --git a/mistral/tests/unit/actions/openstack/test_generator.py b/mistral/tests/unit/actions/openstack/test_generator.py index 81b60f73..78a10080 100644 --- a/mistral/tests/unit/actions/openstack/test_generator.py +++ b/mistral/tests/unit/actions/openstack/test_generator.py @@ -10,11 +10,23 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import contextlib +import os + +from oslo_config import cfg from mistral.actions import generator_factory from mistral.actions.openstack import actions +from mistral import config + from mistral.tests.unit import base +ABSOLUTE_TEST_MAPPING_PATH = os.path.realpath( + os.path.join(os.path.dirname(__file__), + "../../../resources/openstack/test_mapping.json") +) + +RELATIVE_TEST_MAPPING_PATH = "tests/resources/openstack/test_mapping.json" MODULE_MAPPING = { 'nova': ['nova.servers_get', actions.NovaAction], @@ -44,6 +56,10 @@ MODULE_MAPPING = { EXTRA_MODULES = ['neutron', 'swift', 'zaqar', 'tacker'] +CONF = cfg.CONF +CONF.register_opt(config.os_actions_mapping_path) + + class GeneratorTest(base.BaseTest): def test_generator(self): for generator_cls in generator_factory.all_generators(): @@ -65,3 +81,38 @@ class GeneratorTest(base.BaseTest): self.assertTrue(issubclass(action['class'], action_cls)) self.assertEqual(method_name, action['class'].client_method_name) + + def test_missing_module_from_mapping(self): + with _patch_openstack_action_mapping_path(RELATIVE_TEST_MAPPING_PATH): + for generator_cls in generator_factory.all_generators(): + action_classes = generator_cls.create_actions() + action_names = [action['name'] for action in action_classes] + + cls = MODULE_MAPPING.get(generator_cls.action_namespace)[1] + if cls == actions.NovaAction: + self.assertEqual(['nova.servers_get'], action_names) + else: + self.assertEqual([], action_names) + + def test_absolute_mapping_path(self): + with _patch_openstack_action_mapping_path(ABSOLUTE_TEST_MAPPING_PATH): + self.assertTrue(os.path.isabs(ABSOLUTE_TEST_MAPPING_PATH), + "Mapping path is relative: %s" % + ABSOLUTE_TEST_MAPPING_PATH) + for generator_cls in generator_factory.all_generators(): + action_classes = generator_cls.create_actions() + action_names = [action['name'] for action in action_classes] + + cls = MODULE_MAPPING.get(generator_cls.action_namespace)[1] + if cls == actions.NovaAction: + self.assertEqual(['nova.servers_get'], action_names) + else: + self.assertEqual([], action_names) + + +@contextlib.contextmanager +def _patch_openstack_action_mapping_path(path): + original_path = CONF.openstack_actions_mapping_path + CONF.set_default("openstack_actions_mapping_path", path) + yield + CONF.set_default("openstack_actions_mapping_path", original_path) diff --git a/releasenotes/notes/external_openstack_action_mapping_support-5cec5d9d5192feb7.yaml b/releasenotes/notes/external_openstack_action_mapping_support-5cec5d9d5192feb7.yaml new file mode 100644 index 00000000..fe99c0a8 --- /dev/null +++ b/releasenotes/notes/external_openstack_action_mapping_support-5cec5d9d5192feb7.yaml @@ -0,0 +1,9 @@ +--- +features: + - External OpenStack action mapping file could be specified at sync_db.sh or + mistral-db-mange script. + For more details see 'sync_db.sh --help' or 'mistral-db-manage --help'. + + - From now it is optional to list openstack modules in mapping file which + you would not include into supported action set. + diff --git a/tools/sync_db.py b/tools/sync_db.py index 1f84db02..3e01a4d4 100644 --- a/tools/sync_db.py +++ b/tools/sync_db.py @@ -23,7 +23,6 @@ from mistral.db.v2 import api as db_api from mistral.services import action_manager from mistral.services import workflows - CONF = cfg.CONF @@ -36,6 +35,8 @@ def main(): for group, opts in keystonemw_opts.list_auth_token_opts(): CONF.register_opts(opts, group=group) + CONF.register_cli_opt(config.os_actions_mapping_path) + config.parse_args() if len(CONF.config_file) == 0: