Merge "Add action context to all action executions"
This commit is contained in:
commit
7f1c1d0808
@ -122,22 +122,9 @@ class Action(object):
|
|||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _create_action_execution(self, input_dict, runtime_ctx, desc=''):
|
def _create_action_execution(self, input_dict, runtime_ctx,
|
||||||
# Assign the action execution ID here to minimize database calls.
|
desc='', action_ex_id=None):
|
||||||
# Otherwise, the input property of the action execution DB object needs
|
action_ex_id = action_ex_id or utils.generate_unicode_uuid()
|
||||||
# to be updated with the action execution ID after the action execution
|
|
||||||
# DB object is created.
|
|
||||||
action_ex_id = utils.generate_unicode_uuid()
|
|
||||||
|
|
||||||
# TODO(rakhmerov): Bad place, we probably need to push action context
|
|
||||||
# to all actions. It's related to
|
|
||||||
# https://blueprints.launchpad.net/mistral/+spec/mistral-custom-actions-api
|
|
||||||
if a_m.has_action_context(
|
|
||||||
self.action_def.action_class,
|
|
||||||
self.action_def.attributes or {}) and self.task_ex:
|
|
||||||
input_dict.update(
|
|
||||||
a_m.get_action_context(self.task_ex, action_ex_id)
|
|
||||||
)
|
|
||||||
|
|
||||||
values = {
|
values = {
|
||||||
'id': action_ex_id,
|
'id': action_ex_id,
|
||||||
@ -212,10 +199,19 @@ class PythonAction(Action):
|
|||||||
def schedule(self, input_dict, target, index=0, desc=''):
|
def schedule(self, input_dict, target, index=0, desc=''):
|
||||||
assert not self.action_ex
|
assert not self.action_ex
|
||||||
|
|
||||||
|
# Assign the action execution ID here to minimize database calls.
|
||||||
|
# Otherwise, the input property of the action execution DB object needs
|
||||||
|
# to be updated with the action execution ID after the action execution
|
||||||
|
# DB object is created.
|
||||||
|
action_ex_id = utils.generate_unicode_uuid()
|
||||||
|
|
||||||
|
self._insert_action_context(action_ex_id, input_dict)
|
||||||
|
|
||||||
self._create_action_execution(
|
self._create_action_execution(
|
||||||
self._prepare_input(input_dict),
|
self._prepare_input(input_dict),
|
||||||
self._prepare_runtime_context(index),
|
self._prepare_runtime_context(index),
|
||||||
desc=desc
|
desc=desc,
|
||||||
|
action_ex_id=action_ex_id
|
||||||
)
|
)
|
||||||
|
|
||||||
scheduler.schedule_call(
|
scheduler.schedule_call(
|
||||||
@ -233,8 +229,21 @@ class PythonAction(Action):
|
|||||||
input_dict = self._prepare_input(input_dict)
|
input_dict = self._prepare_input(input_dict)
|
||||||
runtime_ctx = self._prepare_runtime_context(index)
|
runtime_ctx = self._prepare_runtime_context(index)
|
||||||
|
|
||||||
|
# Assign the action execution ID here to minimize database calls.
|
||||||
|
# Otherwise, the input property of the action execution DB object needs
|
||||||
|
# to be updated with the action execution ID after the action execution
|
||||||
|
# DB object is created.
|
||||||
|
action_ex_id = utils.generate_unicode_uuid()
|
||||||
|
|
||||||
|
self._insert_action_context(action_ex_id, input_dict, save=save)
|
||||||
|
|
||||||
if save:
|
if save:
|
||||||
self._create_action_execution(input_dict, runtime_ctx, desc=desc)
|
self._create_action_execution(
|
||||||
|
input_dict,
|
||||||
|
runtime_ctx,
|
||||||
|
desc=desc,
|
||||||
|
action_ex_id=action_ex_id
|
||||||
|
)
|
||||||
|
|
||||||
result = rpc.get_executor_client().run_action(
|
result = rpc.get_executor_client().run_action(
|
||||||
self.action_ex.id if self.action_ex else None,
|
self.action_ex.id if self.action_ex else None,
|
||||||
@ -286,6 +295,24 @@ class PythonAction(Action):
|
|||||||
"""
|
"""
|
||||||
return {'index': index}
|
return {'index': index}
|
||||||
|
|
||||||
|
def _insert_action_context(self, action_ex_id, input_dict, save=True):
|
||||||
|
"""Template method to prepare action context.
|
||||||
|
|
||||||
|
It inserts the action context in the input if required
|
||||||
|
runtime context.
|
||||||
|
"""
|
||||||
|
# we need to push action context to all actions. It's related to
|
||||||
|
# https://blueprints.launchpad.net/mistral/+spec/mistral-custom-actions-api
|
||||||
|
has_action_context = a_m.has_action_context(
|
||||||
|
self.action_def.action_class,
|
||||||
|
self.action_def.attributes or {}
|
||||||
|
)
|
||||||
|
|
||||||
|
if has_action_context:
|
||||||
|
input_dict.update(
|
||||||
|
a_m.get_action_context(self.task_ex, action_ex_id, save=save)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AdHocAction(PythonAction):
|
class AdHocAction(PythonAction):
|
||||||
"""Ad-hoc action."""
|
"""Ad-hoc action."""
|
||||||
|
@ -147,7 +147,8 @@ def get_action_class(action_full_name):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_action_context(task_ex, action_ex_id):
|
def get_action_context(task_ex, action_ex_id, save=True):
|
||||||
|
if task_ex:
|
||||||
return {
|
return {
|
||||||
_ACTION_CTX_PARAM: {
|
_ACTION_CTX_PARAM: {
|
||||||
'workflow_name': task_ex.workflow_name,
|
'workflow_name': task_ex.workflow_name,
|
||||||
@ -159,6 +160,30 @@ def get_action_context(task_ex, action_ex_id):
|
|||||||
'callback_url': '/v2/action_executions/%s' % action_ex_id
|
'callback_url': '/v2/action_executions/%s' % action_ex_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elif save:
|
||||||
|
return {
|
||||||
|
_ACTION_CTX_PARAM: {
|
||||||
|
'workflow_name': None,
|
||||||
|
'workflow_execution_id': None,
|
||||||
|
'task_id': None,
|
||||||
|
'task_name': None,
|
||||||
|
'task_tags': None,
|
||||||
|
'action_execution_id': action_ex_id,
|
||||||
|
'callback_url': '/v2/action_executions/%s' % action_ex_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
_ACTION_CTX_PARAM: {
|
||||||
|
'workflow_name': None,
|
||||||
|
'workflow_execution_id': None,
|
||||||
|
'task_id': None,
|
||||||
|
'task_name': None,
|
||||||
|
'task_tags': None,
|
||||||
|
'action_execution_id': None,
|
||||||
|
'callback_url': None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_empty_action_context():
|
def get_empty_action_context():
|
||||||
|
@ -91,3 +91,101 @@ class ActionContextTest(base.EngineTestCase):
|
|||||||
proxies=None,
|
proxies=None,
|
||||||
verify=None
|
verify=None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@mock.patch.object(
|
||||||
|
requests, 'request',
|
||||||
|
mock.MagicMock(return_value=test_base.FakeHTTPResponse('', 200, 'OK')))
|
||||||
|
def test_single_async_saved_action_context(self):
|
||||||
|
action_ex = self.engine.start_action(
|
||||||
|
'std.mistral_http',
|
||||||
|
{'url': 'https://wiki.openstack.org/wiki/mistral'},
|
||||||
|
save_result=True
|
||||||
|
)
|
||||||
|
|
||||||
|
action_context = {
|
||||||
|
'action_execution_id': action_ex.id,
|
||||||
|
'callback_url': '/v2/action_executions/%s' % action_ex.id,
|
||||||
|
'task_id': None,
|
||||||
|
'task_name': None,
|
||||||
|
'task_tags': None,
|
||||||
|
'workflow_name': None,
|
||||||
|
'workflow_execution_id': None
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertIn('action_context', action_ex.input)
|
||||||
|
self.assertEqual(action_context, action_ex.input['action_context'])
|
||||||
|
|
||||||
|
@mock.patch.object(
|
||||||
|
requests, 'request',
|
||||||
|
mock.MagicMock(return_value=test_base.FakeHTTPResponse('', 200, 'OK')))
|
||||||
|
def test_single_async_action_context(self):
|
||||||
|
action_ex = self.engine.start_action(
|
||||||
|
'std.mistral_http',
|
||||||
|
{'url': 'https://wiki.openstack.org/wiki/mistral'},
|
||||||
|
save_result=False
|
||||||
|
)
|
||||||
|
|
||||||
|
action_context = {
|
||||||
|
'action_execution_id': action_ex.id,
|
||||||
|
'callback_url': '/v2/action_executions/%s' % action_ex.id,
|
||||||
|
'task_id': None,
|
||||||
|
'task_name': None,
|
||||||
|
'task_tags': None,
|
||||||
|
'workflow_name': None,
|
||||||
|
'workflow_execution_id': None
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertIn('action_context', action_ex.input)
|
||||||
|
self.assertEqual(action_context, action_ex.input['action_context'])
|
||||||
|
|
||||||
|
@mock.patch.object(
|
||||||
|
requests, 'request',
|
||||||
|
mock.MagicMock(return_value=test_base.FakeHTTPResponse('', 200, 'OK')))
|
||||||
|
@mock.patch.object(
|
||||||
|
std_actions.MistralHTTPAction, 'is_sync',
|
||||||
|
mock.MagicMock(return_value=True))
|
||||||
|
def test_single_sync_saved_action_context(self):
|
||||||
|
action_ex = self.engine.start_action(
|
||||||
|
'std.mistral_http',
|
||||||
|
{'url': 'https://wiki.openstack.org/wiki/mistral'},
|
||||||
|
save_result=True
|
||||||
|
)
|
||||||
|
|
||||||
|
action_context = {
|
||||||
|
'action_execution_id': action_ex.id,
|
||||||
|
'callback_url': '/v2/action_executions/%s' % action_ex.id,
|
||||||
|
'task_id': None,
|
||||||
|
'task_name': None,
|
||||||
|
'task_tags': None,
|
||||||
|
'workflow_name': None,
|
||||||
|
'workflow_execution_id': None
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertIn('action_context', action_ex.input)
|
||||||
|
self.assertEqual(action_context, action_ex.input['action_context'])
|
||||||
|
|
||||||
|
@mock.patch.object(
|
||||||
|
requests, 'request',
|
||||||
|
mock.MagicMock(return_value=test_base.FakeHTTPResponse('', 200, 'OK')))
|
||||||
|
@mock.patch.object(
|
||||||
|
std_actions.MistralHTTPAction, 'is_sync',
|
||||||
|
mock.MagicMock(return_value=True))
|
||||||
|
def test_single_sync_action_context(self):
|
||||||
|
action_ex = self.engine.start_action(
|
||||||
|
'std.mistral_http',
|
||||||
|
{'url': 'https://wiki.openstack.org/wiki/mistral'},
|
||||||
|
save_result=False
|
||||||
|
)
|
||||||
|
|
||||||
|
action_context = {
|
||||||
|
'action_execution_id': None,
|
||||||
|
'callback_url': None,
|
||||||
|
'task_id': None,
|
||||||
|
'task_name': None,
|
||||||
|
'task_tags': None,
|
||||||
|
'workflow_name': None,
|
||||||
|
'workflow_execution_id': None
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertIn('action_context', action_ex.input)
|
||||||
|
self.assertEqual(action_context, action_ex.input['action_context'])
|
||||||
|
Loading…
Reference in New Issue
Block a user