Add executions yaql filter

This allows for filtering or executions

Implements: blueprint mistral-workflow-executions-yaql-function
Change-Id: I8d41c662d8659375750b52f7510e9a35f8b42f93
This commit is contained in:
Adriano Petrich 2017-11-24 14:53:10 +00:00 committed by Dougal Matthews
parent 9b356b6486
commit ad733d3112
4 changed files with 270 additions and 1 deletions

View File

@ -1394,6 +1394,68 @@ Execution info is available by **execution()**. It contains
information about execution itself such as **id**, **wf_spec**,
**input** and **start_params**.
Executions function
'''''''''''''''''''
Signature:
**executions(id=null, root_execution_id=null, state=null,
from_time=null, to_time=null)**
Description:
This function allows users to filter all executions by execution id,
root_execution_id ,state and/or created_at time.
Parameters:
#. **id** - If provided will return a list of executions with that id.
Otherwise it will return all executions that match the other
parameters. *Optional.*
#. **root_execution_id** - Similar to id above, if provided will return
a list of executions with that root_execution_id. Otherwise it will
return all executions that match the other parameters. *Optional.*
False by default.
#. **state** - If provided, the executions will be filtered by their
current state. If state isn't provided, all executions that match the
other parameters will be returned . *Optional.*
#. **from_time** - If provided, the executions will be filtered by their
created_at time being greater or equal to the from_time parameter.
If from_time isn't provided, all executions that match the
other parameters will be returned. from_time parameter can be provided
in the format *YYYY-MM-DD hh:mm:ss*
*Optional.*
#. **to_time** - If provided, the executions will be filtered by their
created_at time being less than to the from_time parameter (less than but
not less than equal as the from_time parameter does)
If to_time isn't provided, all executions that match the
other parameters will be returned. to_time parameter can be provided
in the format *YYYY-MM-DD hh:mm:ss*
*Optional.*
Example:
Workflow definition:
.. code-block:: mistral
---
version: "v2.0"
wf:
tasks:
task:
action: std.noop
publish:
all_executions_yaql: <% executions() %>
all_child_executions_of_this_execution: "{{ executions(root_execution_id=execution().id) }}"
all_executions_in_error_yaql: <% executions(null, null, ERROR) %>
all_executions_in_error_jinja: "{{ executions(None, None, 'ERROR') }}"
all_executions_in_error_yaql_with_kw: <% executions(state => ERROR) %>
all_executions_in_error_jinja_with_kw: "{{ executions(state='ERROR') }}"
all_executions_filtered_date_jinja: "{{ executions(to_time="2016-12-01 15:01:00") }}"
Environment
^^^^^^^^^^^

View File

@ -12,8 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import mock
from mistral.db.v2.sqlalchemy import api as db_api
from mistral import exceptions as exc
from mistral.expressions import jinja_expression as expr
from mistral.tests.unit import base
@ -36,6 +38,38 @@ SERVERS = {
]
}
WF_EXECS = [
{
'spec': {},
'id': "one",
'start_params': {'task': 'my_task1'},
'state': 'IDLE',
'state_info': "Running...",
'created_at': datetime.datetime(2016, 12, 1, 15, 0, 0),
'updated_at': None,
'context': None,
'task_id': None,
'trust_id': None,
'description': None,
'output': None
},
{
'spec': {},
'id': "two",
'root_execution_id': "one",
'start_params': {'task': 'my_task1'},
'state': 'RUNNING',
'state_info': "Running...",
'created_at': datetime.datetime(2016, 12, 1, 15, 1, 0),
'updated_at': None,
'context': {'image_id': '123123'},
'task_id': None,
'trust_id': None,
'description': None,
'output': None
}
]
class JinjaEvaluatorTest(base.BaseTest):
def setUp(self):
@ -314,6 +348,127 @@ class JinjaEvaluatorTest(base.BaseTest):
'updated_at': wf_ex.updated_at.isoformat(' ')
}, result)
def test_executions(self):
with db_api.transaction():
created0 = db_api.create_workflow_execution(WF_EXECS[0])
created1 = db_api.create_workflow_execution(WF_EXECS[1])
ctx = {
'__execution': {
'id': 'some'
}
}
result = self._evaluator.evaluate('_|executions()', ctx)
self.assertEqual([created0, created1], result)
db_api.rollback_tx()
def test_executions_id_filter(self):
with db_api.transaction():
created0 = db_api.create_workflow_execution(WF_EXECS[0])
created1 = db_api.create_workflow_execution(WF_EXECS[1])
ctx = {
'__execution': {
'id': 'some'
}
}
result = self._evaluator.evaluate('_|executions("one")', ctx)
self.assertEqual([created0], result)
result = self._evaluator.evaluate(
'executions(root_execution_id="one") ', ctx
)
self.assertEqual([created1], result)
db_api.rollback_tx()
def test_executions_state_filter(self):
with db_api.transaction():
db_api.create_workflow_execution(WF_EXECS[0])
created1 = db_api.create_workflow_execution(WF_EXECS[1])
ctx = {
'__execution': {
'id': 'some'
}
}
result = self._evaluator.evaluate(
'_|executions(state="RUNNING")', ctx
)
self.assertEqual([created1], result)
result = self._evaluator.evaluate(
'_|executions(id="one", state="RUNNING")', ctx
)
self.assertEqual([], result)
db_api.rollback_tx()
def test_executions_from_time_filter(self):
with db_api.transaction():
created0 = db_api.create_workflow_execution(WF_EXECS[0])
created1 = db_api.create_workflow_execution(WF_EXECS[1])
ctx = {
'__execution': {
'id': 'some'
}
}
result = self._evaluator.evaluate(
'_|executions(from_time="2000-01-01")', ctx
)
self.assertEqual([created0, created1], result)
result = self._evaluator.evaluate(
'_|executions(from_time="2016-12-01 15:01:00")', ctx
)
self.assertEqual([created1], result)
result = self._evaluator.evaluate(
'_|executions(id="one", from_time="2016-12-01 15:01:00")', ctx
)
self.assertEqual([], result)
db_api.rollback_tx()
def test_executions_to_time_filter(self):
with db_api.transaction():
created0 = db_api.create_workflow_execution(WF_EXECS[0])
created1 = db_api.create_workflow_execution(WF_EXECS[1])
ctx = {
'__execution': {
'id': 'some'
}
}
result = self._evaluator.evaluate(
'_|executions(to_time="2020-01-01")', ctx
)
self.assertEqual([created0, created1], result)
result = self._evaluator.evaluate(
'_|executions(to_time="2016-12-01 15:01:00")', ctx
)
self.assertEqual([created0], result)
result = self._evaluator.evaluate(
'_|executions(id="two", to_time="2016-12-01 15:01:00")', ctx
)
self.assertEqual([], result)
db_api.rollback_tx()
@mock.patch('mistral.db.v2.api.get_workflow_execution')
def test_function_execution(self, workflow_execution):
wf_ex = mock.MagicMock(return_value={})

View File

@ -104,6 +104,58 @@ def env_(context):
return context['__env']
def executions_(context,
id=None,
root_execution_id=None,
state=None,
from_time=None,
to_time=None
):
filter = {}
if id is not None:
filter = utils.filter_utils.create_or_update_filter(
'id',
id,
"eq",
filter
)
if root_execution_id is not None:
filter = utils.filter_utils.create_or_update_filter(
'root_execution_id',
root_execution_id,
"eq",
filter
)
if state is not None:
filter = utils.filter_utils.create_or_update_filter(
'state',
state,
"eq",
filter
)
if from_time is not None:
filter = utils.filter_utils.create_or_update_filter(
'created_at',
from_time,
"gte",
filter
)
if to_time is not None:
filter = utils.filter_utils.create_or_update_filter(
'created_at',
to_time,
"lt",
filter
)
wf_executions = db_api.get_workflow_executions(**filter)
return wf_executions
def execution_(context):
wf_ex = db_api.get_workflow_execution(context['__execution']['id'])
@ -251,7 +303,6 @@ def _get_tasks_from_db(workflow_execution_id=None, recursive=False, state=None,
def tasks_(context, workflow_execution_id=None, recursive=False, state=None,
flat=False):
task_execs = _get_tasks_from_db(
workflow_execution_id,
recursive,

View File

@ -84,6 +84,7 @@ mistral.expression.functions =
env = mistral.utils.expression_utils:env_
execution = mistral.utils.expression_utils:execution_
executions = mistral.utils.expression_utils:executions_
global = mistral.utils.expression_utils:global_
json_parse = mistral.utils.expression_utils:json_parse_
json_dump = mistral.utils.expression_utils:json_dump_