Merge "Added 'safe-rerun' policy to task-defaults section"

This commit is contained in:
Zuul 2018-04-25 15:56:53 +00:00 committed by Gerrit Code Review
commit 85a24b20a6
8 changed files with 128 additions and 4 deletions

View File

@ -160,6 +160,7 @@ Common workflow attributes
- **timeout** - Configures timeout policy. *Optional*.
- **retry** - Configures retry policy. *Optional*.
- **concurrency** - Configures concurrency policy. *Optional*.
- **safe-rerun** - Configures safe-rerun policy. *Optional*.
- **tasks** - Dictionary containing workflow tasks. See below for more
details. *Required*.

View File

@ -336,6 +336,22 @@ class Task(object):
self.created = True
def _get_safe_rerun(self):
safe_rerun = self.task_spec.get_safe_rerun()
if safe_rerun is not None:
return safe_rerun
task_defaults = self.wf_spec.get_task_defaults()
if task_defaults:
default_safe_rerun = task_defaults.get_safe_rerun()
if default_safe_rerun is not None:
return default_safe_rerun
return False
def _get_action_defaults(self):
action_name = self.task_spec.get_action_name()
@ -474,7 +490,7 @@ class RegularTask(Task):
action.schedule(
input_dict,
target,
safe_rerun=self.task_spec.get_safe_rerun(),
safe_rerun=self._get_safe_rerun(),
timeout=self._get_timeout()
)
@ -655,7 +671,7 @@ class WithItemsTask(RegularTask):
input_dict,
target,
index=i,
safe_rerun=self.task_spec.get_safe_rerun(),
safe_rerun=self._get_safe_rerun(),
timeout=self._get_timeout()
)

View File

@ -40,6 +40,7 @@ class TaskDefaultsSpec(base.BaseSpec):
"on-complete": types.ANY,
"on-success": types.ANY,
"on-error": types.ANY,
"safe-rerun": types.EXPRESSION_OR_BOOLEAN,
"requires": {
"oneOf": [types.NONEMPTY_STRING, types.UNIQUE_STRING_LIST]
}
@ -70,10 +71,17 @@ class TaskDefaultsSpec(base.BaseSpec):
self._on_success = self._spec_property('on-success', on_spec_cls)
self._on_error = self._spec_property('on-error', on_spec_cls)
self._safe_rerun = data.get('safe-rerun')
# TODO(rakhmerov): 'requires' should reside in a different spec for
# reverse workflows.
self._requires = data.get('requires', [])
def validate_schema(self):
super(TaskDefaultsSpec, self).validate_schema()
self.validate_expr(self._data.get('safe-rerun', {}))
def validate_semantics(self):
# Validate YAQL expressions.
self._validate_transitions(self._on_complete)
@ -101,6 +109,9 @@ class TaskDefaultsSpec(base.BaseSpec):
def get_on_error(self):
return self._on_error
def get_safe_rerun(self):
return self._safe_rerun
def get_requires(self):
if isinstance(self._requires, six.string_types):
return [self._requires]

View File

@ -128,7 +128,7 @@ class TaskSpec(base.BaseSpec):
)
self._target = data.get('target')
self._keep_result = data.get('keep-result', True)
self._safe_rerun = data.get('safe-rerun', False)
self._safe_rerun = data.get('safe-rerun')
self._process_action_and_workflow()

View File

@ -176,3 +176,68 @@ class TestSafeRerun(base.EngineTestCase):
self.assertIn(1, result)
self.assertIn(2, result)
self.assertIn(3, result)
@mock.patch.object(r_exe.RemoteExecutor, 'run_action', MOCK_RUN_AT_TARGET)
def test_safe_rerun_in_task_defaults(self):
wf_text = """---
version: '2.0'
wf:
task-defaults:
safe-rerun: true
tasks:
task1:
safe-rerun: false
on-error:
- task2
task2:
action: std.noop
"""
wf_service.create_workflows(wf_text)
wf_ex = self.engine.start_workflow('wf')
self.await_workflow_success(wf_ex.id)
with db_api.transaction():
wf_ex = db_api.get_workflow_execution(wf_ex.id)
tasks = wf_ex.task_executions
self.assertEqual(len(tasks), 2)
task1 = self._assert_single_item(tasks, name='task1')
task2 = self._assert_single_item(tasks, name='task2')
self.assertEqual(task1.state, states.ERROR)
self.assertEqual(task2.state, states.SUCCESS)
@mock.patch.object(r_exe.RemoteExecutor, 'run_action', MOCK_RUN_AT_TARGET)
def test_default_value_of_safe_rerun(self):
wf_text = """---
version: '2.0'
wf:
tasks:
task1:
action: std.noop
"""
wf_service.create_workflows(wf_text)
wf_ex = self.engine.start_workflow('wf')
self.await_workflow_error(wf_ex.id)
with db_api.transaction():
wf_ex = db_api.get_workflow_execution(wf_ex.id)
tasks = wf_ex.task_executions
self.assertEqual(len(tasks), 1)
task1 = self._assert_single_item(tasks, name='task1')
self.assertEqual(task1.state, states.ERROR)

View File

@ -713,3 +713,24 @@ class TaskSpecValidation(v2_base.WorkflowSpecValidationTestCase):
changes=overlay,
expect_error=expect_error
)
def test_safe_rerurn(self):
tests = [
({'safe-rerun': True}, False),
({'safe-rerun': False}, False),
({'safe-rerun': '<% false %>'}, False),
({'safe-rerun': '<% true %>'}, False),
({'safe-rerun': '<% * %>'}, True),
({'safe-rerun': None}, True)
]
for default, expect_error in tests:
overlay = {'test': {'task-defaults': {}}}
utils.merge_dicts(overlay['test']['task-defaults'], default)
self._parse_dsl_spec(
add_tasks=True,
changes=overlay,
expect_error=expect_error
)

View File

@ -383,7 +383,13 @@ class WorkflowSpecValidation(base.WorkflowSpecValidationTestCase):
({'concurrency': '{{ * }}'}, True),
({'concurrency': -10}, True),
({'concurrency': 10.0}, True),
({'concurrency': '10'}, True)
({'concurrency': '10'}, True),
({'safe-rerun': True}, False),
({'safe-rerun': False}, False),
({'safe-rerun': '<% false %>'}, False),
({'safe-rerun': '<% true %>'}, False),
({'safe-rerun': '<% * %>'}, True),
({'safe-rerun': None}, True)
]
for default, expect_error in tests:

View File

@ -0,0 +1,4 @@
---
features:
- |
Added 'safe-rerun' policy to task-defaults section