def test_run_workflow_action_config_context(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'config-context.yaml') wf_input = {} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert task1 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(wf_svc.is_action_execution_under_workflow_context(tk1_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Verify config_context works self.assertEqual(wf_ex_db.output, {'msg': 'value of config key a'})
def test_output_on_error(self): expected_output = { 'progress': 25 } expected_errors = [ { 'type': 'error', 'task_id': 'task2', 'message': 'Execution failed. See result for details.', 'result': { 'failed': True, 'return_code': 1, 'stderr': '', 'stdout': '', 'succeeded': False } } ] expected_result = { 'errors': expected_errors, 'output': expected_output } wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'output-on-error.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] # Assert task1 is already completed and workflow execution is still running. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task2 is already completed and workflow execution has failed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Check output and result for expected value(s). wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) self.assertDictEqual(wf_ex_db.output, expected_output) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_cancel_subworkflow_cascade_up_to_workflow_with_other_subworkflows(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'subworkflows.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Identify the records for the subworkflow. wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) self.assertEqual(len(wf_ex_dbs), 1) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_dbs[0].id)) self.assertEqual(len(tk_ex_dbs), 2) tk1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[0].id)) self.assertEqual(len(tk1_ac_ex_dbs), 1) tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_dbs[0].liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) tk2_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[1].id)) self.assertEqual(len(tk2_ac_ex_dbs), 1) tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_dbs[0].liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Cancel the subworkflow which should cascade up to the root. requester = cfg.CONF.system_user.user tk1_lv_ac_db, tk1_ac_ex_db = ac_svc.request_cancellation(tk1_lv_ac_db, requester) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELING) # Assert the main workflow is canceling. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELING) # Assert both subworkflows are canceled. tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(tk1_lv_ac_db.id)) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED) tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(tk2_lv_ac_db.id)) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED) # Manually handle action execution completion for one of the tasks. tk1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(tk1_ac_ex_db.id)) self.assertEqual(tk1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_CANCELED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Manually handle action execution completion for the other task. tk2_ac_ex_db = tk2_ac_ex_dbs[0] tk2_ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(tk2_ac_ex_db.id)) self.assertEqual(tk2_ac_ex_db.status, ac_const.LIVEACTION_STATUS_CANCELED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert the main workflow is canceling. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED)
def run_workflow_step(self, wf_ex_db, task_id, ctx=None): spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) task_spec = wf_spec.tasks.get_task(task_id) st2_ctx = {'execution_id': wf_ex_db.action_execution} task_ex_db = wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, ctx or {}, st2_ctx) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, wf_lib_states.SUCCEEDED)
def test_fail_next_task_input_value_type(self): if six.PY3: msg = 'Value "{\'x\': \'foobar\'}" must either be a string or None. Got "dict".' else: msg = 'Value "{u\'x\': u\'foobar\'}" must either be a string or None. Got "dict".' msg = 'ValueError: ' + msg expected_errors = [ { 'type': 'error', 'message': msg, 'task_id': 'task2', 'route': 0 } ] expected_result = {'output': None, 'errors': expected_errors} wf_file = 'fail-task-input-value-type.yaml' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file) wf_input = {'var1': {'x': 'foobar'}} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert task1 is already completed and workflow execution is still running. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] tk1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Manually handle action execution completion for task1 which has an error in publish. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert workflow execution and task2 execution failed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id)) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors) tk2_ex_db = wf_db_access.TaskExecution.query(task_id='task2')[0] self.assertEqual(tk2_ex_db.status, wf_statuses.FAILED) self.assertDictEqual(tk2_ex_db.result, {'errors': expected_errors}) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def _execute_workflow(self, wf_name, expected_task_sequence, expected_output, expected_status=wf_statuses.SUCCEEDED, expected_errors=None): wf_file = wf_name + '.yaml' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file) lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) for task_id, route in expected_task_sequence: tk_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id), task_id=task_id, task_route=route ) if len(tk_ex_dbs) <= 0: break tk_ex_db = sorted(tk_ex_dbs, key=lambda x: x.start_timestamp)[len(tk_ex_dbs) - 1] tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0] tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id']) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(wf_svc.is_action_execution_under_workflow_context(tk_ac_ex_db)) wf_svc.handle_action_execution_completion(tk_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, expected_status) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, expected_status) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, expected_status) # Check workflow output, liveaction result, and action execution result. expected_result = {'output': expected_output} if expected_errors is not None: expected_result['errors'] = expected_errors if expected_output is not None: self.assertDictEqual(wf_ex_db.output, expected_output) self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_fail_manually(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-manually.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] # Assert task1 and workflow execution failed due to fail in the task transition. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) # Assert log task is scheduled even though the workflow execution failed manually. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'log'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) # Check errors and output. expected_errors = [ { 'task_id': 'fail', 'type': 'error', 'message': 'Execution failed. See result for details.' }, { 'task_id': 'task1', 'type': 'error', 'message': 'Execution failed. See result for details.', 'result': { 'failed': True, 'return_code': 1, 'stderr': '', 'stdout': '', 'succeeded': False } } ] self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors)
def test_action_context_source_channel(self): wf_name = 'subworkflow-source-channel-from-action-context' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_name + '.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], context={'source_channel': 'general'}) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Identify the records for the main workflow. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] t1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_statuses.RUNNING) # Complete subworkflow under task1. query_filters = {'workflow_execution': str(t1_wf_ex_db.id), 'task_id': 'task1'} t1_t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t1_ex_db.id))[0] wf_svc.handle_action_execution_completion(t1_t1_ac_ex_db) query_filters = {'workflow_execution': str(t1_wf_ex_db.id), 'task_id': 'task2'} t1_t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t2_ex_db.id))[0] wf_svc.handle_action_execution_completion(t1_t2_ac_ex_db) query_filters = {'workflow_execution': str(t1_wf_ex_db.id), 'task_id': 'task3'} t1_t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t3_ex_db.id))[0] wf_svc.handle_action_execution_completion(t1_t3_ac_ex_db) t1_wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(t1_wf_ex_db.id)) t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(t1_ac_ex_db.id)) self.assertEqual(t1_wf_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Complete task1 and main workflow. wf_svc.handle_action_execution_completion(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(str(t1_ex_db.id)) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id)) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(t1_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check result. expected_result = { 'output': { 'msg': 'general, All your base are belong to us!' } } self.assertDictEqual(lv_ac_db.result, expected_result)
def handle_action_execution(self, ac_ex_db): # Exit if action execution is not executed under an orquesta workflow. if not wf_svc.is_action_execution_under_workflow_context(ac_ex_db): return # Get related record identifiers. wf_ex_id = ac_ex_db.context['orquesta']['workflow_execution_id'] task_ex_id = ac_ex_db.context['orquesta']['task_execution_id'] # Get execution records for logging purposes. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_id) task_ex_db = wf_db_access.TaskExecution.get_by_id(task_ex_id) wf_ac_ex_id = wf_ex_db.action_execution msg = '[%s] Action execution "%s" for task "%s" is updated and in "%s" state.' LOG.info(msg, wf_ac_ex_id, str(ac_ex_db.id), task_ex_db.task_id, ac_ex_db.status) # Skip if task execution is already in completed state. if task_ex_db.status in statuses.COMPLETED_STATUSES: msg = ('[%s] Action execution "%s" for task "%s (%s)", route "%s", is not processed ' 'because task execution "%s" is already in completed state "%s".') LOG.info(msg, wf_ac_ex_id, str(ac_ex_db.id), task_ex_db.task_id, str(task_ex_db.task_route), str(task_ex_db.id), task_ex_db.status) return # Process pending request on the action execution. if ac_ex_db.status == ac_const.LIVEACTION_STATUS_PENDING: wf_svc.handle_action_execution_pending(ac_ex_db) return # Process pause request on the action execution. if ac_ex_db.status == ac_const.LIVEACTION_STATUS_PAUSED: wf_svc.handle_action_execution_pause(ac_ex_db) return # Exit if action execution has not completed yet. if ac_ex_db.status not in ac_const.LIVEACTION_COMPLETED_STATES: return # Apply post run policies. lv_ac_db = lv_db_access.LiveAction.get_by_id(ac_ex_db.liveaction['id']) pc_svc.apply_post_run_policies(lv_ac_db) # Process completion of the action execution. wf_svc.handle_action_execution_completion(ac_ex_db)
def test_fail_task_publish(self): expected_errors = [ { 'type': 'error', 'message': ( 'YaqlEvaluationException: Unable to evaluate expression ' '\'<% foobar() %>\'. NoFunctionRegisteredException: ' 'Unknown function "foobar"' ), 'task_transition_id': 'task2__t0', 'task_id': 'task1', 'route': 0 } ] expected_result = {'output': None, 'errors': expected_errors} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-publish.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert task1 is already completed. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0] tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id']) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion for task1 which has an error in publish. wf_svc.handle_action_execution_completion(tk_ac_ex_db) # Assert task1 succeeded but workflow failed. tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id) self.assertEqual(tk_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_fail_task_execution(self): expected_errors = [ { 'type': 'error', 'message': 'Execution failed. See result for details.', 'task_id': 'task1', 'result': { 'stdout': '', 'stderr': 'boom!', 'return_code': 1, 'failed': True, 'succeeded': False } } ] expected_result = {'output': None, 'errors': expected_errors} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-execution.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Process task1. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] tk1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert workflow state and result. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id)) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_fail_task_transition(self): expected_errors = [ { 'message': ( "Unable to resolve key 'foobar' in expression " "'<% succeeded() and result().foobar %>' from context." ), 'task_transition_id': 'task2__0', 'task_id': 'task1' } ] expected_result = {'output': None, 'errors': expected_errors} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-transition.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert task1 is already completed. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0] tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id']) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion for task1 which has an error in publish. wf_svc.handle_action_execution_completion(tk_ac_ex_db) # Assert task1 succeeded but workflow failed. tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id) self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.FAILED) self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_runtime_context(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'runtime-context.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Identify the records for the workflow. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] t1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id))[0] # Complete the worklfow. wf_svc.handle_action_execution_completion(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(str(t1_ex_db.id)) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id)) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(t1_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check result. expected_st2_ctx = { 'action_execution_id': str(ac_ex_db.id), 'api_url': 'http://127.0.0.1/v1', 'user': '******', 'pack': 'orquesta_tests' } expected_st2_ctx_with_wf_ex_id = copy.deepcopy(expected_st2_ctx) expected_st2_ctx_with_wf_ex_id['workflow_execution_id'] = str(wf_ex_db.id) expected_output = { 'st2_ctx_at_input': expected_st2_ctx, 'st2_ctx_at_vars': expected_st2_ctx, 'st2_ctx_at_publish': expected_st2_ctx_with_wf_ex_id, 'st2_ctx_at_output': expected_st2_ctx_with_wf_ex_id } expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result)
def test_adherence_to_output_schema(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential_with_schema.yaml') wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] wf_svc.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] wf_svc.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] wf_svc.handle_action_execution_completion(tk3_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
def test_fail_next_task_input_expr_eval(self): expected_errors = [ { 'message': 'Unknown function "#property#value"', 'task_id': 'task2' } ] expected_result = {'output': None, 'errors': expected_errors} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-input-expr-eval.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert task1 is already completed. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] tk_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id))[0] tk_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id))[0] tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_db.liveaction['id']) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion for task1 which has an error in publish. wf_svc.handle_action_execution_completion(tk_ac_ex_db) # Assert task1 succeeded but workflow failed. tk_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_db.id) self.assertEqual(tk_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.FAILED) self.assertListEqual(self.sort_wf_runtime_errors(wf_ex_db.errors), expected_errors) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def run_workflow_step(self, wf_ex_db, task_id, route, ctx=None): spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) st2_ctx = {'execution_id': wf_ex_db.action_execution} task_spec = wf_spec.tasks.get_task(task_id) task_actions = [{'action': task_spec.action, 'input': getattr(task_spec, 'input', {})}] task_req = { 'id': task_id, 'route': route, 'spec': task_spec, 'ctx': ctx or {}, 'actions': task_actions } task_ex_db = wf_svc.request_task_execution(wf_ex_db, st2_ctx, task_req) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) ac_ex_db = self._wait_on_ac_ex_status(ac_ex_db, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, wf_statuses.SUCCEEDED)
def _execute_workflow(self, wf_name, expected_output): wf_file = wf_name + '.yaml' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file) lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert task1 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(wf_svc.is_action_execution_under_workflow_context(tk1_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output, liveaction result, and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(wf_ex_db.output, expected_output) self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_resume(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Pause the workflow. lv_ac_db, ac_ex_db = ac_svc.request_pause(lv_ac_db, cfg.CONF.system_user.user) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_PAUSING) # Identify the records for the running task(s) and manually complete it. wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_dbs[0].id)) self.assertEqual(len(tk_ex_dbs), 1) tk_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[0].id)) tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk_ac_ex_dbs[0].liveaction['id']) self.assertEqual(tk_ac_ex_dbs[0].status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk_ac_ex_dbs[0]) # Ensure the workflow is paused. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_PAUSED, lv_ac_db.result) wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) self.assertEqual(wf_ex_dbs[0].status, wf_statuses.PAUSED) # Resume the workflow. lv_ac_db, ac_ex_db = ac_svc.request_resume(lv_ac_db, cfg.CONF.system_user.user) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) self.assertEqual(wf_ex_dbs[0].status, wf_statuses.RUNNING) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_dbs[0].id)) self.assertEqual(len(tk_ex_dbs), 2)
def test_run_workflow_with_unicode_input(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': '薩諾斯'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] # Process task1. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) # Process task2. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) # Process task3. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk3_ac_ex_db) tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_statuses.SUCCEEDED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. wf_input_val = wf_input['who'].decode('utf-8') if six.PY2 else wf_input['who'] expected_output = {'msg': '%s, All your base are belong to us!' % wf_input_val} self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_fail_incorrect_output_schema(self): wf_meta = base.get_wf_fixture_meta_data( TEST_PACK_PATH, 'sequential_with_broken_schema.yaml' ) wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] wf_svc.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] wf_svc.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] wf_svc.handle_action_execution_completion(tk3_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) expected_result = { 'error': "Additional properties are not allowed", 'message': 'Error validating output. See error output for more details.' } self.assertIn(expected_result['error'], ac_ex_db.result['error']) self.assertEqual(expected_result['message'], ac_ex_db.result['message'])
def test_cascade_notify_to_tasks(self): wf_input = {'notify': ['task2']} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db.notify = notify_api_models.NotificationsHelper.to_model(MOCK_NOTIFY) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_RUNNING) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, action_constants.LIVEACTION_STATUS_RUNNING) # Assert task1 notify is not set. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertIsNone(tk1_lv_ac_db.notify) self.assertEqual(tk1_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertFalse(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock() # Handle task1 completion. workflow_service.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task2 notify is set. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) notify = notify_api_models.NotificationsHelper.from_model(notify_model=tk2_lv_ac_db.notify) self.assertEqual(notify, MOCK_NOTIFY) self.assertEqual(tk2_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock() # Handle task2 completion. workflow_service.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task3 notify is not set. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk3_ac_ex_db.liveaction['id']) self.assertIsNone(tk3_lv_ac_db.notify) self.assertEqual(tk3_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertFalse(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock() # Handle task3 completion. workflow_service.handle_action_execution_completion(tk3_ac_ex_db) tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_statuses.SUCCEEDED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock()
def test_run_workflow_with_action_less_tasks(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'action-less-tasks.yaml') wf_input = {'name': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert task1 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id)) self.assertEqual(len(tk1_ac_ex_dbs), 0) self.assertEqual(tk1_ex_db.status, wf_states.SUCCEEDED) # Assert task2 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task3 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert task4 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task4'} tk4_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk4_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(tk4_ex_db.id)) self.assertEqual(len(tk4_ac_ex_dbs), 0) self.assertEqual(tk4_ex_db.status, wf_states.SUCCEEDED) # Assert task5 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task5'} tk5_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk5_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk5_ex_db.id))[0] tk5_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk5_ac_ex_db.liveaction['id']) self.assertEqual(tk5_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk5_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. expected_output = {'greeting': '%s, All your base are belong to us!' % wf_input['name']} expected_output['greeting'] = expected_output['greeting'].upper() self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_run_workflow(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertTrue(lv_ac_db.action_is_workflow) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] # Check required attributes. self.assertEqual(len(wf_ex_dbs), 1) self.assertIsNotNone(wf_ex_db.id) self.assertGreater(wf_ex_db.rev, 0) self.assertEqual(wf_ex_db.action_execution, str(ac_ex_db.id)) self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Check context. self.assertIn('workflow_execution', lv_ac_db.context) self.assertEqual(lv_ac_db.context['workflow_execution'], str(wf_ex_db.id)) # Check graph. self.assertIsNotNone(wf_ex_db.graph) self.assertTrue(isinstance(wf_ex_db.graph, dict)) self.assertIn('nodes', wf_ex_db.graph) self.assertIn('adjacency', wf_ex_db.graph) # Check task flow. self.assertIsNotNone(wf_ex_db.flow) self.assertTrue(isinstance(wf_ex_db.flow, dict)) self.assertIn('tasks', wf_ex_db.flow) self.assertIn('sequence', wf_ex_db.flow) # Check input. self.assertDictEqual(wf_ex_db.input, wf_input) # Assert task1 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert task1 succeeded and workflow is still running. tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Assert task2 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task2 succeeded and workflow is still running. tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Assert task3 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. expected_output = {'msg': '%s, All your base are belong to us!' % wf_input['who']} self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_resume_from_subworkflow_when_parent_is_running(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'subworkflows.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Identify the records for the main workflow. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 2) # Identify the records for the subworkflows. t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[0].id))[0] t1_lv_ac_db = lv_db_access.LiveAction.get_by_id(t1_ac_ex_db.liveaction['id']) t1_wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_statuses.RUNNING) t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[1].id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(t2_ac_ex_db.liveaction['id']) t2_wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(t2_ac_ex_db.id))[0] self.assertEqual(t2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t2_wf_ex_db.status, wf_statuses.RUNNING) # Pause the subworkflow. t1_lv_ac_db, t1_ac_ex_db = ac_svc.request_pause(t1_lv_ac_db, cfg.CONF.system_user.user) self.assertEqual(t1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_PAUSING) # Assert the main workflow is still running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert the other subworkflow is still running. t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(t2_ac_ex_db.liveaction['id']) self.assertEqual(t2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Manually notify action execution completion for the task in the subworkflow. t1_t1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id))[0] t1_t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t1_ex_db.id))[0] workflows.get_engine().process(t1_t1_ac_ex_db) # Assert the subworkflow is paused and manually notify the paused of the # corresponding action execution in the main workflow. t1_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t1_lv_ac_db.id)) self.assertEqual(t1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_PAUSED) t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(t1_ac_ex_db.id) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_PAUSED) workflows.get_engine().process(t1_ac_ex_db) # Assert the main workflow is still running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert the other subworkflow is still running. t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(t2_ac_ex_db.liveaction['id']) self.assertEqual(t2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Resume the subworkflow and assert it is running. t1_lv_ac_db, t1_ac_ex_db = ac_svc.request_resume(t1_lv_ac_db, cfg.CONF.system_user.user) t1_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t1_lv_ac_db.id)) self.assertEqual(t1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert the main workflow is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert the other subworkflow is still running. t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(t2_ac_ex_db.liveaction['id']) self.assertEqual(t2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Manually notify action execution completion for the tasks in the subworkflow. t1_t2_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id))[1] t1_t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t2_ex_db.id))[0] workflows.get_engine().process(t1_t2_ac_ex_db) t1_t3_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id))[2] t1_t3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t3_ex_db.id))[0] workflows.get_engine().process(t1_t3_ac_ex_db) t1_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t1_lv_ac_db.id)) self.assertEqual(t1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Assert the subworkflow is completed and manually notify the # completion to the corresponding action execution in the main workflow. t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(t1_ac_ex_db.id) workflows.get_engine().process(t1_ac_ex_db) # Manually notify action execution completion for the tasks in the other subworkflow. t2_t1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t2_wf_ex_db.id))[0] t2_t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t2_t1_ex_db.id))[0] workflows.get_engine().process(t2_t1_ac_ex_db) t2_t2_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t2_wf_ex_db.id))[1] t2_t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t2_t2_ex_db.id))[0] workflows.get_engine().process(t2_t2_ac_ex_db) t2_t3_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t2_wf_ex_db.id))[2] t2_t3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t2_t3_ex_db.id))[0] workflows.get_engine().process(t2_t3_ac_ex_db) t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t2_lv_ac_db.id)) self.assertEqual(t2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Assert this other subworkflow is completed and manually notify the # completion to the corresponding action execution in the main workflow. t2_ac_ex_db = ex_db_access.ActionExecution.get_by_id(t2_ac_ex_db.id) workflows.get_engine().process(t2_ac_ex_db) # Assert task3 has started and completed. tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 3) t3_ex_db_qry = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} t3_ex_db = wf_db_access.TaskExecution.query(**t3_ex_db_qry)[0] t3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t3_ex_db.id))[0] t3_lv_ac_db = lv_db_access.LiveAction.get_by_id(t3_ac_ex_db.liveaction['id']) self.assertEqual(t3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(t3_ac_ex_db) # Assert the main workflow is completed. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED)
def test_cancel_subworkflow_cascade_up_to_workflow_with_other_subworkflows( self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'subworkflows.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Identify the records for the subworkflow. wf_ex_dbs = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id)) self.assertEqual(len(wf_ex_dbs), 1) tk_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_dbs[0].id)) self.assertEqual(len(tk_ex_dbs), 2) tk1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(tk_ex_dbs[0].id)) self.assertEqual(len(tk1_ac_ex_dbs), 1) tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_dbs[0].liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) tk2_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(tk_ex_dbs[1].id)) self.assertEqual(len(tk2_ac_ex_dbs), 1) tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_dbs[0].liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Cancel the subworkflow which should cascade up to the root. requester = cfg.CONF.system_user.user tk1_lv_ac_db, tk1_ac_ex_db = ac_svc.request_cancellation( tk1_lv_ac_db, requester) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELING) # Assert the main workflow is canceling. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELING) # Assert both subworkflows are canceled. tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(tk1_lv_ac_db.id)) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED) tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(tk2_lv_ac_db.id)) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED) # Manually handle action execution completion for one of the tasks. tk1_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(tk1_ac_ex_db.id)) self.assertEqual(tk1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_CANCELED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Manually handle action execution completion for the other task. tk2_ac_ex_db = tk2_ac_ex_dbs[0] tk2_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(tk2_ac_ex_db.id)) self.assertEqual(tk2_ac_ex_db.status, ac_const.LIVEACTION_STATUS_CANCELED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert the main workflow is canceling. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED)
def test_action_context_source_channel(self): wf_name = "subworkflow-source-channel-from-action-context" wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_name + ".yaml") lv_ac_db = lv_db_models.LiveActionDB( action=wf_meta["name"], context={"source_channel": "general"} ) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual( lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result ) # Identify the records for the main workflow. wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id) )[0] t1_ex_db = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id) )[0] t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id) )[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(t1_ac_ex_db.id) )[0] self.assertEqual(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_statuses.RUNNING) # Complete subworkflow under task1. query_filters = {"workflow_execution": str(t1_wf_ex_db.id), "task_id": "task1"} t1_t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t1_ex_db.id) )[0] wf_svc.handle_action_execution_completion(t1_t1_ac_ex_db) query_filters = {"workflow_execution": str(t1_wf_ex_db.id), "task_id": "task2"} t1_t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t2_ex_db.id) )[0] wf_svc.handle_action_execution_completion(t1_t2_ac_ex_db) query_filters = {"workflow_execution": str(t1_wf_ex_db.id), "task_id": "task3"} t1_t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t3_ex_db.id) )[0] wf_svc.handle_action_execution_completion(t1_t3_ac_ex_db) t1_wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(t1_wf_ex_db.id)) t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(t1_ac_ex_db.id)) self.assertEqual(t1_wf_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Complete task1 and main workflow. wf_svc.handle_action_execution_completion(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(str(t1_ex_db.id)) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id)) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(t1_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check result. expected_result = { "output": {"msg": "general, All your base are belong to us!"} } self.assertDictEqual(lv_ac_db.result, expected_result)
def test_rerun_workflow_already_succeeded(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, "sequential.yaml") wf_input = {"who": "Thanos"} lv_ac_db1 = lv_db_models.LiveActionDB(action=wf_meta["name"], parameters=wf_input) lv_ac_db1, ac_ex_db1 = action_service.request(lv_ac_db1) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db1.id))[0] # Process task1. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task1" } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction["id"]) self.assertEqual(tk1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflow_service.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) # Process task2. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task2" } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction["id"]) self.assertEqual(tk2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflow_service.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) # Process task3. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task3" } tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction["id"]) self.assertEqual(tk3_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflow_service.handle_action_execution_completion(tk3_ac_ex_db) tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_statuses.SUCCEEDED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db1 = lv_db_access.LiveAction.get_by_id(str(lv_ac_db1.id)) self.assertEqual(lv_ac_db1.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db1 = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db1.id)) self.assertEqual(ac_ex_db1.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Rerun the execution. context = {"re-run": {"ref": str(ac_ex_db1.id), "tasks": ["task1"]}} lv_ac_db2 = lv_db_models.LiveActionDB(action=wf_meta["name"], context=context) lv_ac_db2, ac_ex_db2 = action_service.request(lv_ac_db2) # Assert the workflow reran ok and is running. wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db2.id))[0] self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) lv_ac_db2 = lv_db_access.LiveAction.get_by_id(str(lv_ac_db2.id)) self.assertEqual(lv_ac_db2.status, action_constants.LIVEACTION_STATUS_RUNNING) ac_ex_db2 = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db2.id)) self.assertEqual(ac_ex_db2.status, action_constants.LIVEACTION_STATUS_RUNNING) # Assert there are two task1 and the last entry succeeded. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task1" } tk1_ex_dbs = wf_db_access.TaskExecution.query(**query_filters) self.assertEqual(len(tk1_ex_dbs), 2) tk1_ex_dbs = sorted(tk1_ex_dbs, key=lambda x: x.start_timestamp) tk1_ex_db = tk1_ex_dbs[-1] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction["id"]) self.assertEqual(tk1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflow_service.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) # Assert there are two task2 and the last entry succeeded. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task2" } tk2_ex_dbs = wf_db_access.TaskExecution.query(**query_filters) self.assertEqual(len(tk2_ex_dbs), 2) tk2_ex_dbs = sorted(tk2_ex_dbs, key=lambda x: x.start_timestamp) tk2_ex_db = tk2_ex_dbs[-1] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction["id"]) self.assertEqual(tk2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflow_service.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) # Assert there are two task3 and the last entry succeeded. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task3" } tk3_ex_dbs = wf_db_access.TaskExecution.query(**query_filters) self.assertEqual(len(tk3_ex_dbs), 2) tk3_ex_dbs = sorted(tk3_ex_dbs, key=lambda x: x.start_timestamp) tk3_ex_db = tk3_ex_dbs[-1] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction["id"]) self.assertEqual(tk3_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflow_service.handle_action_execution_completion(tk3_ac_ex_db) tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_statuses.SUCCEEDED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db1 = lv_db_access.LiveAction.get_by_id(str(lv_ac_db1.id)) self.assertEqual(lv_ac_db1.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db1 = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db1.id)) self.assertEqual(ac_ex_db1.status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
def test_output_on_error(self): expected_output = {'progress': 25} expected_errors = [{ 'type': 'error', 'task_id': 'task2', 'message': 'Execution failed. See result for details.', 'result': { 'failed': True, 'return_code': 1, 'stderr': '', 'stdout': '', 'succeeded': False } }] expected_result = { 'errors': expected_errors, 'output': expected_output } wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'output-on-error.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id))[0] # Assert task1 is already completed and workflow execution is still running. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task2 is already completed and workflow execution has failed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2' } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Check output and result for expected value(s). wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) self.assertDictEqual(wf_ex_db.output, expected_output) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(lv_ac_db.result, expected_result) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_run_workflow_with_action_less_tasks(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'action-less-tasks.yaml') wf_input = {'name': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert task1 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id)) self.assertEqual(len(tk1_ac_ex_dbs), 0) self.assertEqual(tk1_ex_db.status, wf_states.SUCCEEDED) # Assert task2 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2' } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task3 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3' } tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert task4 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task4' } tk4_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk4_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(tk4_ex_db.id)) self.assertEqual(len(tk4_ac_ex_dbs), 0) self.assertEqual(tk4_ex_db.status, wf_states.SUCCEEDED) # Assert task5 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task5' } tk5_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk5_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk5_ex_db.id))[0] tk5_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk5_ac_ex_db.liveaction['id']) self.assertEqual(tk5_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk5_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. expected_output = { 'greeting': '%s, All your base are belong to us!' % wf_input['name'] } expected_output['greeting'] = expected_output['greeting'].upper() self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_action_context_sys_user(self): wf_name = 'subworkflow-default-value-from-action-context' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_name + '.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) # Identify the records for the main workflow. wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id))[0] t1_ex_db = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id))[0] t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ex_db.status, wf_states.RUNNING) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_states.RUNNING) # Complete subworkflow under task1. query_filters = { 'workflow_execution': str(t1_wf_ex_db.id), 'task_id': 'task1' } t1_t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t1_ex_db.id))[0] wf_svc.handle_action_execution_completion(t1_t1_ac_ex_db) query_filters = { 'workflow_execution': str(t1_wf_ex_db.id), 'task_id': 'task2' } t1_t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t2_ex_db.id))[0] wf_svc.handle_action_execution_completion(t1_t2_ac_ex_db) query_filters = { 'workflow_execution': str(t1_wf_ex_db.id), 'task_id': 'task3' } t1_t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_t3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t3_ex_db.id))[0] wf_svc.handle_action_execution_completion(t1_t3_ac_ex_db) t1_wf_ex_db = wf_db_access.WorkflowExecution.get_by_id( str(t1_wf_ex_db.id)) t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(t1_ac_ex_db.id)) self.assertEqual(t1_wf_ex_db.status, wf_states.SUCCEEDED) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Complete task1 and main workflow. wf_svc.handle_action_execution_completion(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(str(t1_ex_db.id)) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(str(wf_ex_db.id)) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(t1_ex_db.status, wf_states.SUCCEEDED) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check result. expected_result = { 'output': { 'msg': 'stanley, All your base are belong to us!' } } self.assertDictEqual(lv_ac_db.result, expected_result)
def test_run_workflow_with_unicode_input(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': '薩諾斯'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id))[0] # Process task1. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_states.SUCCEEDED) # Process task2. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2' } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_states.SUCCEEDED) # Process task3. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3' } tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(tk3_ac_ex_db) tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_states.SUCCEEDED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. wf_input_val = wf_input['who'].decode( 'utf-8') if six.PY2 else wf_input['who'] expected_output = { 'msg': '%s, All your base are belong to us!' % wf_input_val } self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_run_workflow(self): username = '******' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # The main action execution for this workflow is not under the context of another workflow. self.assertFalse( wf_svc.is_action_execution_under_workflow_context(ac_ex_db)) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertTrue(lv_ac_db.action_is_workflow) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_dbs = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] # Check required attributes. self.assertEqual(len(wf_ex_dbs), 1) self.assertIsNotNone(wf_ex_db.id) self.assertGreater(wf_ex_db.rev, 0) self.assertEqual(wf_ex_db.action_execution, str(ac_ex_db.id)) self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Check context in the workflow execution. expected_wf_ex_ctx = { 'st2': { 'workflow_execution_id': str(wf_ex_db.id), 'action_execution_id': str(ac_ex_db.id), 'api_url': 'http://127.0.0.1/v1', 'user': username, 'pack': 'orquesta_tests' }, 'parent': { 'pack': 'orquesta_tests' } } self.assertDictEqual(wf_ex_db.context, expected_wf_ex_ctx) # Check context in the liveaction. expected_lv_ac_ctx = { 'workflow_execution': str(wf_ex_db.id), 'pack': 'orquesta_tests' } self.assertDictEqual(lv_ac_db.context, expected_lv_ac_ctx) # Check graph. self.assertIsNotNone(wf_ex_db.graph) self.assertTrue(isinstance(wf_ex_db.graph, dict)) self.assertIn('nodes', wf_ex_db.graph) self.assertIn('adjacency', wf_ex_db.graph) # Check task flow. self.assertIsNotNone(wf_ex_db.flow) self.assertTrue(isinstance(wf_ex_db.flow, dict)) self.assertIn('tasks', wf_ex_db.flow) self.assertIn('sequence', wf_ex_db.flow) # Check input. self.assertDictEqual(wf_ex_db.input, wf_input) # Assert task1 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.context.get('user'), username) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue( wf_svc.is_action_execution_under_workflow_context(tk1_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert task1 succeeded and workflow is still running. tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Assert task2 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2' } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.context.get('user'), username) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue( wf_svc.is_action_execution_under_workflow_context(tk2_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task2 succeeded and workflow is still running. tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Assert task3 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3' } tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.context.get('user'), username) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue( wf_svc.is_action_execution_under_workflow_context(tk3_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check post run is invoked for the liveaction. self.assertTrue(runners_utils.invoke_post_run.called) self.assertEqual(runners_utils.invoke_post_run.call_count, 1) # Check workflow output. expected_output = { 'msg': '%s, All your base are belong to us!' % wf_input['who'] } self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def assert_data_flow(self, data): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'data-flow.yaml') wf_input = {'a1': data} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Assert task1 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert task1 succeeded and workflow is still running. tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task2 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task2 succeeded and workflow is still running. tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task3 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert task3 succeeded and workflow is completed. tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. expected_output = { 'a5': wf_input['a1'] if six.PY3 else wf_input['a1'].decode('utf-8'), 'b5': wf_input['a1'] if six.PY3 else wf_input['a1'].decode('utf-8') } self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_run_workflow(self): username = '******' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # The main action execution for this workflow is not under the context of another workflow. self.assertFalse(wf_svc.is_action_execution_under_workflow_context(ac_ex_db)) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertTrue(lv_ac_db.action_is_workflow) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] # Check required attributes. self.assertEqual(len(wf_ex_dbs), 1) self.assertIsNotNone(wf_ex_db.id) self.assertGreater(wf_ex_db.rev, 0) self.assertEqual(wf_ex_db.action_execution, str(ac_ex_db.id)) self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Check context in the workflow execution. expected_wf_ex_ctx = { 'st2': { 'workflow_execution_id': str(wf_ex_db.id), 'action_execution_id': str(ac_ex_db.id), 'api_url': 'http://127.0.0.1/v1', 'user': username, 'pack': 'orquesta_tests' }, 'parent': { 'pack': 'orquesta_tests' } } self.assertDictEqual(wf_ex_db.context, expected_wf_ex_ctx) # Check context in the liveaction. expected_lv_ac_ctx = { 'workflow_execution': str(wf_ex_db.id), 'pack': 'orquesta_tests' } self.assertDictEqual(lv_ac_db.context, expected_lv_ac_ctx) # Check graph. self.assertIsNotNone(wf_ex_db.graph) self.assertTrue(isinstance(wf_ex_db.graph, dict)) self.assertIn('nodes', wf_ex_db.graph) self.assertIn('adjacency', wf_ex_db.graph) # Check task states. self.assertIsNotNone(wf_ex_db.state) self.assertTrue(isinstance(wf_ex_db.state, dict)) self.assertIn('tasks', wf_ex_db.state) self.assertIn('sequence', wf_ex_db.state) # Check input. self.assertDictEqual(wf_ex_db.input, wf_input) # Assert task1 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1'} tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.context.get('user'), username) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(wf_svc.is_action_execution_under_workflow_context(tk1_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert task1 succeeded and workflow is still running. tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task2 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.context.get('user'), username) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(wf_svc.is_action_execution_under_workflow_context(tk2_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task2 succeeded and workflow is still running. tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task3 is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3'} tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id(tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.context.get('user'), username) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(wf_svc.is_action_execution_under_workflow_context(tk3_ac_ex_db)) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check post run is invoked for the liveaction. self.assertTrue(runners_utils.invoke_post_run.called) self.assertEqual(runners_utils.invoke_post_run.call_count, 1) # Check workflow output. expected_output = {'msg': '%s, All your base are belong to us!' % wf_input['who']} self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)
def test_rerun_with_missing_workflow_execution_id(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, "sequential.yaml") wf_input = {"who": "Thanos"} lv_ac_db1 = lv_db_models.LiveActionDB(action=wf_meta["name"], parameters=wf_input) lv_ac_db1, ac_ex_db1 = action_service.request(lv_ac_db1) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db1.id))[0] # Process task1. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task1" } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction["id"]) self.assertEqual(tk1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_FAILED) workflow_service.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.FAILED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) lv_ac_db1 = lv_db_access.LiveAction.get_by_id(str(lv_ac_db1.id)) self.assertEqual(lv_ac_db1.status, action_constants.LIVEACTION_STATUS_FAILED) ac_ex_db1 = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db1.id)) self.assertEqual(ac_ex_db1.status, action_constants.LIVEACTION_STATUS_FAILED) # Delete the workflow execution. wf_db_access.WorkflowExecution.delete(wf_ex_db, publish=False) # Manually delete the workflow_execution_id from context of the action execution. lv_ac_db1.context.pop("workflow_execution") lv_ac_db1 = lv_db_access.LiveAction.add_or_update(lv_ac_db1, publish=False) ac_ex_db1 = execution_service.update_execution(lv_ac_db1, publish=False) # Rerun the execution. context = {"re-run": {"ref": str(ac_ex_db1.id), "tasks": ["task1"]}} lv_ac_db2 = lv_db_models.LiveActionDB(action=wf_meta["name"], context=context) lv_ac_db2, ac_ex_db2 = action_service.request(lv_ac_db2) expected_error = ("Unable to rerun workflow execution because " "workflow_execution_id is not provided.") # Assert the workflow rerrun fails. lv_ac_db2 = lv_db_access.LiveAction.get_by_id(str(lv_ac_db2.id)) self.assertEqual(lv_ac_db2.status, action_constants.LIVEACTION_STATUS_FAILED) self.assertEqual(expected_error, lv_ac_db2.result["errors"][0]["message"]) ac_ex_db2 = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db2.id)) self.assertEqual(ac_ex_db2.status, action_constants.LIVEACTION_STATUS_FAILED) self.assertEqual(expected_error, ac_ex_db2.result["errors"][0]["message"])
def test_include_result_to_error_log(self): username = '******' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_dbs = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] # Assert task1 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.context.get('user'), username) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually override and fail the action execution and write some result. # Action execution result can contain dotted notation so ensure this is tested. result = {"127.0.0.1": {"hostname": "foobar"}} ac_svc.update_status(tk1_lv_ac_db, ac_const.LIVEACTION_STATUS_FAILED, result=result, publish=False) tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(tk1_lv_ac_db.result, result) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert task and workflow failed. tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.FAILED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) # Assert result is included in the error log. expected_errors = [{ 'message': 'Execution failed. See result for details.', 'type': 'error', 'task_id': 'task1', 'result': { '127.0.0.1': { 'hostname': 'foobar' } } }] self.assertListEqual(wf_ex_db.errors, expected_errors)
def test_fail_manually_with_recovery_failure(self): wf_file = 'fail-manually-with-recovery-failure.yaml' wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_file) lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id))[0] # Assert task1 and workflow execution failed due to fail in the task transition. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) wf_svc.handle_action_execution_completion(tk1_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) # Assert recover task is scheduled even though the workflow execution failed manually. # The recover task in the workflow is setup to fail. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'recover' } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_FAILED) wf_svc.handle_action_execution_completion(tk2_ac_ex_db) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.FAILED) # Check errors and output. expected_errors = [{ 'task_id': 'fail', 'type': 'error', 'message': 'Execution failed. See result for details.' }, { 'task_id': 'recover', 'type': 'error', 'message': 'Execution failed. See result for details.', 'result': { 'failed': True, 'return_code': 1, 'stderr': '', 'stdout': '', 'succeeded': False } }, { 'task_id': 'task1', 'type': 'error', 'message': 'Execution failed. See result for details.', 'result': { 'failed': True, 'return_code': 1, 'stderr': '', 'stdout': '', 'succeeded': False } }] self.assertListEqual(self.sort_workflow_errors(wf_ex_db.errors), expected_errors)
def test_cascade_notify_to_tasks(self): wf_input = {"notify": ["task2"]} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, "sequential.yaml") lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta["name"], parameters=wf_input) lv_ac_db.notify = notify_api_models.NotificationsHelper.to_model( MOCK_NOTIFY) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_RUNNING) wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id))[0] self.assertEqual(wf_ex_db.status, action_constants.LIVEACTION_STATUS_RUNNING) # Assert task1 notify is not set. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task1" } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction["id"]) self.assertIsNone(tk1_lv_ac_db.notify) self.assertEqual(tk1_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertFalse(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock() # Handle task1 completion. workflow_service.handle_action_execution_completion(tk1_ac_ex_db) tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task2 notify is set. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task2" } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction["id"]) notify = notify_api_models.NotificationsHelper.from_model( notify_model=tk2_lv_ac_db.notify) self.assertEqual(notify, MOCK_NOTIFY) self.assertEqual(tk2_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock() # Handle task2 completion. workflow_service.handle_action_execution_completion(tk2_ac_ex_db) tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_statuses.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert task3 notify is not set. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task3" } tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction["id"]) self.assertIsNone(tk3_lv_ac_db.notify) self.assertEqual(tk3_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertFalse(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock() # Handle task3 completion. workflow_service.handle_action_execution_completion(tk3_ac_ex_db) tk3_ex_db = wf_db_access.TaskExecution.get_by_id(tk3_ex_db.id) self.assertEqual(tk3_ex_db.status, wf_statuses.SUCCEEDED) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertTrue(notifier.Notifier._post_notify_triggers.called) notifier.Notifier._post_notify_triggers.reset_mock()
def test_run_workflow(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') wf_input = {'who': 'Thanos'} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = ac_svc.request(lv_ac_db) # Assert action execution is running. lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertTrue(lv_ac_db.action_is_workflow) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING, lv_ac_db.result) wf_ex_dbs = wf_db_access.WorkflowExecution.query( action_execution=str(ac_ex_db.id)) wf_ex_db = wf_ex_dbs[0] # Check required attributes. self.assertEqual(len(wf_ex_dbs), 1) self.assertIsNotNone(wf_ex_db.id) self.assertGreater(wf_ex_db.rev, 0) self.assertEqual(wf_ex_db.action_execution, str(ac_ex_db.id)) self.assertEqual(wf_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Check context. self.assertIn('workflow_execution', lv_ac_db.context) self.assertEqual(lv_ac_db.context['workflow_execution'], str(wf_ex_db.id)) # Check graph. self.assertIsNotNone(wf_ex_db.graph) self.assertTrue(isinstance(wf_ex_db.graph, dict)) self.assertIn('nodes', wf_ex_db.graph) self.assertIn('adjacency', wf_ex_db.graph) # Check task flow. self.assertIsNotNone(wf_ex_db.flow) self.assertTrue(isinstance(wf_ex_db.flow, dict)) self.assertIn('tasks', wf_ex_db.flow) self.assertIn('sequence', wf_ex_db.flow) # Check input. self.assertDictEqual(wf_ex_db.input, wf_input) # Assert task1 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } tk1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk1_ex_db.id))[0] tk1_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk1_ac_ex_db.liveaction['id']) self.assertEqual(tk1_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk1_ac_ex_db) # Assert task1 succeeded and workflow is still running. tk1_ex_db = wf_db_access.TaskExecution.get_by_id(tk1_ex_db.id) self.assertEqual(tk1_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Assert task2 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2' } tk2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk2_ex_db.id))[0] tk2_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk2_ac_ex_db.liveaction['id']) self.assertEqual(tk2_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk2_ac_ex_db) # Assert task2 succeeded and workflow is still running. tk2_ex_db = wf_db_access.TaskExecution.get_by_id(tk2_ex_db.id) self.assertEqual(tk2_ex_db.status, wf_states.SUCCEEDED) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Assert task3 is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task3' } tk3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] tk3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk3_ex_db.id))[0] tk3_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk3_ac_ex_db.liveaction['id']) self.assertEqual(tk3_lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Manually handle action execution completion. wf_svc.handle_action_execution_completion(tk3_ac_ex_db) # Assert workflow is completed. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.SUCCEEDED) lv_ac_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(ac_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) # Check workflow output. expected_output = { 'msg': '%s, All your base are belong to us!' % wf_input['who'] } self.assertDictEqual(wf_ex_db.output, expected_output) # Check liveaction and action execution result. expected_result = {'output': expected_output} self.assertDictEqual(lv_ac_db.result, expected_result) self.assertDictEqual(ac_ex_db.result, expected_result)