def test_subworkflow_with_items_empty_list(self): wf_input = {'members': []} wf_meta = base.get_wf_fixture_meta_data( TEST_PACK_PATH, 'with-items-empty-parent.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # 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), 1) # Identify the records for the tasks. t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk_ex_dbs[0].id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(t1_wf_ex_db.status, wf_statuses.SUCCEEDED) # Manually processing completion of the subworkflow in task1. workflows.get_engine().process(t1_ac_ex_db) t1_ex_db = wf_db_access.TaskExecution.get_by_id(tk_ex_dbs[0].id) self.assertEqual(t1_ex_db.status, wf_statuses.SUCCEEDED) # Check that the workflow execution 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_retry_policy_applied_on_workflow_failure(self): wf_name = 'sequential' wf_ac_ref = TEST_PACK + '.' + wf_name 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) # Ensure there is only one execution recorded. self.assertEqual(len(lv_db_access.LiveAction.query(action=wf_ac_ref)), 1) # Identify the records for the workflow and task. 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_lv_ac_db = lv_db_access.LiveAction.query(task_execution=str(t1_ex_db.id))[0] t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id))[0] # Manually set the status to fail. ac_svc.update_status(t1_lv_ac_db, ac_const.LIVEACTION_STATUS_FAILED) t1_lv_ac_db = lv_db_access.LiveAction.query(task_execution=str(t1_ex_db.id))[0] t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id))[0] self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) notifier.get_notifier().process(t1_ac_ex_db) workflows.get_engine().process(t1_ac_ex_db) # Assert the main workflow is completed. 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) notifier.get_notifier().process(ac_ex_db) # Ensure execution is retried. self.assertEqual(len(lv_db_access.LiveAction.query(action=wf_ac_ref)), 2)
def publish_state(cls, payload, state): try: if isinstance(payload, wf_ex_db.WorkflowExecutionDB): workflows.get_engine().process(payload) except Exception: traceback.print_exc() print(payload)
def test_process_error_handling(self, mock_get_lock): expected_errors = [ { "message": "Execution failed. See result for details.", "type": "error", "task_id": "task1", }, { "type": "error", "message": "ToozConnectionError: foobar", "task_id": "task1", "route": 0, }, ] mock_get_lock.side_effect = coordination_service.NoOpLock(name="noop") 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] mock_get_lock.side_effect = [ coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination_service.NoOpLock(name="noop"), coordination_service.NoOpLock(name="noop"), ] 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_pause_workflow_cascade_down_to_subworkflow(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 main workflow. wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(ac_ex_db.id)) self.assertEqual(len(wf_ex_dbs), 1) wf_ex_db = wf_ex_dbs[0] tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 1) tk_ex_db = tk_ex_dbs[0] tk_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_db.id)) self.assertEqual(len(tk_ac_ex_dbs), 1) tk_ac_ex_db = tk_ac_ex_dbs[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_RUNNING) # Identify the records for the subworkflow. sub_wf_ex_dbs = wf_db_access.WorkflowExecution.query(action_execution=str(tk_ac_ex_db.id)) self.assertEqual(len(sub_wf_ex_dbs), 1) sub_wf_ex_db = sub_wf_ex_dbs[0] sub_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(sub_wf_ex_db.id)) self.assertEqual(len(sub_tk_ex_dbs), 1) sub_tk_ex_db = sub_tk_ex_dbs[0] sub_tk_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(sub_tk_ex_db.id)) self.assertEqual(len(sub_tk_ac_ex_dbs), 1) # Pause the main workflow and assert it is pausing because subworkflow is still running. lv_ac_db, ac_ex_db = ac_svc.request_pause(lv_ac_db, cfg.CONF.system_user.user) self.assertEqual(lv_ac_db.status, ac_const.LIVEACTION_STATUS_PAUSING) # Assert the subworkflow is pausing. 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_PAUSING) # Manually handle action execution completion for the task in the subworkflow. sub_tk_ac_ex_db = sub_tk_ac_ex_dbs[0] self.assertEqual(sub_tk_ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(sub_tk_ac_ex_db) # Assert the subworkflow is paused and manually process the execution update. 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_PAUSED) 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_PAUSED) workflows.get_engine().process(tk_ac_ex_db) # Assert the main 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)
def test_delay_for_with_items(self): expected_delay_sec = 1 expected_delay_msec = expected_delay_sec * 1000 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-delay.yaml') wf_input = {'delay': expected_delay_sec} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert action execution is running. lv_ac_db = self._wait_on_status( lv_ac_db, 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)) t1_lv_ac_dbs = lv_db_access.LiveAction.query( task_execution=str(t1_ex_db.id)) # Assert delay value is rendered and assigned. self.assertEqual(t1_ex_db.delay, expected_delay_sec) for t1_lv_ac_db in t1_lv_ac_dbs: self.assertEqual(t1_lv_ac_db.delay, expected_delay_msec) for t1_ac_ex_db in t1_ac_ex_dbs: self.assertEqual(t1_ac_ex_db.delay, expected_delay_msec) 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_states.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_states.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_no_retry_policy_applied_on_task_failure(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 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), 1) # Identify the records for the tasks. t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(tk_ex_dbs[0].id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_statuses.RUNNING) # Ensure there is only one execution for the task. tk_ac_ref = TEST_PACK + '.' + 'sequential' self.assertEqual(len(lv_db_access.LiveAction.query(action=tk_ac_ref)), 1) # Fail the subtask of the subworkflow. t1_t1_ex_db = wf_db_access.TaskExecution.query( workflow_execution=str(t1_wf_ex_db.id))[0] t1_t1_lv_ac_db = lv_db_access.LiveAction.query( task_execution=str(t1_t1_ex_db.id))[0] ac_svc.update_status(t1_t1_lv_ac_db, ac_const.LIVEACTION_STATUS_FAILED) t1_t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t1_t1_ex_db.id))[0] self.assertEqual(t1_t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) notifier.get_notifier().process(t1_t1_ac_ex_db) workflows.get_engine().process(t1_t1_ac_ex_db) # Ensure the task execution is not retried. self.assertEqual(len(lv_db_access.LiveAction.query(action=tk_ac_ref)), 1) # Process the failure of the subworkflow. t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(t1_ac_ex_db.id)) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) workflows.get_engine().process(t1_ac_ex_db) # Assert the main workflow is completed. 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)
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_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_delay_for_with_items(self): expected_delay_sec = 1 expected_delay_msec = expected_delay_sec * 1000 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-delay.yaml') wf_input = {'delay': expected_delay_sec} lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert action execution is running. lv_ac_db = self._wait_on_status(lv_ac_db, 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)) t1_lv_ac_dbs = lv_db_access.LiveAction.query(task_execution=str(t1_ex_db.id)) # Assert delay value is rendered and assigned. self.assertEqual(t1_ex_db.delay, expected_delay_sec) for t1_lv_ac_db in t1_lv_ac_dbs: self.assertEqual(t1_lv_ac_db.delay, expected_delay_msec) for t1_ac_ex_db in t1_ac_ex_dbs: self.assertEqual(t1_ac_ex_db.delay, expected_delay_msec) 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_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 publish_state(cls, payload, state): try: if isinstance(payload, wf_ex_db.WorkflowExecutionDB): thread = eventlet.spawn(workflows.get_engine().process, payload) cls.threads.append(thread) except Exception: traceback.print_exc() print(payload)
def test_process_error_handling_has_error(self, mock_get_lock): mock_get_lock.side_effect = coordination_service.NoOpLock(name="noop") 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] mock_get_lock.side_effect = [ coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), coordination.ToozConnectionError("foobar"), ] self.assertRaisesRegexp(Exception, "Unexpected error.", workflows.get_engine().process, t1_ac_ex_db) self.assertTrue( workflows.WorkflowExecutionHandler.fail_workflow_execution.called) mock_get_lock.side_effect = coordination_service.NoOpLock(name="noop") # 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_no_retry_policy_applied_on_task_failure(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 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), 1) # Identify the records for the tasks. t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[0].id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_statuses.RUNNING) # Ensure there is only one execution for the task. tk_ac_ref = TEST_PACK + '.' + 'sequential' self.assertEqual(len(lv_db_access.LiveAction.query(action=tk_ac_ref)), 1) # Fail the subtask of the subworkflow. t1_t1_ex_db = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id))[0] t1_t1_lv_ac_db = lv_db_access.LiveAction.query(task_execution=str(t1_t1_ex_db.id))[0] ac_svc.update_status(t1_t1_lv_ac_db, ac_const.LIVEACTION_STATUS_FAILED) t1_t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t1_t1_ex_db.id))[0] self.assertEqual(t1_t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) notifier.get_notifier().process(t1_t1_ac_ex_db) workflows.get_engine().process(t1_t1_ac_ex_db) # Ensure the task execution is not retried. self.assertEqual(len(lv_db_access.LiveAction.query(action=tk_ac_ref)), 1) # Process the failure of the subworkflow. t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(t1_ac_ex_db.id)) self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_FAILED) workflows.get_engine().process(t1_ac_ex_db) # Assert the main workflow is completed. 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)
def test_process(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] 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) # Process task2. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task2" } t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_ex_db.id))[0] workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_ex_db.status, wf_statuses.SUCCEEDED) # Process task3. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "task3" } t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t3_ex_db.id))[0] workflows.get_engine().process(t3_ac_ex_db) t3_ex_db = wf_db_access.TaskExecution.get_by_id(t3_ex_db.id) self.assertEqual(t3_ex_db.status, wf_statuses.SUCCEEDED) # Assert the workflow has completed successfully with expected output. expected_output = {"msg": "Stanley, All your base are belong to us!"} wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.SUCCEEDED) 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, action_constants.LIVEACTION_STATUS_SUCCEEDED)
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 run_server(): LOG.info('(PID=%s) Workflow engine started.', os.getpid()) engine = workflows.get_engine() try: engine.start(wait=True) except (KeyboardInterrupt, SystemExit): LOG.info('(PID=%s) Workflow engine stopped.', os.getpid()) engine.shutdown() except: LOG.exception('(PID=%s) Workflow engine unexpectedly stopped.', os.getpid()) return 1 return 0
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 run_server(): LOG.info("(PID=%s) Workflow engine started.", os.getpid()) engine = workflows.get_engine() setup_sigterm_handler(engine) try: engine.start(wait=True) except (KeyboardInterrupt, SystemExit): LOG.info("(PID=%s) Workflow engine stopped.", os.getpid()) deregister_service(service=WORKFLOW_ENGINE) engine.shutdown() except: LOG.exception("(PID=%s) Workflow engine unexpectedly stopped.", os.getpid()) return 1 return 0
def test_parallel_inquiries(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, "ask-parallel-approvals.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) # Assert start task is already completed. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "start" } 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] t1_lv_ac_db = lv_db_access.LiveAction.get_by_id( t1_ac_ex_db.liveaction["id"]) self.assertEqual(t1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) 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 still running. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert get approval task is already pending. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "ask_jack" } t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_ex_db.id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_ac_ex_db.liveaction["id"]) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_PENDING) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_ex_db.status, wf_statuses.PENDING) # Assert the main workflow is paused since it has no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSING) # Assert get approval task is already pending. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "ask_jill" } t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[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, action_constants.LIVEACTION_STATUS_PENDING) workflows.get_engine().process(t3_ac_ex_db) t3_ex_db = wf_db_access.TaskExecution.get_by_id(t3_ex_db.id) self.assertEqual(t3_ex_db.status, wf_statuses.PENDING) # Assert the main workflow is paused since it has no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) # Respond to the inquiry and check status. inquiry_api = inqy_api_models.InquiryAPI.from_model(t2_ac_ex_db) inquiry_response = {"approved": True} inquiry_service.respond(inquiry_api, inquiry_response) t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t2_lv_ac_db.id)) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) t2_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(t2_ac_ex_db.id)) self.assertEqual(t2_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(str(t2_ex_db.id)) self.assertEqual(t2_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Assert the main workflow is paused because we are still waiting for # the other pending task and there are no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) # Respond to the inquiry and check status. inquiry_api = inqy_api_models.InquiryAPI.from_model(t3_ac_ex_db) inquiry_response = {"approved": True} inquiry_service.respond(inquiry_api, inquiry_response) t3_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t3_lv_ac_db.id)) self.assertEqual(t3_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) t3_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(t3_ac_ex_db.id)) self.assertEqual(t3_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t3_ac_ex_db) t3_ex_db = wf_db_access.TaskExecution.get_by_id(str(t3_ex_db.id)) self.assertEqual(t3_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Assert the main workflow resumed running. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert the final task is completed. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "finish" } t4_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t4_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t4_ex_db.id))[0] t4_lv_ac_db = lv_db_access.LiveAction.get_by_id( t4_ac_ex_db.liveaction["id"]) self.assertEqual(t4_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t4_ac_ex_db) t4_ex_db = wf_db_access.TaskExecution.get_by_id(t4_ex_db.id) self.assertEqual(t4_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)
def test_nested_inquiry(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, "ask-nested-approval.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) # Assert start task is already completed. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "start" } 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] t1_lv_ac_db = lv_db_access.LiveAction.get_by_id( t1_ac_ex_db.liveaction["id"]) self.assertEqual(t1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) 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 still running. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert the subworkflow is already started. query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "get_approval", } t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_ex_db.id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_ac_ex_db.liveaction["id"]) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_RUNNING) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_ex_db.status, wf_statuses.RUNNING) t2_wf_ex_db = wf_db_access.WorkflowExecution.query( action_execution=str(t2_ac_ex_db.id))[0] self.assertEqual(t2_wf_ex_db.status, wf_statuses.RUNNING) # Process task1 of subworkflow. query_filters = { "workflow_execution": str(t2_wf_ex_db.id), "task_id": "start" } t2_t1_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_t1_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_t1_ex_db.id))[0] t2_t1_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_t1_ac_ex_db.liveaction["id"]) self.assertEqual(t2_t1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_t1_ac_ex_db) t2_t1_ex_db = wf_db_access.TaskExecution.get_by_id(t2_t1_ex_db.id) self.assertEqual(t2_t1_ex_db.status, wf_statuses.SUCCEEDED) t2_wf_ex_db = wf_db_access.WorkflowExecution.get_by_id( str(t2_wf_ex_db.id)) self.assertEqual(t2_wf_ex_db.status, wf_statuses.RUNNING) # Process inquiry task of subworkflow and assert the subworkflow is paused. query_filters = { "workflow_execution": str(t2_wf_ex_db.id), "task_id": "get_approval", } t2_t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_t2_ex_db.id))[0] t2_t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_t2_ac_ex_db.liveaction["id"]) self.assertEqual(t2_t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_PENDING) workflows.get_engine().process(t2_t2_ac_ex_db) t2_t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_t2_ex_db.id) self.assertEqual(t2_t2_ex_db.status, wf_statuses.PENDING) t2_wf_ex_db = wf_db_access.WorkflowExecution.get_by_id( str(t2_wf_ex_db.id)) self.assertEqual(t2_wf_ex_db.status, wf_statuses.PAUSED) # Process the corresponding task in parent workflow and assert the task is paused. t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_ex_db.id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_ac_ex_db.liveaction["id"]) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_PAUSED) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_ex_db.status, wf_statuses.PAUSED) # Assert the main workflow is paused. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) # Respond to the inquiry and check status. inquiry_api = inqy_api_models.InquiryAPI.from_model(t2_t2_ac_ex_db) inquiry_response = {"approved": True} inquiry_service.respond(inquiry_api, inquiry_response) t2_t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( str(t2_t2_lv_ac_db.id)) self.assertEqual(t2_t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) t2_t2_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(t2_t2_ac_ex_db.id)) self.assertEqual(t2_t2_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_t2_ac_ex_db) t2_t2_ex_db = wf_db_access.TaskExecution.get_by_id(str(t2_t2_ex_db.id)) self.assertEqual(t2_t2_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Assert the main workflow is running again. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Complete the rest of the subworkflow query_filters = { "workflow_execution": str(t2_wf_ex_db.id), "task_id": "finish" } t2_t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_t3_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_t3_ex_db.id))[0] t2_t3_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_t3_ac_ex_db.liveaction["id"]) self.assertEqual(t2_t3_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_t3_ac_ex_db) t2_t3_ex_db = wf_db_access.TaskExecution.get_by_id(t2_t3_ex_db.id) self.assertEqual(t2_t3_ex_db.status, wf_statuses.SUCCEEDED) t2_wf_ex_db = wf_db_access.WorkflowExecution.get_by_id( str(t2_wf_ex_db.id)) self.assertEqual(t2_wf_ex_db.status, wf_statuses.SUCCEEDED) t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_ex_db.id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_ac_ex_db.liveaction["id"]) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_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) # Complete the rest of the main workflow query_filters = { "workflow_execution": str(wf_ex_db.id), "task_id": "finish" } t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[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, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t3_ac_ex_db) t3_ex_db = wf_db_access.TaskExecution.get_by_id(t3_ex_db.id) self.assertEqual(t3_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)
def test_inquiry(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'ask-approval.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) # Assert start task is already completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'start'} 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] t1_lv_ac_db = lv_db_access.LiveAction.get_by_id(t1_ac_ex_db.liveaction['id']) self.assertEqual(t1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) 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 still running. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert get approval task is already pending. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'get_approval'} t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t2_ex_db.id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(t2_ac_ex_db.liveaction['id']) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_PENDING) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_ex_db.status, wf_statuses.PENDING) # Assert the main workflow is paused since it has no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) # Respond to the inquiry and check status. inquiry_api = inqy_api_models.InquiryAPI.from_model(t2_ac_ex_db) inquiry_response = {'approved': True} inquiry_service.respond(inquiry_api, inquiry_response) t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t2_lv_ac_db.id)) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) t2_ac_ex_db = ex_db_access.ActionExecution.get_by_id(str(t2_ac_ex_db.id)) self.assertEqual(t2_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(str(t2_ex_db.id)) self.assertEqual(t2_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Assert the main workflow is paused since it has no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert the final task is completed. query_filters = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'finish'} t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[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, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t3_ac_ex_db) t3_ex_db = wf_db_access.TaskExecution.get_by_id(t3_ex_db.id) self.assertEqual(t3_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)
def test_delay_for_with_items_concurrency(self): num_items = 3 concurrency = 2 expected_delay_sec = 1 expected_delay_msec = expected_delay_sec * 1000 wf_input = {'concurrency': concurrency, 'delay': expected_delay_sec} wf_meta = base.get_wf_fixture_meta_data( TEST_PACK_PATH, 'with-items-concurrency-delay.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert action execution is running. lv_ac_db = self._wait_on_status( lv_ac_db, 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 first set of action executions from with items concurrency. 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)) t1_lv_ac_dbs = lv_db_access.LiveAction.query( task_execution=str(t1_ex_db.id)) # Assert the number of concurrent items is correct. self.assertEqual(len(t1_ac_ex_dbs), concurrency) # Assert delay value is rendered and assigned. self.assertEqual(t1_ex_db.delay, expected_delay_sec) for t1_lv_ac_db in t1_lv_ac_dbs: self.assertEqual(t1_lv_ac_db.delay, expected_delay_msec) for t1_ac_ex_db in t1_ac_ex_dbs: self.assertEqual(t1_ac_ex_db.delay, expected_delay_msec) 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_states.RUNNING) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_states.RUNNING) # Process the second set of action executions from with items concurrency. t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) t1_lv_ac_dbs = lv_db_access.LiveAction.query( task_execution=str(t1_ex_db.id)) # Assert delay value is rendered and assigned only to the first set of action executions. t1_lv_ac_dbs_delays = [ t1_lv_ac_db.delay for t1_lv_ac_db in t1_lv_ac_dbs if t1_lv_ac_db.delay is not None ] self.assertEqual(len(t1_lv_ac_dbs_delays), concurrency) t1_ac_ex_dbs_delays = [ t1_ac_ex_db.delay for t1_ac_ex_db in t1_ac_ex_dbs if t1_ac_ex_db.delay is not None ] self.assertEqual(len(t1_ac_ex_dbs_delays), concurrency) # Assert all items are processed. 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[concurrency:]: 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_states.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_states.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 __init__(self, *args, **kwargs): super(WorkflowEngineTest, self).__init__(*args, **kwargs) self.wf_engine = workflows.get_engine()
def test_with_items_pause_and_resume(self): num_items = 3 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, "with-items-concurrency.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 the workflow 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) 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(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(len(t1_ac_ex_dbs), num_items) status = [ ac_ex.status == action_constants.LIVEACTION_STATUS_RUNNING for ac_ex in t1_ac_ex_dbs ] self.assertTrue(all(status)) # Pause the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.request_pause(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, action_constants.LIVEACTION_STATUS_PAUSING) # Manually succeed the action executions and process completion. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction["id"], action_constants.LIVEACTION_STATUS_SUCCEEDED) t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) 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) # Check that the workflow execution is paused. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) 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_PAUSED) # Resume the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.request_resume(lv_ac_db, requester) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_RESUMING) # Check that the workflow execution 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_with_items_concurrency_pause_and_resume(self): num_items = 3 concurrency = 2 wf_input = {'concurrency': concurrency} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert the workflow 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) 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(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(len(t1_ac_ex_dbs), concurrency) # Reset the action executions to running status. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_RUNNING ) t1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id)) status = [ ac_ex.status == action_constants.LIVEACTION_STATUS_RUNNING for ac_ex in t1_ac_ex_dbs ] self.assertTrue(all(status)) # Pause the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.request_pause(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, action_constants.LIVEACTION_STATUS_PAUSING) # Manually succeed the action executions and process completion. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_SUCCEEDED ) t1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id)) 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) # Check that the workflow execution is paused. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) 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_PAUSED) # Resume the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.request_resume(lv_ac_db, requester) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_RESUMING) # Check that the workflow 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) # Check new set of action execution is scheduled. 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) # Manually process the last action execution. workflows.get_engine().process(t1_ac_ex_dbs[2]) # Check that the workflow execution 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_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_with_items_concurrency(self): num_items = 3 concurrency = 2 wf_input = {'concurrency': concurrency} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) 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 first set of action executions from with items concurrency. 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), concurrency) 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.RUNNING) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Process the second set of action executions from with items concurrency. 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[concurrency:]: 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_with_items_concurrency_pause_and_resume(self): num_items = 3 concurrency = 2 wf_input = {'concurrency': concurrency} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert the workflow 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) 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(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(len(t1_ac_ex_dbs), concurrency) # Reset the action executions to running status. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_RUNNING) t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) status = [ ac_ex.status == action_constants.LIVEACTION_STATUS_RUNNING for ac_ex in t1_ac_ex_dbs ] self.assertTrue(all(status)) # Pause the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.request_pause(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, action_constants.LIVEACTION_STATUS_PAUSING) # Manually succeed the action executions and process completion. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_SUCCEEDED) t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) 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) # Check that the workflow execution is paused. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) 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_PAUSED) # Resume the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.request_resume(lv_ac_db, requester) self.assertEqual(lv_ac_db.status, action_constants.LIVEACTION_STATUS_RESUMING) # Check that the workflow 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) # Check new set of action execution is scheduled. 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) # Manually process the last action execution. workflows.get_engine().process(t1_ac_ex_dbs[2]) # Check that the workflow execution 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_with_items_cancellation(self): num_items = 3 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency.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 the workflow 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) 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(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(len(t1_ac_ex_dbs), num_items) # Reset the action executions to running status. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_RUNNING) t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) status = [ ac_ex.status == action_constants.LIVEACTION_STATUS_RUNNING for ac_ex in t1_ac_ex_dbs ] self.assertTrue(all(status)) # Cancels the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.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, action_constants.LIVEACTION_STATUS_CANCELING) # Manually succeed the action executions and process completion. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_SUCCEEDED) t1_ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(t1_ex_db.id)) 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) # Check that the workflow execution is canceled. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.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_with_items_concurrency(self): num_items = 3 concurrency = 2 wf_input = {'concurrency': concurrency} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) 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 first set of action executions from with items concurrency. 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), concurrency) 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.RUNNING) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Process the second set of action executions from with items concurrency. 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[concurrency:]: 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_with_items_cancellation(self): num_items = 3 wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency.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 the workflow 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) 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(t1_ex_db.status, wf_statuses.RUNNING) self.assertEqual(len(t1_ac_ex_dbs), num_items) # Reset the action executions to running status. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_RUNNING ) t1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id)) status = [ ac_ex.status == action_constants.LIVEACTION_STATUS_RUNNING for ac_ex in t1_ac_ex_dbs ] self.assertTrue(all(status)) # Cancels the workflow execution. requester = cfg.CONF.system_user.user lv_ac_db, ac_ex_db = action_service.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, action_constants.LIVEACTION_STATUS_CANCELING) # Manually succeed the action executions and process completion. for ac_ex in t1_ac_ex_dbs: self.set_execution_status( ac_ex.liveaction['id'], action_constants.LIVEACTION_STATUS_SUCCEEDED ) t1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id)) 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) # Check that the workflow execution is canceled. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.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_delay_for_with_items_concurrency(self): num_items = 3 concurrency = 2 expected_delay_sec = 1 expected_delay_msec = expected_delay_sec * 1000 wf_input = {'concurrency': concurrency, 'delay': expected_delay_sec} wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'with-items-concurrency-delay.yaml') lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name'], parameters=wf_input) lv_ac_db, ac_ex_db = action_service.request(lv_ac_db) # Assert action execution is running. lv_ac_db = self._wait_on_status(lv_ac_db, 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 first set of action executions from with items concurrency. 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)) t1_lv_ac_dbs = lv_db_access.LiveAction.query(task_execution=str(t1_ex_db.id)) # Assert the number of concurrent items is correct. self.assertEqual(len(t1_ac_ex_dbs), concurrency) # Assert delay value is rendered and assigned. self.assertEqual(t1_ex_db.delay, expected_delay_sec) for t1_lv_ac_db in t1_lv_ac_dbs: self.assertEqual(t1_lv_ac_db.delay, expected_delay_msec) for t1_ac_ex_db in t1_ac_ex_dbs: self.assertEqual(t1_ac_ex_db.delay, expected_delay_msec) 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.RUNNING) wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Process the second set of action executions from with items concurrency. t1_ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(t1_ex_db.id)) t1_lv_ac_dbs = lv_db_access.LiveAction.query(task_execution=str(t1_ex_db.id)) # Assert delay value is rendered and assigned only to the first set of action executions. t1_lv_ac_dbs_delays = [ t1_lv_ac_db.delay for t1_lv_ac_db in t1_lv_ac_dbs if t1_lv_ac_db.delay is not None ] self.assertEqual(len(t1_lv_ac_dbs_delays), concurrency) t1_ac_ex_dbs_delays = [ t1_ac_ex_db.delay for t1_ac_ex_db in t1_ac_ex_dbs if t1_ac_ex_db.delay is not None ] self.assertEqual(len(t1_ac_ex_dbs_delays), concurrency) # Assert all items are processed. 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[concurrency:]: 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_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_states.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_states.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_handle_action_execution_completion(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 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), 1) # Identify the records for the tasks. t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[0].id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_states.RUNNING) # Manually notify action execution completion for the tasks. # Assert policies are not applied in the notifier. 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] notifier.get_notifier().process(t1_t1_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) t1_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id)) self.assertEqual(len(t1_tk_ex_dbs), 1) workflows.get_engine().process(t1_t1_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() 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] notifier.get_notifier().process(t1_t2_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) t1_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id)) self.assertEqual(len(t1_tk_ex_dbs), 2) workflows.get_engine().process(t1_t2_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() 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] notifier.get_notifier().process(t1_t3_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) t1_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id)) self.assertEqual(len(t1_tk_ex_dbs), 3) workflows.get_engine().process(t1_t3_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(t1_ac_ex_db.id) notifier.get_notifier().process(t1_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 1) workflows.get_engine().process(t1_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() t2_ex_db_qry = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} t2_ex_db = wf_db_access.TaskExecution.query(**t2_ex_db_qry)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t2_ex_db.id))[0] self.assertEqual(t2_ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) notifier.get_notifier().process(t2_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 2) workflows.get_engine().process(t2_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() # 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_inquiry(self): wf_meta = base.get_wf_fixture_meta_data(TEST_PACK_PATH, 'ask-approval.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) # Assert start task is already completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'start' } 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] t1_lv_ac_db = lv_db_access.LiveAction.get_by_id( t1_ac_ex_db.liveaction['id']) self.assertEqual(t1_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) 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 still running. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert get approval task is already pending. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'get_approval' } t2_ex_db = wf_db_access.TaskExecution.query(**query_filters)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query( task_execution=str(t2_ex_db.id))[0] t2_lv_ac_db = lv_db_access.LiveAction.get_by_id( t2_ac_ex_db.liveaction['id']) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_PENDING) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(t2_ex_db.id) self.assertEqual(t2_ex_db.status, wf_statuses.PENDING) # Assert the main workflow is paused since it has no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.PAUSED) # Respond to the inquiry and check status. inquiry_api = inqy_api_models.InquiryAPI.from_model(t2_ac_ex_db) inquiry_response = {'approved': True} inquiry_service.respond(inquiry_api, inquiry_response) t2_lv_ac_db = lv_db_access.LiveAction.get_by_id(str(t2_lv_ac_db.id)) self.assertEqual(t2_lv_ac_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) t2_ac_ex_db = ex_db_access.ActionExecution.get_by_id( str(t2_ac_ex_db.id)) self.assertEqual(t2_ac_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t2_ac_ex_db) t2_ex_db = wf_db_access.TaskExecution.get_by_id(str(t2_ex_db.id)) self.assertEqual(t2_ex_db.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Assert the main workflow is paused since it has no other active tasks. wf_ex_db = wf_db_access.WorkflowExecution.get_by_id(wf_ex_db.id) self.assertEqual(wf_ex_db.status, wf_statuses.RUNNING) # Assert the final task is completed. query_filters = { 'workflow_execution': str(wf_ex_db.id), 'task_id': 'finish' } t3_ex_db = wf_db_access.TaskExecution.query(**query_filters)[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, action_constants.LIVEACTION_STATUS_SUCCEEDED) workflows.get_engine().process(t3_ac_ex_db) t3_ex_db = wf_db_access.TaskExecution.get_by_id(t3_ex_db.id) self.assertEqual(t3_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)
def test_handle_action_execution_completion(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 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), 1) # Identify the records for the tasks. t1_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(tk_ex_dbs[0].id))[0] t1_wf_ex_db = wf_db_access.WorkflowExecution.query(action_execution=str(t1_ac_ex_db.id))[0] self.assertEqual(t1_ac_ex_db.status, ac_const.LIVEACTION_STATUS_RUNNING) self.assertEqual(t1_wf_ex_db.status, wf_statuses.RUNNING) # Manually notify action execution completion for the tasks. # Assert policies are not applied in the notifier. 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] notifier.get_notifier().process(t1_t1_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) t1_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id)) self.assertEqual(len(t1_tk_ex_dbs), 1) workflows.get_engine().process(t1_t1_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() 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] notifier.get_notifier().process(t1_t2_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) t1_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id)) self.assertEqual(len(t1_tk_ex_dbs), 2) workflows.get_engine().process(t1_t2_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() 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] notifier.get_notifier().process(t1_t3_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) t1_tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(t1_wf_ex_db.id)) self.assertEqual(len(t1_tk_ex_dbs), 3) workflows.get_engine().process(t1_t3_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() t1_ac_ex_db = ex_db_access.ActionExecution.get_by_id(t1_ac_ex_db.id) notifier.get_notifier().process(t1_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 1) workflows.get_engine().process(t1_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() t2_ex_db_qry = {'workflow_execution': str(wf_ex_db.id), 'task_id': 'task2'} t2_ex_db = wf_db_access.TaskExecution.query(**t2_ex_db_qry)[0] t2_ac_ex_db = ex_db_access.ActionExecution.query(task_execution=str(t2_ex_db.id))[0] self.assertEqual(t2_ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) notifier.get_notifier().process(t2_ac_ex_db) self.assertFalse(pc_svc.apply_post_run_policies.called) tk_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(tk_ex_dbs), 2) workflows.get_engine().process(t2_ac_ex_db) self.assertTrue(pc_svc.apply_post_run_policies.called) pc_svc.apply_post_run_policies.reset_mock() # 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)