Merge "External OpenStack action mapping file support"
This commit is contained in:
commit
58b10ebb44
@ -23,12 +23,8 @@ from mistral.actions import action_generator
|
|||||||
from mistral.utils import inspect_utils as i_u
|
from mistral.utils import inspect_utils as i_u
|
||||||
from mistral import version
|
from mistral import version
|
||||||
|
|
||||||
os_actions_mapping_path = cfg.StrOpt('openstack_actions_mapping_path',
|
|
||||||
default='actions/openstack/mapping.json')
|
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.register_opt(os_actions_mapping_path)
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -84,7 +80,7 @@ class OpenStackActionGenerator(action_generator.ActionGenerator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def create_actions(cls):
|
def create_actions(cls):
|
||||||
mapping = get_mapping()
|
mapping = get_mapping()
|
||||||
method_dict = mapping[cls.action_namespace]
|
method_dict = mapping.get(cls.action_namespace, {})
|
||||||
|
|
||||||
action_classes = []
|
action_classes = []
|
||||||
|
|
||||||
|
@ -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
|
CONF = cfg.CONF
|
||||||
|
|
||||||
API_GROUP = 'api'
|
API_GROUP = 'api'
|
||||||
|
@ -23,6 +23,7 @@ from oslo_utils import importutils
|
|||||||
import six
|
import six
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from mistral import config
|
||||||
from mistral.services import action_manager
|
from mistral.services import action_manager
|
||||||
from mistral.services import workflows
|
from mistral.services import workflows
|
||||||
|
|
||||||
@ -113,6 +114,7 @@ command_opt = cfg.SubCommandOpt('command',
|
|||||||
handler=add_command_parsers)
|
handler=add_command_parsers)
|
||||||
|
|
||||||
CONF.register_cli_opt(command_opt)
|
CONF.register_cli_opt(command_opt)
|
||||||
|
CONF.register_cli_opt(config.os_actions_mapping_path)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
6
mistral/tests/resources/openstack/test_mapping.json
Normal file
6
mistral/tests/resources/openstack/test_mapping.json
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
}
|
@ -10,11 +10,23 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
import contextlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
from mistral.actions import generator_factory
|
from mistral.actions import generator_factory
|
||||||
from mistral.actions.openstack import actions
|
from mistral.actions.openstack import actions
|
||||||
|
from mistral import config
|
||||||
|
|
||||||
from mistral.tests.unit import base
|
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 = {
|
MODULE_MAPPING = {
|
||||||
'nova': ['nova.servers_get', actions.NovaAction],
|
'nova': ['nova.servers_get', actions.NovaAction],
|
||||||
@ -44,6 +56,10 @@ MODULE_MAPPING = {
|
|||||||
EXTRA_MODULES = ['neutron', 'swift', 'zaqar', 'tacker']
|
EXTRA_MODULES = ['neutron', 'swift', 'zaqar', 'tacker']
|
||||||
|
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
CONF.register_opt(config.os_actions_mapping_path)
|
||||||
|
|
||||||
|
|
||||||
class GeneratorTest(base.BaseTest):
|
class GeneratorTest(base.BaseTest):
|
||||||
def test_generator(self):
|
def test_generator(self):
|
||||||
for generator_cls in generator_factory.all_generators():
|
for generator_cls in generator_factory.all_generators():
|
||||||
@ -65,3 +81,38 @@ class GeneratorTest(base.BaseTest):
|
|||||||
|
|
||||||
self.assertTrue(issubclass(action['class'], action_cls))
|
self.assertTrue(issubclass(action['class'], action_cls))
|
||||||
self.assertEqual(method_name, action['class'].client_method_name)
|
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)
|
||||||
|
@ -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.
|
||||||
|
|
@ -23,7 +23,6 @@ from mistral.db.v2 import api as db_api
|
|||||||
from mistral.services import action_manager
|
from mistral.services import action_manager
|
||||||
from mistral.services import workflows
|
from mistral.services import workflows
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +35,8 @@ def main():
|
|||||||
for group, opts in keystonemw_opts.list_auth_token_opts():
|
for group, opts in keystonemw_opts.list_auth_token_opts():
|
||||||
CONF.register_opts(opts, group=group)
|
CONF.register_opts(opts, group=group)
|
||||||
|
|
||||||
|
CONF.register_cli_opt(config.os_actions_mapping_path)
|
||||||
|
|
||||||
config.parse_args()
|
config.parse_args()
|
||||||
|
|
||||||
if len(CONF.config_file) == 0:
|
if len(CONF.config_file) == 0:
|
||||||
|
Loading…
Reference in New Issue
Block a user