Make OpenStack related data available in actions
* Make OpenStack related data accessible via context in action DSL without explicitly defining parameters such as auth_token and project_id * Make Openstack data accessible via action_context parameter for new Actions * Unit tests Implements blueprint: mistral-openstack-data-accessible-by-default Change-Id: I9b6802d90c0ac17e0494d2025897ce5cdd02f4ee
This commit is contained in:

committed by
Renat Akhmerov

parent
f814baae8c
commit
e50d1eaa9f
@@ -4,10 +4,10 @@ Namespaces:
|
||||
actions:
|
||||
create-vm:
|
||||
base-parameters:
|
||||
url: '{$.nova_url}/{$.project_id}/servers'
|
||||
url: '{$.nova_url}/{$.openstack.project_id}/servers'
|
||||
method: POST
|
||||
headers:
|
||||
X-Auth-Token: $.auth_token
|
||||
X-Auth-Token: $.openstack.auth_token
|
||||
Content-Type: application/json
|
||||
body:
|
||||
server:
|
||||
@@ -26,7 +26,5 @@ Workflow:
|
||||
image_id: $.image_id
|
||||
flavor_id: $.flavor_id
|
||||
nova_url: $.nova_url
|
||||
project_id: $.project_id
|
||||
auth_token: $.auth_token
|
||||
publish:
|
||||
vm_id: vm_id
|
||||
vm_id: $.vm_id
|
||||
|
@@ -72,15 +72,20 @@ def get_action_class(action_full_name):
|
||||
return ns.get_action_class(arr[1])
|
||||
|
||||
|
||||
def _get_action_context(db_task):
|
||||
return {
|
||||
def _get_action_context(db_task, openstack_context):
|
||||
result = {
|
||||
'workbook_name': db_task['workbook_name'],
|
||||
'execution_id': db_task['execution_id'],
|
||||
'task_id': db_task['id'],
|
||||
'task_name': db_task['name'],
|
||||
'task_tags': db_task['tags']
|
||||
'task_tags': db_task['tags'],
|
||||
}
|
||||
|
||||
if openstack_context:
|
||||
result.update({'openstack': openstack_context})
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _has_action_context_param(action_cls):
|
||||
arg_spec = inspect.getargspec(action_cls.__init__)
|
||||
@@ -88,7 +93,7 @@ def _has_action_context_param(action_cls):
|
||||
return _ACTION_CTX_PARAM in arg_spec.args
|
||||
|
||||
|
||||
def _create_adhoc_action(db_task):
|
||||
def _create_adhoc_action(db_task, openstack_context):
|
||||
task_spec = tasks.TaskSpec(db_task['task_spec'])
|
||||
full_action_name = task_spec.get_full_action_name()
|
||||
|
||||
@@ -108,7 +113,7 @@ def _create_adhoc_action(db_task):
|
||||
|
||||
action_context = None
|
||||
if _has_action_context_param(base_cls):
|
||||
action_context = _get_action_context(db_task)
|
||||
action_context = _get_action_context(db_task, openstack_context)
|
||||
|
||||
if not base_cls:
|
||||
msg = 'Ad-hoc action base class is not registered ' \
|
||||
@@ -130,10 +135,14 @@ def create_action(db_task):
|
||||
|
||||
action_cls = get_action_class(full_action_name)
|
||||
|
||||
openstack_ctx = db_task['in_context'].get('openstack')
|
||||
|
||||
if not action_cls:
|
||||
# If action is not found in registered actions try to find ad-hoc
|
||||
# action definition.
|
||||
action = _create_adhoc_action(db_task)
|
||||
if openstack_ctx is not None:
|
||||
db_task['parameters'].update({'openstack': openstack_ctx})
|
||||
action = _create_adhoc_action(db_task, openstack_ctx)
|
||||
|
||||
if action:
|
||||
return action
|
||||
@@ -145,7 +154,8 @@ def create_action(db_task):
|
||||
action_params = db_task['parameters'] or {}
|
||||
|
||||
if _has_action_context_param(action_cls):
|
||||
action_params[_ACTION_CTX_PARAM] = _get_action_context(db_task)
|
||||
action_params[_ACTION_CTX_PARAM] = _get_action_context(db_task,
|
||||
openstack_ctx)
|
||||
|
||||
try:
|
||||
return action_cls(**action_params)
|
||||
|
@@ -278,7 +278,7 @@ class Engine(object):
|
||||
def _add_variables_to_data_flow_context(cls, context, execution):
|
||||
db_workbook = db_api.workbook_get(execution['workbook_name'])
|
||||
|
||||
data_flow.add_token_to_context(context, db_workbook)
|
||||
data_flow.add_openstack_data_to_context(context, db_workbook)
|
||||
data_flow.add_execution_to_context(context, execution)
|
||||
|
||||
@classmethod
|
||||
|
@@ -82,14 +82,14 @@ def get_outbound_context(task, output=None):
|
||||
return out_context
|
||||
|
||||
|
||||
def add_token_to_context(context, db_workbook):
|
||||
def add_openstack_data_to_context(context, db_workbook):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
if CONF.pecan.auth_enable:
|
||||
workbook_ctx = trusts.create_context(db_workbook)
|
||||
if workbook_ctx:
|
||||
context.update(workbook_ctx.to_dict())
|
||||
context.update({'openstack': workbook_ctx.to_dict()})
|
||||
|
||||
return context
|
||||
|
||||
|
@@ -19,6 +19,7 @@ import json
|
||||
|
||||
from mistral.actions import action_factory as a_f
|
||||
from mistral.actions import std_actions as std
|
||||
from mistral.engine import data_flow
|
||||
from mistral import exceptions
|
||||
from mistral.openstack.common import log as logging
|
||||
from mistral.tests import base
|
||||
@@ -35,6 +36,7 @@ DB_TASK = {
|
||||
'workbook_name': 'my_workbook',
|
||||
'execution_id': '123',
|
||||
'id': '123',
|
||||
'in_context': {},
|
||||
'tags': ['deployment', 'test'],
|
||||
'parameters': {
|
||||
'url': 'http://some.url',
|
||||
@@ -76,6 +78,7 @@ DB_TASK_ADHOC = {
|
||||
'workbook_name': 'my_workbook',
|
||||
'execution_id': '123',
|
||||
'id': '123',
|
||||
'in_context': {},
|
||||
'tags': ['deployment', 'test'],
|
||||
'parameters': {
|
||||
'first': 'Tango',
|
||||
@@ -156,6 +159,59 @@ class ActionFactoryTest(base.BaseTest):
|
||||
self.assertEqual(db_task['id'],
|
||||
headers['Mistral-Task-Id'])
|
||||
|
||||
def test_create_adhoc_action_with_openstack_context(self):
|
||||
db_task = copy.copy(DB_TASK_ADHOC)
|
||||
db_task['action_spec']['output'] = {'res': '{$}'}
|
||||
db_task['in_context'].update({
|
||||
'openstack': {
|
||||
'auth_token': '123',
|
||||
'project_id': '321'
|
||||
}
|
||||
})
|
||||
base_parameters = db_task['action_spec']['base-parameters']
|
||||
base_parameters['output'] = ("{$.openstack.auth_token}"
|
||||
"{$.openstack.project_id}")
|
||||
|
||||
action = a_f.create_action(db_task)
|
||||
|
||||
self.assertEqual({'res': "123321"}, action.run())
|
||||
|
||||
def test_create_adhoc_action_no_openstack_context(self):
|
||||
db_task = copy.copy(DB_TASK_ADHOC)
|
||||
db_task['action_spec']['output'] = {'res': '{$}'}
|
||||
db_task['in_context'].update({
|
||||
'openstack': None
|
||||
})
|
||||
base_parameters = db_task['action_spec']['base-parameters']
|
||||
base_parameters['output'] = "$.openstack.auth_token"
|
||||
|
||||
action = a_f.create_action(db_task)
|
||||
|
||||
self.assertEqual({'res': "$.openstack.auth_token"}, action.run())
|
||||
|
||||
def test_create_no_adhoc_action_with_openstack_context(self):
|
||||
db_task = copy.copy(DB_TASK)
|
||||
db_task['task_spec']['action'] = 'std.http'
|
||||
db_task['in_context'].update({
|
||||
'openstack': {
|
||||
'auth_token': '123',
|
||||
'project_id': '321'
|
||||
}
|
||||
})
|
||||
## In case of no-adhoc action we should evaluate task parameters
|
||||
## to see what we need.
|
||||
task_spec = db_task['task_spec']
|
||||
task_spec['parameters'] = {
|
||||
'url': "http://some/{$.openstack.project_id}/servers",
|
||||
}
|
||||
|
||||
db_task['parameters'] = data_flow.evaluate_task_parameters(
|
||||
db_task, db_task['in_context'])
|
||||
|
||||
action = a_f.create_action(db_task)
|
||||
|
||||
self.assertEqual("http://some/321/servers", action.url)
|
||||
|
||||
def test_get_ssh_action(self):
|
||||
db_task = copy.copy(DB_TASK)
|
||||
db_task['task_spec'] = {
|
||||
@@ -181,7 +237,7 @@ class ActionFactoryTest(base.BaseTest):
|
||||
self.assertEqual("10.0.0.1", action.host)
|
||||
|
||||
def test_adhoc_echo_action(self):
|
||||
db_task = DB_TASK_ADHOC.copy()
|
||||
db_task = copy.copy(DB_TASK_ADHOC)
|
||||
action_spec = db_task['action_spec']
|
||||
|
||||
# With dic-like output formatter.
|
||||
|
@@ -76,6 +76,8 @@ SAMPLE_TASK = {
|
||||
},
|
||||
'namespace': 'MyRest'
|
||||
},
|
||||
'in_context': {},
|
||||
'parameters': {},
|
||||
'task_spec': {
|
||||
'action': 'MyRest.my-action',
|
||||
'name': TASK_NAME},
|
||||
|
@@ -447,11 +447,11 @@ class DataFlowTest(base.EngineTestCase):
|
||||
|
||||
task = self._assert_single_item(tasks, name=task_name)
|
||||
|
||||
context = task['in_context']
|
||||
openstack_context = task['in_context']['openstack']
|
||||
|
||||
self.assertIn("auth_token", context)
|
||||
self.assertEqual(TOKEN, context['auth_token'])
|
||||
self.assertEqual(USER_ID, context["user_id"])
|
||||
self.assertIn("auth_token", openstack_context)
|
||||
self.assertEqual(TOKEN, openstack_context['auth_token'])
|
||||
self.assertEqual(USER_ID, openstack_context["user_id"])
|
||||
|
||||
self.engine.convey_task_result(task['id'], states.SUCCESS, {})
|
||||
|
||||
|
Reference in New Issue
Block a user