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_workflow_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 test_fail_next_task_input_expr_eval(self): expected_errors = [{ "type": "error", "message": ("YaqlEvaluationException: Unable to evaluate expression " "'<% ctx().msg2.value %>'. NoFunctionRegisteredException: " 'Unknown function "#property#value"'), "task_id": "task2", "route": 0, }] 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_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_workflow_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_next_task_action(self): expected_errors = [{ 'type': 'error', 'message': ('YaqlEvaluationException: Unable to evaluate expression ' '\'<% ctx().func.value %>\'. NoFunctionRegisteredException: ' 'Unknown function "#property#value"'), 'task_id': 'task2', 'route': 0 }] expected_result = {'output': None, 'errors': expected_errors} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-task-action.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_transition(self): expected_errors = [{ "type": "error", "message": ("YaqlEvaluationException: Unable to resolve key 'foobar' in expression " "'<% succeeded() and result().foobar %>' from context."), "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-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_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_workflow_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", "action": "orquesta_tests.runtime-context", "runner": "orquesta", } 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_request_wf_def_with_unregistered_action(self): wf_meta = self.get_wf_fixture_meta_data( TEST_PACK_PATH, 'fail-inspection-action-db.yaml') # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Exception is expected on request of workflow execution. self.assertRaises(orquesta_exc.WorkflowInspectionError, workflow_service.request, self.get_wf_def(TEST_PACK_PATH, wf_meta), ac_ex_db, self.mock_st2_context(ac_ex_db))
def test_no_notify(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 = 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) # Check that notify is setup correctly in the db record. self.assertDictEqual(wf_ex_db.notify, {})
def test_request_rerun_while_original_is_still_running(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, "sequential.yaml") # Manually create the liveaction and action execution objects without publishing. lv_ac_db1 = lv_db_models.LiveActionDB(action=wf_meta["name"]) lv_ac_db1, ac_ex_db1 = action_service.create_request(lv_ac_db1) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db1) wf_ex_db = workflow_service.request(wf_def, ac_ex_db1, st2_ctx) wf_ex_db = self.prep_wf_ex(wf_ex_db) # Check workflow status. conductor, wf_ex_db = workflow_service.refresh_conductor( str(wf_ex_db.id)) self.assertEqual(conductor.get_workflow_status(), wf_statuses.RUNNING) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Manually create the liveaction and action execution objects for the rerun. lv_ac_db2 = lv_db_models.LiveActionDB(action=wf_meta["name"]) lv_ac_db2, ac_ex_db2 = action_service.create_request(lv_ac_db2) # Request workflow execution rerun. st2_ctx = self.mock_st2_context(ac_ex_db2, ac_ex_db1.context) st2_ctx["workflow_execution_id"] = str(wf_ex_db.id) rerun_options = {"ref": str(ac_ex_db1.id), "tasks": ["task1"]} expected_error = ('^Unable to rerun workflow execution ".*" ' "because it is not in a completed state.$") self.assertRaisesRegexp( wf_exc.WorkflowExecutionRerunException, expected_error, workflow_service.request_rerun, ac_ex_db2, st2_ctx, rerun_options, )
def test_cancel(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) requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = ac_svc.request_cancellation(lv_ac_db, requester) 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)
def test_request_task_execution(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Manually request task execution. task_route = 0 task_id = 'task1' task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} st2_ctx = {'execution_id': wf_ex_db.action_execution} task_ex_req = { 'id': task_id, 'route': task_route, 'spec': task_spec, 'ctx': task_ctx, 'actions': [ {'action': 'core.echo', 'input': {'message': 'Veni, vidi, vici.'}} ] } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) # Check required attributes. task_ex_db = task_ex_dbs[0] self.assertIsNotNone(task_ex_db.id) self.assertGreater(task_ex_db.rev, 0) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) self.assertEqual(task_ex_db.status, wf_statuses.RUNNING) # Check action execution for the task query with task execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(task_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1) # Check action execution for the task query with workflow execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1)
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_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_notify_task_list_item_value(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.notify = notify_api_models.NotificationsHelper.to_model(MOCK_NOTIFY) expected_schema_success_test_cases = [[], ["task1"], ["task1", "task2"]] for notify_tasks in expected_schema_success_test_cases: lv_ac_db.parameters = {"notify": notify_tasks} lv_ac_db, ac_ex_db = action_service.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, action_constants.LIVEACTION_STATUS_RUNNING )
def test_process_error_handling(self): expected_errors = [ { "message": "Execution failed. See result for details.", "type": "error", "task_id": "task1", }, { "type": "error", "message": "ToozConnectionError: foobar", "task_id": "task1", "route": 0, }, ] wf_meta = self.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 = 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) # Process task1. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task1" } t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id))[0] workflows.get_engine().process(t1_ac_ex_db) # Assert the task is marked as failed. t1_ex_db = wf_db_access.TaskExecution.get_by_id(str(t1_ex_db.id)) self.assertEqual(t1_ex_db.status, wf_statuses.FAILED) # Assert the workflow has failed with expected errors. 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(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, action_constants.LIVEACTION_STATUS_FAILED)
def test_fail_inspection(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-inspection.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_FAILED) self.assertIn('errors', lv_ac_db.result) self.assertIn('expressions', lv_ac_db.result['errors']) self.assertGreater(len(lv_ac_db.result['errors']['expressions']), 0) self.assertIn('context', lv_ac_db.result['errors']) self.assertGreater(len(lv_ac_db.result['errors']['context']), 0) self.assertIn('syntax', lv_ac_db.result['errors']) self.assertGreater(len(lv_ac_db.result['errors']['syntax']), 0)
def test_cancel_subworkflow_cascade_up_to_workflow(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'subworkflow.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), 1) tk_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(tk_ex_dbs[0].id)) self.assertEqual(len(tk_ac_ex_dbs), 1) tk_lv_ac_db = lv_db_access.LiveAction.get_by_id( tk_ac_ex_dbs[0].liveaction['id']) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_RUNNING) # Cancel the subworkflow. requester = cfg.CONF.system_user.user tk_lv_ac_db, tk_ac_ex_db = ac_svc.request_cancellation( tk_lv_ac_db, requester) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELING) # Assert the subworkflow is canceled. tk_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(tk_lv_ac_db.id)) self.assertEqual(tk_lv_ac_db.status, ac_const.LIVEACTION_STATUS_CANCELED) # Manually handle action execution completion for the task. tk_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(tk_ac_ex_db.id)) self.assertEqual(tk_ac_ex_db.status, ac_const.LIVEACTION_STATUS_CANCELED) wf_svc.handle_action_execution_completion(tk_ac_ex_db) # Assert the main workflow is canceled. 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_fail_inspection(self): expected_errors = [{ 'type': 'content', 'message': 'The action "std.noop" is not registered in the database.', 'schema_path': 'properties.tasks.patternProperties.^\w+$.properties.action', 'spec_path': 'tasks.task3.action' }, { 'type': 'context', 'language': 'yaql', 'expression': '<% ctx().foobar %>', 'message': 'Variable "foobar" is referenced before assignment.', 'schema_path': 'properties.tasks.patternProperties.^\w+$.properties.input', 'spec_path': 'tasks.task1.input', }, { 'type': 'expression', 'language': 'yaql', 'expression': '<% <% succeeded() %>', 'message': ('Parse error: unexpected \'<\' at ' 'position 0 of expression \'<% succeeded()\''), 'schema_path': ('properties.tasks.patternProperties.^\w+$.' 'properties.next.items.properties.when'), 'spec_path': 'tasks.task2.next[0].when' }, { 'type': 'syntax', 'message': ('[{\'cmd\': \'echo <% ctx().macro %>\'}] is ' 'not valid under any of the given schemas'), 'schema_path': 'properties.tasks.patternProperties.^\w+$.properties.input.oneOf', 'spec_path': 'tasks.task2.input' }] wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'fail-inspection.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_FAILED) self.assertIn('errors', lv_ac_db.result) self.assertListEqual(lv_ac_db.result['errors'], expected_errors)
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_workflow_errors(wf_ex_db.errors), expected_errors)
def test_with_items_failure(self): num_items = 10 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-failure.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) 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) # Process the with items task. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) self.assertEqual(len(t1_ac_ex_dbs), num_items) for i in range(0, num_items): if not i % 2: expected_status = action_constants.LIVEACTION_STATUS_SUCCEEDED else: expected_status = action_constants.LIVEACTION_STATUS_FAILED self.assertEqual(t1_ac_ex_dbs[i].status, expected_status) for t1_ac_ex_db in t1_ac_ex_dbs: workflows.get_engine().process(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(t1_ex_db.id) self.assertEqual(t1_ex_db.status, wf_statuses.FAILED) # Assert the main 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_db = lv_db_access.LiveAction.get_by_id(str(lv_ac_db.id)) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_FAILED)
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_process_error_handling_has_error(self): wf_meta = self.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 = 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) # Process task1. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'task1' } t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id))[0] self.assertRaisesRegexp(Exception, 'Unexpected error.', workflows.get_engine().process, t1_ac_ex_db) self.assertTrue( workflows.WorkflowExecutionHandler.fail_workflow_execution.called) # Since error handling failed, the workflow will have status of running. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.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) # Sleep up to the test config gc_max_idle_sec before running gc. eventlet.sleep(cfg.CONF.workflow_engine.gc_max_idle_sec) # Run garbage collection. gc = garbage_collector.GarbageCollectorService() gc._purge_orphaned_workflow_executions() # Assert workflow execution is cleaned up and canceled. 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_CANCELED)
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_cancel_before_wf_ex_db_created(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) # Delete the workfow execution to mock issue where the record has not been created yet. wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id))[0] wf_db_access.WorkflowExecution.delete(wf_ex_db, publish=False, dispatch_trigger=False) # Cancel the action execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = ac_svc.request_cancellation(lv_ac_db, requester) 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_with_items(self): num_items = 3 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, "with-items.yaml") lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta["name"]) 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) # Process the with items task. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task1" } t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) self.assertEqual(len(t1_ac_ex_dbs), num_items) status = [ ac_ex.status == action_constants.LIVEACTION_STATUS_SUCCEEDED for ac_ex in t1_ac_ex_dbs ] self.assertTrue(all(status)) for t1_ac_ex_db in t1_ac_ex_dbs: workflows.get_engine().process(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(t1_ex_db.id) self.assertEqual(t1_ex_db.status, wf_statuses.SUCCEEDED) # Assert the main 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)
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_workflow_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_request_rerun_with_missing_workflow_execution_id(self): # Create and return a failed workflow execution. wf_meta, lv_ac_db1, ac_ex_db1, wf_ex_db = self.prep_wf_ex_for_rerun() # Manually create the liveaction and action execution objects for the rerun. lv_ac_db2 = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db2, ac_ex_db2 = action_service.create_request(lv_ac_db2) # Request workflow execution rerun without workflow_execution_id. st2_ctx = self.mock_st2_context(ac_ex_db2, ac_ex_db1.context) rerun_options = {'ref': str(ac_ex_db1.id), 'tasks': ['task1']} expected_error = ('Unable to rerun workflow execution because ' 'workflow_execution_id is not provided.') self.assertRaisesRegexp(wf_exc.WorkflowExecutionRerunException, expected_error, workflow_service.request_rerun, ac_ex_db2, st2_ctx, rerun_options)
def test_request_rerun_with_bad_task_name(self): # Create and return a failed workflow execution. wf_meta, lv_ac_db1, ac_ex_db1, wf_ex_db = self.prep_wf_ex_for_rerun() # Manually create the liveaction and action execution objects for the rerun. lv_ac_db2 = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db2, ac_ex_db2 = action_service.create_request(lv_ac_db2) # Request workflow execution. st2_ctx = self.mock_st2_context(ac_ex_db2, ac_ex_db1.context) st2_ctx['workflow_execution_id'] = str(wf_ex_db.id) rerun_options = {'ref': str(ac_ex_db1.id), 'tasks': ['task5354']} expected_error = '^Unable to rerun workflow because one or more tasks is not found: .*$' self.assertRaisesRegexp(wf_exc.WorkflowExecutionRerunException, expected_error, workflow_service.request_rerun, ac_ex_db2, st2_ctx, rerun_options)
def test_request_task_execution_bad_action(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, "sequential.yaml") # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta["name"]) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec["catalog"]) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Manually request task execution. task_route = 0 task_id = "task1" task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {"foo": "bar"} st2_ctx = {"execution_id": wf_ex_db.action_execution} task_ex_req = { "id": task_id, "route": task_route, "spec": task_spec, "ctx": task_ctx, "actions": [{ "action": "mock.echo", "input": { "message": "Veni, vidi, vici." } }], } self.assertRaises( action_exc.InvalidActionReferencedException, workflow_service.request_task_execution, wf_ex_db, st2_ctx, task_ex_req, )
def test_request_wf_def_with_missing_required_action_param(self): wf_name = "fail-inspection-missing-required-action-param" wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, wf_name + ".yaml") # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta["name"]) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Exception is expected on request of workflow execution. self.assertRaises( orquesta_exc.WorkflowInspectionError, workflow_service.request, self.get_wf_def(TEST_PACK_PATH, wf_meta), ac_ex_db, self.mock_st2_context(ac_ex_db), )