def test_request_task_execution(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Manually request task execution. task_id = 'task1' task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} st2_ctx = {'execution_id': wf_ex_db.action_execution} task_ex_req = { 'id': task_id, 'spec': task_spec, 'ctx': task_ctx, 'actions': [{ 'action': 'core.echo', 'input': { 'message': 'Veni, vidi, vici.' } }] } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) # Check required attributes. task_ex_db = task_ex_dbs[0] self.assertIsNotNone(task_ex_db.id) self.assertGreater(task_ex_db.rev, 0) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) self.assertEqual(task_ex_db.status, wf_states.RUNNING) # Check action execution for the task query with task execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(task_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1) # Check action execution for the task query with workflow execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1)
def process(self, wf_ex_db): # Refresh record from the database in case the request is in the queue for too long. conductor, wf_ex_db = wf_svc.refresh_conductor(str(wf_ex_db.id)) # Continue if workflow is still active. if conductor.get_workflow_state() not in states.COMPLETED_STATES: # Set workflow to running state. conductor.set_workflow_state(states.RUNNING) # Identify the next set of tasks to execute. next_tasks = conductor.get_next_tasks() # If there is no new tasks, update execution records to handle possible completion. if not next_tasks: # Update workflow execution and related liveaction and action execution. wf_svc.update_execution_records(wf_ex_db, conductor) # If workflow execution is no longer active, then stop processing here. if wf_ex_db.status in states.COMPLETED_STATES: return # Iterate while there are next tasks identified for processing. In the case for # task with no action execution defined, the task execution will complete # immediately with a new set of tasks available. while next_tasks: # Mark the tasks as running in the task flow before actual task execution. for task in next_tasks: conductor.update_task_flow(task['id'], states.RUNNING) # Update workflow execution and related liveaction and action execution. wf_svc.update_execution_records(wf_ex_db, conductor) # If workflow execution is no longer active, then stop processing here. if wf_ex_db.status in states.COMPLETED_STATES: break # Request task execution for the tasks. for task in next_tasks: try: task_id, task_spec, task_ctx = task['id'], task[ 'spec'], task['ctx'] st2_ctx = {'execution_id': wf_ex_db.action_execution} wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, task_ctx, st2_ctx) except Exception as e: wf_svc.fail_workflow_execution(str(wf_ex_db.id), e, task_id=task['id']) return # Identify the next set of tasks to execute. conductor, wf_ex_db = wf_svc.refresh_conductor(str(wf_ex_db.id)) next_tasks = conductor.get_next_tasks()
def test_request_task_execution(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, 'sequential.yaml') # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Manually request task execution. task_route = 0 task_id = 'task1' task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} st2_ctx = {'execution_id': wf_ex_db.action_execution} task_ex_req = { 'id': task_id, 'route': task_route, 'spec': task_spec, 'ctx': task_ctx, 'actions': [ {'action': 'core.echo', 'input': {'message': 'Veni, vidi, vici.'}} ] } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) # Check required attributes. task_ex_db = task_ex_dbs[0] self.assertIsNotNone(task_ex_db.id) self.assertGreater(task_ex_db.rev, 0) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) self.assertEqual(task_ex_db.status, wf_statuses.RUNNING) # Check action execution for the task query with task execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(task_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1) # Check action execution for the task query with workflow execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1)
def process(self, wf_ex_db): # Refresh record from the database in case the request is in the queue for too long. conductor, wf_ex_db = wf_svc.refresh_conductor(str(wf_ex_db.id)) # Continue if workflow is still active. if conductor.get_workflow_state() not in states.COMPLETED_STATES: # Set workflow to running state. conductor.set_workflow_state(states.RUNNING) # Identify the next set of tasks to execute. next_tasks = conductor.get_next_tasks() # If there is no new tasks, update execution records to handle possible completion. if not next_tasks: # Update workflow execution and related liveaction and action execution. wf_svc.update_execution_records(wf_ex_db, conductor) # If workflow execution is no longer active, then stop processing here. if wf_ex_db.status in states.COMPLETED_STATES: return # Iterate while there are next tasks identified for processing. In the case for # task with no action execution defined, the task execution will complete # immediately with a new set of tasks available. while next_tasks: # Mark the tasks as running in the task flow before actual task execution. for task in next_tasks: conductor.update_task_flow(task['id'], states.RUNNING) # Update workflow execution and related liveaction and action execution. wf_svc.update_execution_records(wf_ex_db, conductor) # If workflow execution is no longer active, then stop processing here. if wf_ex_db.status in states.COMPLETED_STATES: break # Request task execution for the tasks. for task in next_tasks: try: task_id, task_spec, task_ctx = task['id'], task['spec'], task['ctx'] st2_ctx = {'execution_id': wf_ex_db.action_execution} wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, task_ctx, st2_ctx) except Exception as e: wf_svc.fail_workflow_execution(str(wf_ex_db.id), e, task_id=task['id']) return # Identify the next set of tasks to execute. conductor, wf_ex_db = wf_svc.refresh_conductor(str(wf_ex_db.id)) next_tasks = conductor.get_next_tasks()
def run_workflow_step( self, wf_ex_db, task_id, route, ctx=None, expected_ac_ex_db_status=ac_const.LIVEACTION_STATUS_SUCCEEDED, expected_tk_ex_db_status=wf_statuses.SUCCEEDED): spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) st2_ctx = {'execution_id': wf_ex_db.action_execution} task_spec = wf_spec.tasks.get_task(task_id) task_actions = [{ 'action': task_spec.action, 'input': getattr(task_spec, 'input', {}) }] task_req = { 'id': task_id, 'route': route, 'spec': task_spec, 'ctx': ctx or {}, 'actions': task_actions } task_ex_db = wf_svc.request_task_execution(wf_ex_db, st2_ctx, task_req) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) ac_ex_db = self._wait_on_ac_ex_status(ac_ex_db, expected_ac_ex_db_status) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, expected_tk_ex_db_status)
def run_workflow_step( self, wf_ex_db, task_id, route, ctx=None, expected_ac_ex_db_status=ac_const.LIVEACTION_STATUS_SUCCEEDED, expected_tk_ex_db_status=wf_statuses.SUCCEEDED, ): spec_module = specs_loader.get_spec_module(wf_ex_db.spec["catalog"]) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) st2_ctx = {"execution_id": wf_ex_db.action_execution} task_spec = wf_spec.tasks.get_task(task_id) task_actions = [ {"action": task_spec.action, "input": getattr(task_spec, "input", {})} ] task_req = { "id": task_id, "route": route, "spec": task_spec, "ctx": ctx or {}, "actions": task_actions, } task_ex_db = wf_svc.request_task_execution(wf_ex_db, st2_ctx, task_req) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) ac_ex_db = self._wait_on_ac_ex_status(ac_ex_db, expected_ac_ex_db_status) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, expected_tk_ex_db_status)
def test_request_task_execution(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, TEST_FIXTURES['workflows'][0]) # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = wf_svc.request(wf_def, ac_ex_db, st2_ctx) # Manually request task execution. task_id = 'task1' spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} st2_ctx = {'execution_id': wf_ex_db.action_execution} wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, task_ctx, st2_ctx) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) # Check required attributes. task_ex_db = task_ex_dbs[0] self.assertIsNotNone(task_ex_db.id) self.assertGreater(task_ex_db.rev, 0) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) self.assertEqual(task_ex_db.status, wf_lib_states.RUNNING) # Check action execution for the task query with task execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(task_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1) # Check action execution for the task query with workflow execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1)
def run_workflow_step(self, wf_ex_db, task_id, ctx=None): spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) task_spec = wf_spec.tasks.get_task(task_id) st2_ctx = {'execution_id': wf_ex_db.action_execution} task_ex_db = wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, ctx or {}, st2_ctx) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, wf_lib_states.SUCCEEDED)
def run_workflow_step(self, wf_ex_db, task_id, ctx=None): spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) task_spec = wf_spec.tasks.get_task(task_id) st2_ctx = {'execution_id': wf_ex_db.action_execution} task_ex_db = wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, ctx or {}, st2_ctx) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) self.assertEqual(ac_ex_db.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, wf_lib_states.SUCCEEDED)
def test_request_task_execution(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, TEST_FIXTURES['workflows'][0]) # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = ac_svc.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) wf_ex_db = wf_svc.request(wf_def, ac_ex_db) # Manually request task execution. task_id = 'task1' spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} st2_ctx = {'execution_id': wf_ex_db.action_execution} wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, task_ctx, st2_ctx) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) # Check required attributes. task_ex_db = task_ex_dbs[0] self.assertIsNotNone(task_ex_db.id) self.assertGreater(task_ex_db.rev, 0) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) self.assertEqual(task_ex_db.status, wf_lib_states.RUNNING) # Check action execution for the task query with task execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query(task_execution=str(task_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1) # Check action execution for the task query with workflow execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1)
def run_workflow_step(self, wf_ex_db, task_id, route, ctx=None): spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) st2_ctx = {'execution_id': wf_ex_db.action_execution} task_spec = wf_spec.tasks.get_task(task_id) task_actions = [{'action': task_spec.action, 'input': getattr(task_spec, 'input', {})}] task_req = { 'id': task_id, 'route': route, 'spec': task_spec, 'ctx': ctx or {}, 'actions': task_actions } task_ex_db = wf_svc.request_task_execution(wf_ex_db, st2_ctx, task_req) ac_ex_db = self.get_action_ex(str(task_ex_db.id)) ac_ex_db = self._wait_on_ac_ex_status(ac_ex_db, ac_const.LIVEACTION_STATUS_SUCCEEDED) wf_svc.handle_action_execution_completion(ac_ex_db) task_ex_db = wf_db_access.TaskExecution.get_by_id(str(task_ex_db.id)) self.assertEqual(task_ex_db.status, wf_statuses.SUCCEEDED)
def test_request_action_execution_render(self): # Manually create ConfigDB output = 'Testing' value = {"config_item_one": output} config_db = pk_db_models.ConfigDB(pack=PACK_7, values=value) config = pk_db_access.Config.add_or_update(config_db) self.assertEqual(len(config), 3) wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, 'render_config_context.yaml') # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Pass down appropriate st2 context to the task and action execution(s). root_st2_ctx = wf_ex_db.context.get('st2', {}) st2_ctx = { 'execution_id': wf_ex_db.action_execution, 'user': root_st2_ctx.get('user'), 'pack': root_st2_ctx.get('pack') } # Manually request task execution. task_route = 0 task_id = 'task1' task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} task_ex_req = { 'id': task_id, 'route': task_route, 'spec': task_spec, 'ctx': task_ctx, 'actions': [{ 'action': 'dummy_pack_7.render_config_context', 'input': None }] } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Manually request action execution task_ex_db = task_ex_dbs[0] action_ex_db = workflow_service.request_action_execution( wf_ex_db, task_ex_db, st2_ctx, task_ex_req['actions'][0]) # Check required attributes. self.assertIsNotNone(str(action_ex_db.id)) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) expected_parameters = {'value1': output} self.assertEqual(expected_parameters, action_ex_db.parameters)
def test_request_action_execution_render(self): # Manually create ConfigDB output = "Testing" value = {"config_item_one": output} config_db = pk_db_models.ConfigDB(pack=PACK_7, values=value) config = pk_db_access.Config.add_or_update(config_db) self.assertEqual(len(config), 3) wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, "render_config_context.yaml") # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta["name"]) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec["catalog"]) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Pass down appropriate st2 context to the task and action execution(s). root_st2_ctx = wf_ex_db.context.get("st2", {}) st2_ctx = { "execution_id": wf_ex_db.action_execution, "user": root_st2_ctx.get("user"), "pack": root_st2_ctx.get("pack"), } # Manually request task execution. task_route = 0 task_id = "task1" task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {"foo": "bar"} task_ex_req = { "id": task_id, "route": task_route, "spec": task_spec, "ctx": task_ctx, "actions": [{ "action": "dummy_pack_7.render_config_context", "input": None }], } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Manually request action execution task_ex_db = task_ex_dbs[0] action_ex_db = workflow_service.request_action_execution( wf_ex_db, task_ex_db, st2_ctx, task_ex_req["actions"][0]) # Check required attributes. self.assertIsNotNone(str(action_ex_db.id)) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) expected_parameters = {"value1": output} self.assertEqual(expected_parameters, action_ex_db.parameters)
def test_request_task_execution(self): wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, "sequential.yaml") # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta["name"]) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec["catalog"]) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Manually request task execution. task_route = 0 task_id = "task1" task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {"foo": "bar"} st2_ctx = {"execution_id": wf_ex_db.action_execution} task_ex_req = { "id": task_id, "route": task_route, "spec": task_spec, "ctx": task_ctx, "actions": [{ "action": "core.echo", "input": { "message": "Veni, vidi, vici." } }], } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) # Check required attributes. task_ex_db = task_ex_dbs[0] self.assertIsNotNone(task_ex_db.id) self.assertGreater(task_ex_db.rev, 0) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) self.assertEqual(task_ex_db.status, wf_statuses.RUNNING) # Check action execution for the task query with task execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query( task_execution=str(task_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1) # Check action execution for the task query with workflow execution ID. ac_ex_dbs = ex_db_access.ActionExecution.query( workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(ac_ex_dbs), 1)
def test_request_action_execution_render(self): # Manually create ConfigDB output = 'Testing' value = { "config_item_one": output } config_db = pk_db_models.ConfigDB(pack=PACK_7, values=value) config = pk_db_access.Config.add_or_update(config_db) self.assertEqual(len(config), 3) wf_meta = self.get_wf_fixture_meta_data(TEST_PACK_PATH, 'render_config_context.yaml') # Manually create the liveaction and action execution objects without publishing. lv_ac_db = lv_db_models.LiveActionDB(action=wf_meta['name']) lv_ac_db, ac_ex_db = action_service.create_request(lv_ac_db) # Request the workflow execution. wf_def = self.get_wf_def(TEST_PACK_PATH, wf_meta) st2_ctx = self.mock_st2_context(ac_ex_db) wf_ex_db = workflow_service.request(wf_def, ac_ex_db, st2_ctx) spec_module = specs_loader.get_spec_module(wf_ex_db.spec['catalog']) wf_spec = spec_module.WorkflowSpec.deserialize(wf_ex_db.spec) # Pass down appropriate st2 context to the task and action execution(s). root_st2_ctx = wf_ex_db.context.get('st2', {}) st2_ctx = { 'execution_id': wf_ex_db.action_execution, 'user': root_st2_ctx.get('user'), 'pack': root_st2_ctx.get('pack') } # Manually request task execution. task_route = 0 task_id = 'task1' task_spec = wf_spec.tasks.get_task(task_id) task_ctx = {'foo': 'bar'} task_ex_req = { 'id': task_id, 'route': task_route, 'spec': task_spec, 'ctx': task_ctx, 'actions': [ {'action': 'dummy_pack_7.render_config_context', 'input': None} ] } workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Check task execution is saved to the database. task_ex_dbs = wf_db_access.TaskExecution.query(workflow_execution=str(wf_ex_db.id)) self.assertEqual(len(task_ex_dbs), 1) workflow_service.request_task_execution(wf_ex_db, st2_ctx, task_ex_req) # Manually request action execution task_ex_db = task_ex_dbs[0] action_ex_db = workflow_service.request_action_execution(wf_ex_db, task_ex_db, st2_ctx, task_ex_req['actions'][0]) # Check required attributes. self.assertIsNotNone(str(action_ex_db.id)) self.assertEqual(task_ex_db.workflow_execution, str(wf_ex_db.id)) expected_parameters = {'value1': output} self.assertEqual(expected_parameters, action_ex_db.parameters)
def handle_workflow_execution(self, wf_ex_db): iteration = 0 wf_ac_ex_id = wf_ex_db.action_execution LOG.info('[%s] Processing request for workflow execution.', wf_ac_ex_id) # Refresh record from the database in case the request is in the queue for too long. conductor, wf_ex_db = wf_svc.refresh_conductor(str(wf_ex_db.id)) # Continue if workflow is still active and set workflow to running state. if conductor.get_workflow_state() not in states.COMPLETED_STATES: LOG.info( '[%s] Requesting conductor to start running workflow execution.', wf_ac_ex_id) conductor.request_workflow_state(states.RUNNING) # Identify the next set of tasks to execute. msg = '[%s] Identifying next set (%s) of tasks for workflow execution in state "%s".' LOG.info(msg, wf_ac_ex_id, str(iteration), conductor.get_workflow_state()) LOG.debug('[%s] %s', wf_ac_ex_id, conductor.serialize()) next_tasks = conductor.get_next_tasks() # If there is no new tasks, update execution records to handle possible completion. if not next_tasks: # Update workflow execution and related liveaction and action execution. LOG.info('[%s] No tasks identified to execute next.', wf_ac_ex_id) wf_svc.update_execution_records(wf_ex_db, conductor) # If workflow execution is no longer active, then stop processing here. if wf_ex_db.status in states.COMPLETED_STATES: msg = '[%s] Workflow execution is in completed state "%s".' LOG.info(msg, wf_ac_ex_id, wf_ex_db.status) return # Iterate while there are next tasks identified for processing. In the case for # task with no action execution defined, the task execution will complete # immediately with a new set of tasks available. while next_tasks: msg = '[%s] Identified the following set of tasks to execute next: %s' LOG.info(msg, wf_ac_ex_id, ', '.join([task['id'] for task in next_tasks])) # Mark the tasks as running in the task flow before actual task execution. for task in next_tasks: msg = '[%s] Mark task "%s" in conductor as running.' LOG.info(msg, wf_ac_ex_id, task['id']) ac_ex_event = events.ActionExecutionEvent(states.RUNNING) conductor.update_task_flow(task['id'], ac_ex_event) # Update workflow execution and related liveaction and action execution. wf_svc.update_execution_records(wf_ex_db, conductor) # If workflow execution is no longer active, then stop processing here. if wf_ex_db.status in states.COMPLETED_STATES: msg = '[%s] Workflow execution is in completed state "%s".' LOG.info(msg, wf_ac_ex_id, wf_ex_db.status) break # Request task execution for the tasks. for task in next_tasks: try: LOG.info('[%s] Requesting execution for task "%s".', wf_ac_ex_id, task['id']) task_id, task_spec, task_ctx = task['id'], task[ 'spec'], task['ctx'] st2_ctx = {'execution_id': wf_ex_db.action_execution} wf_svc.request_task_execution(wf_ex_db, task_id, task_spec, task_ctx, st2_ctx) except Exception as e: LOG.exception('[%s] Failed task execution for "%s".', wf_ac_ex_id, task['id']) wf_svc.fail_workflow_execution(str(wf_ex_db.id), e, task_id=task['id']) return # Identify the next set of tasks to execute. iteration += 1 conductor, wf_ex_db = wf_svc.refresh_conductor(str(wf_ex_db.id)) msg = '[%s] Identifying next set (%s) of tasks for workflow execution in state "%s".' LOG.info(msg, wf_ac_ex_id, str(iteration), conductor.get_workflow_state()) LOG.debug('[%s] %s', wf_ac_ex_id, conductor.serialize()) next_tasks = conductor.get_next_tasks() if not next_tasks: LOG.info('[%s] No tasks identified to execute next.', wf_ac_ex_id)