Add the 'error_data' parameter to the FailAction

This may be useful for a testing purpose if you want to emulate a
action error with data for timeout, retry and the rest of task policies

Change-Id: I679b8338dade284817000670e96ab108481372ae
Signed-off-by: Vitalii Solodilov <mcdkr@yandex.ru>
This commit is contained in:
Vitalii Solodilov 2017-12-17 16:20:36 +04:00 committed by Vitalii Solodilov
parent 3f48e24dc4
commit d2ffecd003
3 changed files with 43 additions and 11 deletions

View File

@ -36,10 +36,10 @@ workflow context variables and thereby implements passing data between workflow
tasks. It's also referred to as Data Flow mechanism. YAQL is a simple but tasks. It's also referred to as Data Flow mechanism. YAQL is a simple but
powerful query language that allows to extract needed information from JSON powerful query language that allows to extract needed information from JSON
structured data. Although Jinja2 is primarily a templating technology, Mistral structured data. Although Jinja2 is primarily a templating technology, Mistral
also uses it for evaluating expression so user have a choice between YAQL and also uses it for evaluating expressions so users have a choice between YAQL and
Jinja2. It's also possible to combine both expression languages within one Jinja2. It's also possible to combine both expression languages within one
workflow definition. The only limitation is that it's impossible to use both workflow definition. The only limitation is that it's impossible to use both
types of expression within one line. As long as there are YAQL and Jinja2 types of expressions within one line. As long as there are YAQL and Jinja2
expressions on different lines of the workflow definition text, it is valid. expressions on different lines of the workflow definition text, it is valid.
It is allowed to use YAQL/Jinja2 in the following sections of It is allowed to use YAQL/Jinja2 in the following sections of
Mistral Workflow Language: Mistral Workflow Language:
@ -941,16 +941,25 @@ a special plugin mechanism. Currently, built-in system actions are:
std.fail std.fail
'''''''' ''''''''
Fail the current workflow. This action can be used to manually set the workflow This action always fails. It can be used to manually fail a workflow task..
state to error.
Example:
.. code-block:: mistral .. code-block:: mistral
manual_fail: wf:
action: std.fail tasks:
manual_fail:
action: std.fail
The action can be passed the `error_data` parameter. This data will be used as
the action return value.
.. code-block:: mistral
wf:
tasks:
manual_fail:
action: std.fail
input: error_data={x:1,y:2}
std.http std.http
'''''''' ''''''''

View File

@ -80,20 +80,31 @@ class AsyncNoOpAction(NoOpAction):
class FailAction(actions.Action): class FailAction(actions.Action):
"""'Always fail' action. """'Always fail' action.
This action just always throws an instance of ActionException. If you pass the `error_data` parameter, this action will be failed and
return this data as error data. Otherwise, the action just throws an
instance of ActionException.
This behavior is useful in a number of cases, especially if we need to This behavior is useful in a number of cases, especially if we need to
test a scenario where some of workflow tasks fail. test a scenario where some of workflow tasks fail.
:param error_data: Action will be failed with this data
""" """
def __init__(self): def __init__(self, error_data=None):
pass self.error_data = error_data
def run(self, context): def run(self, context):
LOG.info('Running fail action.') LOG.info('Running fail action.')
if self.error_data:
return actions.Result(error=self.error_data)
raise exc.ActionException('Fail action expected exception.') raise exc.ActionException('Fail action expected exception.')
def test(self, context): def test(self, context):
if self.error_data:
return actions.Result(error=self.error_data)
raise exc.ActionException('Fail action expected exception.') raise exc.ActionException('Fail action expected exception.')

View File

@ -23,3 +23,15 @@ class FailActionTest(base.BaseTest):
action = std.FailAction() action = std.FailAction()
self.assertRaises(exc.ActionException, action.run, mock.Mock) self.assertRaises(exc.ActionException, action.run, mock.Mock)
def test_fail_with_data(self):
data = {
"x": 1,
"y": 2,
}
action = std.FailAction(error_data=data)
action_result = action.run(context={})
self.assertTrue(action_result.is_error())
self.assertDictEqual(data, action_result.to_dict()['result'])