Merge "Use on-clause and retry_policy get_spec for validation"
This commit is contained in:
commit
6c4e089f00
@ -19,26 +19,81 @@ from mistral.lang import types
|
|||||||
from mistral.lang.v2 import base
|
from mistral.lang.v2 import base
|
||||||
from mistral.lang.v2 import publish
|
from mistral.lang.v2 import publish
|
||||||
|
|
||||||
|
NEXT_TASK = {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^\w+$",
|
||||||
|
"description": "Task name (e.g.: `task1`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^\w+ \w+=(.*)$",
|
||||||
|
"description": "Task name with dict parameter "
|
||||||
|
"(e.g.: `fail msg=\"test\"`, "
|
||||||
|
"`fail msg=<% task() %>`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^\w+\\(\w+=(.*)\\)$",
|
||||||
|
"description": "Task name with func parameter "
|
||||||
|
"(e.g.: `fail(msg=\"test\")`, "
|
||||||
|
"`fail(msg=<% task() %>)`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_WITH_EXPRESSION = {
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
"maxProperties": 1,
|
||||||
|
"patternProperties": {
|
||||||
|
x['pattern']: types.EXPRESSION for x in NEXT_TASK['oneOf']
|
||||||
|
},
|
||||||
|
"description": "All next task variants plus expression (e.g.: "
|
||||||
|
"`task1: <% $.vm_id != null %>`, "
|
||||||
|
"`fail(msg=\"test\"): <% $.vm_id != null %>`)."
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_OF_TASKS = {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
NEXT_TASK,
|
||||||
|
TASK_WITH_EXPRESSION
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"uniqueItems": True,
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ADVANCED_PUBLISHING_DICT = {
|
||||||
|
"type": "object",
|
||||||
|
"minProperties": 1,
|
||||||
|
"properties": {
|
||||||
|
"publish": publish.PublishSpec.get_schema(),
|
||||||
|
"next": {
|
||||||
|
"oneOf": [
|
||||||
|
NEXT_TASK,
|
||||||
|
TASK_WITH_EXPRESSION,
|
||||||
|
LIST_OF_TASKS
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": False
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class OnClauseSpec(base.BaseSpec):
|
class OnClauseSpec(base.BaseSpec):
|
||||||
_simple_schema = {
|
_schema = {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
types.NONEMPTY_STRING,
|
NEXT_TASK,
|
||||||
types.UNIQUE_STRING_OR_EXPRESSION_CONDITION_LIST
|
TASK_WITH_EXPRESSION,
|
||||||
|
LIST_OF_TASKS,
|
||||||
|
ADVANCED_PUBLISHING_DICT
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
_advanced_schema = {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"publish": types.NONEMPTY_DICT,
|
|
||||||
"next": _simple_schema,
|
|
||||||
},
|
|
||||||
"additionalProperties": False
|
|
||||||
}
|
|
||||||
|
|
||||||
_schema = {"oneOf": [_simple_schema, _advanced_schema]}
|
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
super(OnClauseSpec, self).__init__(data)
|
super(OnClauseSpec, self).__init__(data)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class PoliciesSpec(base.BaseSpec):
|
|||||||
_schema = {
|
_schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"retry": types.ANY,
|
"retry": retry_policy.RetrySpec.get_schema(),
|
||||||
"wait-before": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
"wait-before": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"wait-after": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
"wait-after": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"timeout": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
"timeout": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
|
@ -19,6 +19,7 @@ from mistral.lang import types
|
|||||||
from mistral.lang.v2 import base
|
from mistral.lang.v2 import base
|
||||||
from mistral.lang.v2 import on_clause
|
from mistral.lang.v2 import on_clause
|
||||||
from mistral.lang.v2 import policies
|
from mistral.lang.v2 import policies
|
||||||
|
from mistral.lang.v2 import retry_policy
|
||||||
|
|
||||||
|
|
||||||
# TODO(rakhmerov): This specification should be broken into two separate
|
# TODO(rakhmerov): This specification should be broken into two separate
|
||||||
@ -31,15 +32,15 @@ class TaskDefaultsSpec(base.BaseSpec):
|
|||||||
_schema = {
|
_schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"retry": types.ANY,
|
"retry": retry_policy.RetrySpec.get_schema(),
|
||||||
"wait-before": types.ANY,
|
"wait-before": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"wait-after": types.ANY,
|
"wait-after": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"timeout": types.ANY,
|
"timeout": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"pause-before": types.ANY,
|
"pause-before": types.EXPRESSION_OR_BOOLEAN,
|
||||||
"concurrency": types.ANY,
|
"concurrency": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"on-complete": types.ANY,
|
"on-complete": on_clause.OnClauseSpec.get_schema(),
|
||||||
"on-success": types.ANY,
|
"on-success": on_clause.OnClauseSpec.get_schema(),
|
||||||
"on-error": types.ANY,
|
"on-error": on_clause.OnClauseSpec.get_schema(),
|
||||||
"safe-rerun": types.EXPRESSION_OR_BOOLEAN,
|
"safe-rerun": types.EXPRESSION_OR_BOOLEAN,
|
||||||
"requires": {
|
"requires": {
|
||||||
"oneOf": [types.NONEMPTY_STRING, types.UNIQUE_STRING_LIST]
|
"oneOf": [types.NONEMPTY_STRING, types.UNIQUE_STRING_LIST]
|
||||||
|
@ -25,6 +25,7 @@ from mistral.lang.v2 import base
|
|||||||
from mistral.lang.v2 import on_clause
|
from mistral.lang.v2 import on_clause
|
||||||
from mistral.lang.v2 import policies
|
from mistral.lang.v2 import policies
|
||||||
from mistral.lang.v2 import publish
|
from mistral.lang.v2 import publish
|
||||||
|
from mistral.lang.v2 import retry_policy
|
||||||
from mistral import utils
|
from mistral import utils
|
||||||
from mistral.workflow import states
|
from mistral.workflow import states
|
||||||
|
|
||||||
@ -73,12 +74,12 @@ class TaskSpec(base.BaseSpec):
|
|||||||
},
|
},
|
||||||
"publish": types.NONEMPTY_DICT,
|
"publish": types.NONEMPTY_DICT,
|
||||||
"publish-on-error": types.NONEMPTY_DICT,
|
"publish-on-error": types.NONEMPTY_DICT,
|
||||||
"retry": types.ANY,
|
"retry": retry_policy.RetrySpec.get_schema(),
|
||||||
"wait-before": types.ANY,
|
"wait-before": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"wait-after": types.ANY,
|
"wait-after": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"timeout": types.ANY,
|
"timeout": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"pause-before": types.ANY,
|
"pause-before": types.EXPRESSION_OR_BOOLEAN,
|
||||||
"concurrency": types.ANY,
|
"concurrency": types.EXPRESSION_OR_POSITIVE_INTEGER,
|
||||||
"target": types.NONEMPTY_STRING,
|
"target": types.NONEMPTY_STRING,
|
||||||
"keep-result": types.EXPRESSION_OR_BOOLEAN,
|
"keep-result": types.EXPRESSION_OR_BOOLEAN,
|
||||||
"safe-rerun": types.EXPRESSION_OR_BOOLEAN
|
"safe-rerun": types.EXPRESSION_OR_BOOLEAN
|
||||||
@ -279,9 +280,9 @@ class DirectWorkflowTaskSpec(TaskSpec):
|
|||||||
types.POSITIVE_INTEGER
|
types.POSITIVE_INTEGER
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"on-complete": types.ANY,
|
"on-complete": on_clause.OnClauseSpec.get_schema(),
|
||||||
"on-success": types.ANY,
|
"on-success": on_clause.OnClauseSpec.get_schema(),
|
||||||
"on-error": types.ANY
|
"on-error": on_clause.OnClauseSpec.get_schema()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,63 +276,41 @@ class TaskSpecValidation(v2_base.WorkflowSpecValidationTestCase):
|
|||||||
|
|
||||||
def test_direct_transition(self):
|
def test_direct_transition(self):
|
||||||
tests = [
|
tests = [
|
||||||
({'on-success': ['email']}, False),
|
(['email'], False),
|
||||||
({'on-success': [{'email': '<% 1 %>'}]}, False),
|
(['email%'], True),
|
||||||
({'on-success': [{'email': '<% 1 %>'}, 'echo']}, False),
|
([{'email': '<% 1 %>'}], False),
|
||||||
({'on-success': [{'email': '<% $.v1 in $.v2 %>'}]}, False),
|
([{'email': '<% 1 %>'}, {'email': '<% 1 %>'}], True),
|
||||||
({'on-success': [{'email': '<% * %>'}]}, True),
|
([{'email': '<% 1 %>', 'more_email': '<% 2 %>'}], True),
|
||||||
({'on-success': [{'email': '{{ 1 }}'}]}, False),
|
(['email'], False),
|
||||||
({'on-success': [{'email': '{{ 1 }}'}, 'echo']}, False),
|
([{'email': '<% 1 %>'}, 'echo'], False),
|
||||||
({'on-success': [{'email': '{{ _.v1 in _.v2 }}'}]}, False),
|
([{'email': '<% $.v1 in $.v2 %>'}], False),
|
||||||
({'on-success': [{'email': '{{ * }}'}]}, True),
|
([{'email': '<% * %>'}], True),
|
||||||
({'on-success': 'email'}, False),
|
([{'email': '{{ 1 }}'}], False),
|
||||||
({'on-success': None}, True),
|
([{'email': '{{ 1 }}'}, 'echo'], False),
|
||||||
({'on-success': ['']}, True),
|
([{'email': '{{ _.v1 in _.v2 }}'}], False),
|
||||||
({'on-success': []}, True),
|
([{'email': '{{ * }}'}], True),
|
||||||
({'on-success': ['email', 'email']}, True),
|
('email', False),
|
||||||
({'on-success': ['email', 12345]}, True),
|
('fail msg="<% task().result %>"', False),
|
||||||
({'on-error': ['email']}, False),
|
('fail(msg=<% task() %>)', False),
|
||||||
({'on-error': [{'email': '<% 1 %>'}]}, False),
|
(None, True),
|
||||||
({'on-error': [{'email': '<% 1 %>'}, 'echo']}, False),
|
([''], True),
|
||||||
({'on-error': [{'email': '<% $.v1 in $.v2 %>'}]}, False),
|
([], True),
|
||||||
({'on-error': [{'email': '<% * %>'}]}, True),
|
(['email', 'email'], True),
|
||||||
({'on-error': [{'email': '{{ 1 }}'}]}, False),
|
(['email', 12345], True)
|
||||||
({'on-error': [{'email': '{{ 1 }}'}, 'echo']}, False),
|
|
||||||
({'on-error': [{'email': '{{ _.v1 in _.v2 }}'}]}, False),
|
|
||||||
({'on-error': [{'email': '{{ * }}'}]}, True),
|
|
||||||
({'on-error': 'email'}, False),
|
|
||||||
({'on-error': None}, True),
|
|
||||||
({'on-error': ['']}, True),
|
|
||||||
({'on-error': []}, True),
|
|
||||||
({'on-error': ['email', 'email']}, True),
|
|
||||||
({'on-error': ['email', 12345]}, True),
|
|
||||||
({'on-complete': ['email']}, False),
|
|
||||||
({'on-complete': [{'email': '<% 1 %>'}]}, False),
|
|
||||||
({'on-complete': [{'email': '<% 1 %>'}, 'echo']}, False),
|
|
||||||
({'on-complete': [{'email': '<% $.v1 in $.v2 %>'}]}, False),
|
|
||||||
({'on-complete': [{'email': '<% * %>'}]}, True),
|
|
||||||
({'on-complete': [{'email': '{{ 1 }}'}]}, False),
|
|
||||||
({'on-complete': [{'email': '{{ 1 }}'}, 'echo']}, False),
|
|
||||||
({'on-complete': [{'email': '{{ _.v1 in _.v2 }}'}]}, False),
|
|
||||||
({'on-complete': [{'email': '{{ * }}'}]}, True),
|
|
||||||
({'on-complete': 'email'}, False),
|
|
||||||
({'on-complete': None}, True),
|
|
||||||
({'on-complete': ['']}, True),
|
|
||||||
({'on-complete': []}, True),
|
|
||||||
({'on-complete': ['email', 'email']}, True),
|
|
||||||
({'on-complete': ['email', 12345]}, True)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for transition, expect_error in tests:
|
for on_clause_key in ['on-error', 'on-success', 'on-complete']:
|
||||||
overlay = {'test': {'tasks': {}}}
|
for on_clause_value, expect_error in tests:
|
||||||
|
overlay = {'test': {'tasks': {}}}
|
||||||
|
|
||||||
utils.merge_dicts(overlay['test']['tasks'], {'get': transition})
|
utils.merge_dicts(overlay['test']['tasks'],
|
||||||
|
{'get': {on_clause_key: on_clause_value}})
|
||||||
|
|
||||||
self._parse_dsl_spec(
|
self._parse_dsl_spec(
|
||||||
add_tasks=True,
|
add_tasks=True,
|
||||||
changes=overlay,
|
changes=overlay,
|
||||||
expect_error=expect_error
|
expect_error=expect_error
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_direct_transition_advanced_schema(self):
|
def test_direct_transition_advanced_schema(self):
|
||||||
tests = [
|
tests = [
|
||||||
@ -431,6 +409,9 @@ class TaskSpecValidation(v2_base.WorkflowSpecValidationTestCase):
|
|||||||
({'on-success': {'next': 'email'}}, False),
|
({'on-success': {'next': 'email'}}, False),
|
||||||
({'on-success': {'next': ['email']}}, False),
|
({'on-success': {'next': ['email']}}, False),
|
||||||
({'on-success': {'next': [{'email': 'email'}]}}, True),
|
({'on-success': {'next': [{'email': 'email'}]}}, True),
|
||||||
|
({'on-success': {'next': [{'email': 'email',
|
||||||
|
'more_email': 'more_email'}]}}, True),
|
||||||
|
({'on-success': {'next': {'email': 'email'}}}, True),
|
||||||
({'on-error': {'publish': {'var1': 1234}}}, True),
|
({'on-error': {'publish': {'var1': 1234}}}, True),
|
||||||
({'on-error': {'publish': {'branch': {'var1': 1234}}}}, False),
|
({'on-error': {'publish': {'branch': {'var1': 1234}}}}, False),
|
||||||
(
|
(
|
||||||
@ -526,6 +507,9 @@ class TaskSpecValidation(v2_base.WorkflowSpecValidationTestCase):
|
|||||||
({'on-error': {'next': 'email'}}, False),
|
({'on-error': {'next': 'email'}}, False),
|
||||||
({'on-error': {'next': ['email']}}, False),
|
({'on-error': {'next': ['email']}}, False),
|
||||||
({'on-error': {'next': [{'email': 'email'}]}}, True),
|
({'on-error': {'next': [{'email': 'email'}]}}, True),
|
||||||
|
({'on-error': {'next': [{'email': 'email',
|
||||||
|
'more_email': 'more_email'}]}}, True),
|
||||||
|
({'on-error': {'next': {'email': 'email'}}}, True),
|
||||||
({'on-complete': {'publish': {'var1': 1234}}}, True),
|
({'on-complete': {'publish': {'var1': 1234}}}, True),
|
||||||
({'on-complete': {'publish': {'branch': {'var1': 1234}}}}, False),
|
({'on-complete': {'publish': {'branch': {'var1': 1234}}}}, False),
|
||||||
(
|
(
|
||||||
@ -620,7 +604,10 @@ class TaskSpecValidation(v2_base.WorkflowSpecValidationTestCase):
|
|||||||
({'on-complete': {'next': [{'email': '<% $.v1 %>'}]}}, False),
|
({'on-complete': {'next': [{'email': '<% $.v1 %>'}]}}, False),
|
||||||
({'on-complete': {'next': 'email'}}, False),
|
({'on-complete': {'next': 'email'}}, False),
|
||||||
({'on-complete': {'next': ['email']}}, False),
|
({'on-complete': {'next': ['email']}}, False),
|
||||||
({'on-complete': {'next': [{'email': 'email'}]}}, True)
|
({'on-complete': {'next': [{'email': 'email'}]}}, True),
|
||||||
|
({'on-complete': {'next': [{'email': 'email',
|
||||||
|
'more_email': 'more_email'}]}}, True),
|
||||||
|
({'on-complete': {'next': {'email': 'email'}}}, True)
|
||||||
]
|
]
|
||||||
|
|
||||||
for transition, expect_error in tests:
|
for transition, expect_error in tests:
|
||||||
|
Loading…
Reference in New Issue
Block a user