def _get_runner(self, runnertype_db, action_db, liveaction_db): runner = get_runner(runnertype_db.runner_module) resolved_entry_point = self._get_entry_point_abs_path(action_db.pack, action_db.entry_point) runner.runner_type_db = runnertype_db runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.execution = ActionExecution.get(liveaction__id=runner.liveaction_id) runner.execution_id = str(runner.execution.id) runner.entry_point = resolved_entry_point runner.context = getattr(liveaction_db, 'context', dict()) runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path(action_db.pack, action_db.entry_point) # For re-run, get the ActionExecutionDB in which the re-run is based on. rerun_ref_id = runner.context.get('re-run', {}).get('ref') runner.rerun_ex_ref = ActionExecution.get(id=rerun_ref_id) if rerun_ref_id else None return runner
def setUp(self): super(MistralAuthTest, self).setUp() # Mock the local runner run method. local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result)
def test_resume_option(self): patched_mistral_runner = runners.get_runner('mistral-v2').__class__ mock_resume_result = (action_constants.LIVEACTION_STATUS_RUNNING, { 'tasks': [] }, { 'execution_id': str(uuid.uuid4()) }) with mock.patch.object( patched_mistral_runner, 'resume_workflow', mock.MagicMock(return_value=mock_resume_result)): liveaction1 = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) liveaction1, execution1 = action_service.request(liveaction1) self.assertFalse(patched_mistral_runner.resume_workflow.called) # Rerun the execution. context = {'re-run': {'ref': execution1.id, 'tasks': ['x']}} liveaction2 = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, context=context) liveaction2, execution2 = action_service.request(liveaction2) liveaction2 = LiveAction.get_by_id(str(liveaction2.id)) self.assertEqual(liveaction2.status, action_constants.LIVEACTION_STATUS_RUNNING) task_specs = {'x': {'reset': False}} patched_mistral_runner.resume_workflow.assert_called_with( ex_ref=execution1, task_specs=task_specs)
def _invoke_post_run(self, actionexec_db, action_db): LOG.info( "Invoking post run for action execution %s. Action=%s; Runner=%s", actionexec_db.id, action_db.name, action_db.runner_type["name"], ) # Get an instance of the action runner. runnertype_db = get_runnertype_by_name(action_db.runner_type["name"]) runner = get_runner(runnertype_db.runner_module) # Configure the action runner. runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(actionexec_db.id) runner.entry_point = RunnerContainerService.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point ) runner.context = getattr(actionexec_db, "context", dict()) runner.callback = getattr(actionexec_db, "callback", dict()) runner.libs_dir_path = RunnerContainerService.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point ) # Invoke the post_run method. runner.post_run(actionexec_db.status, actionexec_db.result)
def _get_runner(self, runnertype_db, action_db, liveaction_db): runner = get_runner(runnertype_db.runner_module) resolved_entry_point = self._get_entry_point_abs_path( action_db.pack, action_db.entry_point) runner.runner_type_db = runnertype_db runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.execution = ActionExecution.get( liveaction__id=runner.liveaction_id) runner.execution_id = str(runner.execution.id) runner.entry_point = resolved_entry_point runner.context = getattr(liveaction_db, 'context', dict()) runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path( action_db.pack, action_db.entry_point) # For re-run, get the ActionExecutionDB in which the re-run is based on. rerun_ref_id = runner.context.get('re-run', {}).get('ref') runner.rerun_ex_ref = ActionExecution.get( id=rerun_ref_id) if rerun_ref_id else None return runner
def invoke_post_run(liveaction_db, action_db=None): LOG.info('Invoking post run for action execution %s.', liveaction_db.id) # Identify action and runner. if not action_db: action_db = action_db_utils.get_action_by_ref(liveaction_db.action) if not action_db: LOG.exception('Unable to invoke post run. Action %s no longer exists.', liveaction_db.action) return LOG.info('Action execution %s runs %s of runner type %s.', liveaction_db.id, action_db.name, action_db.runner_type['name']) # Get an instance of the action runner. runnertype_db = action_db_utils.get_runnertype_by_name( action_db.runner_type['name']) runner = runners.get_runner(runnertype_db.runner_module) # Configure the action runner. runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(liveaction_db.id) runner.entry_point = content_utils.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) runner.context = getattr(liveaction_db, 'context', dict()) runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = content_utils.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) # Invoke the post_run method. runner.post_run(liveaction_db.status, liveaction_db.result)
def test_get_runner_module_fail(self): runnertype_db = RunnerTypeDB(name='dummy', runner_module='absent.module') runner = None try: runner = get_runner(runnertype_db.runner_module, runnertype_db.runner_module) except ActionRunnerCreateError: pass self.assertFalse(runner, 'TestRunner must be valid.')
def test_callback_incomplete_state(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_RUNNING, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status(liveaction, local_run_result[0]) self.assertFalse(action_executions.ActionExecutionManager.update.called)
def test_pre_run_runner_is_disabled(self): runnertype_db = RunnerContainerTest.runnertype_db runner = get_runner(runnertype_db.runner_module, runnertype_db.runner_module) runner.runner_type = runnertype_db runner.runner_type.enabled = False expected_msg = 'Runner "test-runner-1" has been disabled by the administrator' self.assertRaisesRegexp(ValueError, expected_msg, runner.pre_run)
def test_pre_run_runner_is_disabled(self): runnertype_db = RunnerContainerTest.runnertype_db runner = get_runner(runnertype_db.runner_module) runner.runner_type_db = runnertype_db runner.runner_type_db.enabled = False expected_msg = 'Runner "test-runner-1" has been disabled by the administrator' self.assertRaisesRegexp(ValueError, expected_msg, runner.pre_run)
def test_callback_retry(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED) calls = [call('12345', state='SUCCESS', output=NON_EMPTY_RESULT) for i in range(0, 2)] action_executions.ActionExecutionManager.update.assert_has_calls(calls)
def test_callback_incomplete_state(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_RUNNING, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status(liveaction, local_run_result[0]) self.assertFalse( action_executions.ActionExecutionManager.update.called)
def test_cancel_on_task_action_concurrency_by_attr(self): # Delete other policies in the test pack to avoid conflicts. required_policy = 'mistral_tests.cancel_on_concurrency_by_attr' self._drop_all_other_policies(required_policy) # Get threshold from the policy. policy = Policy.get_by_ref(required_policy) threshold = policy.parameters.get('threshold', 0) self.assertGreater(threshold, 0) params = {'friend': 'grande animalerie'} # Launch instances of the workflow up to threshold. for i in range(0, threshold): liveaction = LiveActionDB(action=WF1_NAME, parameters=params) liveaction, execution1 = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) liveaction = self._wait_on_status( liveaction, action_constants.LIVEACTION_STATUS_RUNNING ) # Check number of running instances running = LiveAction.count( action=WF1_NAME, status=action_constants.LIVEACTION_STATUS_RUNNING, parameters__friend=params['friend']) self.assertEqual(running, threshold) # Mock the mistral runner cancel method to assert cancel is called. mistral_runner_cls = runners.get_runner('mistral-v2').__class__ mock_cancel_return_value = (action_constants.LIVEACTION_STATUS_CANCELING, None, None) mock_cancel = mock.MagicMock(return_value=mock_cancel_return_value) with mock.patch.object(mistral_runner_cls, 'cancel', mock_cancel): # Launch another instance of the workflow with mistral callback defined # to indicate that this is executed under a workflow. callback = { 'source': MISTRAL_RUNNER_NAME, 'url': 'http://127.0.0.1:8989/v2/action_executions/12345' } liveaction2 = LiveActionDB(action=WF1_NAME, parameters=params, callback=callback) liveaction2, execution2 = action_service.request(liveaction2) liveaction2 = LiveAction.get_by_id(str(liveaction2.id)) # Assert cancel has been called. liveaction2 = self._wait_on_status( liveaction2, action_constants.LIVEACTION_STATUS_CANCELING ) mistral_runner_cls.cancel.assert_called_once_with()
def test_callback_paused_state(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_PAUSED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) expected_mistral_status = self.status_map[local_run_result[0]] liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status(liveaction, local_run_result[0]) action_executions.ActionExecutionManager.update.assert_called_with( '12345', state=expected_mistral_status, output=NON_EMPTY_RESULT)
def invoke_post_run(liveaction_db, action_db=None): # NOTE: This import has intentionally been moved here to avoid massive performance overhead # (1+ second) for other functions inside this module which don't need to use those imports. from st2common.runners import base as runners from st2common.util import action_db as action_db_utils from st2common.content import utils as content_utils LOG.info("Invoking post run for action execution %s.", liveaction_db.id) # Identify action and runner. if not action_db: action_db = action_db_utils.get_action_by_ref(liveaction_db.action) if not action_db: LOG.error( "Unable to invoke post run. Action %s no longer exists.", liveaction_db.action, ) return LOG.info( "Action execution %s runs %s of runner type %s.", liveaction_db.id, action_db.name, action_db.runner_type["name"], ) # Get instance of the action runner and related configuration. runner_type_db = action_db_utils.get_runnertype_by_name( action_db.runner_type["name"]) runner = runners.get_runner(name=runner_type_db.name) entry_point = content_utils.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) libs_dir_path = content_utils.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) # Configure the action runner. runner.runner_type_db = runner_type_db runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.entry_point = entry_point runner.context = getattr(liveaction_db, "context", dict()) runner.callback = getattr(liveaction_db, "callback", dict()) runner.libs_dir_path = libs_dir_path # Invoke the post_run method. runner.post_run(liveaction_db.status, liveaction_db.result)
def test_callback_retry_exhausted(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED) # This test initially setup mock for action_executions.ActionExecutionManager.update # to fail the first 4 times and return success on the 5th times. The max attempts # is set to 3. We expect only 3 calls to pass thru the update method. calls = [call('12345', state='SUCCESS', output=NON_EMPTY_RESULT) for i in range(0, 2)] action_executions.ActionExecutionManager.update.assert_has_calls(calls)
def test_callback_success_state(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) expected_mistral_status = self.status_map[local_run_result[0]] liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) action_executions.ActionExecutionManager.update.assert_called_with( '12345', state=expected_mistral_status, output=NON_EMPTY_RESULT)
def test_callback_retry(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status( liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED) calls = [ call('12345', state='SUCCESS', output=NON_EMPTY_RESULT) for i in range(0, 2) ] action_executions.ActionExecutionManager.update.assert_has_calls(calls)
def test_callback_resuming_state(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_RESUMING, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) local_resume_result = (action_constants.LIVEACTION_STATUS_RUNNING, NON_EMPTY_RESULT, None) local_runner_cls.resume = mock.Mock(return_value=local_resume_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) self.assertEqual(liveaction.status, local_resume_result[0]) self.assertFalse( action_executions.ActionExecutionManager.update.called)
def test_resume_option_reset_tasks(self): patched_mistral_runner = runners.get_runner('mistral-v2').__class__ mock_resume_result = ( action_constants.LIVEACTION_STATUS_RUNNING, {'tasks': []}, {'execution_id': str(uuid.uuid4())} ) with mock.patch.object(patched_mistral_runner, 'resume_workflow', mock.MagicMock(return_value=mock_resume_result)): liveaction1 = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) liveaction1, execution1 = action_service.request(liveaction1) self.assertFalse(patched_mistral_runner.resume_workflow.called) # Rerun the execution. context = { 're-run': { 'ref': execution1.id, 'tasks': ['x', 'y'], 'reset': ['y'] } } liveaction2 = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, context=context) liveaction2, execution2 = action_service.request(liveaction2) liveaction2 = self._wait_on_status( liveaction2, action_constants.LIVEACTION_STATUS_RUNNING ) task_specs = { 'x': { 'reset': False }, 'y': { 'reset': True } } patched_mistral_runner.resume_workflow.assert_called_with( ex_ref=execution1, task_specs=task_specs )
def test_callback_retry_exhausted(self): local_runner_cls = runners.get_runner('local-shell-cmd').__class__ local_run_result = (action_constants.LIVEACTION_STATUS_SUCCEEDED, NON_EMPTY_RESULT, None) local_runner_cls.run = mock.Mock(return_value=local_run_result) liveaction = self.get_liveaction_instance() liveaction, execution = action_service.request(liveaction) liveaction = self._wait_on_status( liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED) # This test initially setup mock for action_executions.ActionExecutionManager.update # to fail the first 4 times and return success on the 5th times. The max attempts # is set to 3. We expect only 3 calls to pass thru the update method. calls = [ call('12345', state='SUCCESS', output=NON_EMPTY_RESULT) for i in range(0, 2) ] action_executions.ActionExecutionManager.update.assert_has_calls(calls)
def _get_runner(self, runnertype_db, action_db, liveaction_db): resolved_entry_point = self._get_entry_point_abs_path( action_db.pack, action_db.entry_point) context = getattr(liveaction_db, 'context', dict()) user = context.get('user', cfg.CONF.system_user.user) # Note: Right now configs are only supported by the Python runner actions if runnertype_db.runner_module == 'python_runner': LOG.debug('Loading config for pack') config_loader = ContentPackConfigLoader(pack_name=action_db.pack, user=user) config = config_loader.get_config() else: config = None runner = get_runner(package_name=runnertype_db.runner_package, module_name=runnertype_db.runner_module, config=config) # TODO: Pass those arguments to the constructor instead of late # assignment, late assignment is awful runner.runner_type_db = runnertype_db runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.execution = ActionExecution.get( liveaction__id=runner.liveaction_id) runner.execution_id = str(runner.execution.id) runner.entry_point = resolved_entry_point runner.context = context runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path( action_db.pack, action_db.entry_point) # For re-run, get the ActionExecutionDB in which the re-run is based on. rerun_ref_id = runner.context.get('re-run', {}).get('ref') runner.rerun_ex_ref = ActionExecution.get( id=rerun_ref_id) if rerun_ref_id else None return runner
def _get_runner(self, runner_type_db, action_db, liveaction_db): resolved_entry_point = self._get_entry_point_abs_path( action_db.pack, action_db.entry_point) context = getattr(liveaction_db, "context", dict()) user = context.get("user", cfg.CONF.system_user.user) config = None # Note: Right now configs are only supported by the Python runner actions if (runner_type_db.name == "python-script" or runner_type_db.runner_module == "python_runner"): LOG.debug("Loading config from pack for python runner.") config_loader = ContentPackConfigLoader(pack_name=action_db.pack, user=user) config = config_loader.get_config() runner = get_runner(name=runner_type_db.name, config=config) # TODO: Pass those arguments to the constructor instead of late # assignment, late assignment is awful runner.runner_type = runner_type_db runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.execution = ActionExecution.get( liveaction__id=runner.liveaction_id) runner.execution_id = str(runner.execution.id) runner.entry_point = resolved_entry_point runner.context = context runner.callback = getattr(liveaction_db, "callback", dict()) runner.libs_dir_path = self._get_action_libs_abs_path( action_db.pack, action_db.entry_point) # For re-run, get the ActionExecutionDB in which the re-run is based on. rerun_ref_id = runner.context.get("re-run", {}).get("ref") runner.rerun_ex_ref = (ActionExecution.get( id=rerun_ref_id) if rerun_ref_id else None) return runner
def _invoke_post_run(self, actionexec_db, action_db): LOG.info( 'Invoking post run for action execution %s. Action=%s; Runner=%s', actionexec_db.id, action_db.name, action_db.runner_type['name']) # Get an instance of the action runner. runnertype_db = get_runnertype_by_name(action_db.runner_type['name']) runner = get_runner(runnertype_db.runner_module) # Configure the action runner. runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(actionexec_db.id) runner.entry_point = RunnerContainerService.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) runner.context = getattr(actionexec_db, 'context', dict()) runner.callback = getattr(actionexec_db, 'callback', dict()) runner.libs_dir_path = RunnerContainerService.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) # Invoke the post_run method. runner.post_run(actionexec_db.status, actionexec_db.result)
def _get_runner(self, runner_type_db, action_db, liveaction_db): resolved_entry_point = self._get_entry_point_abs_path(action_db.pack, action_db.entry_point) context = getattr(liveaction_db, 'context', dict()) user = context.get('user', cfg.CONF.system_user.user) config = None # Note: Right now configs are only supported by the Python runner actions if (runner_type_db.name == 'python-script' or runner_type_db.runner_module == 'python_runner'): LOG.debug('Loading config from pack for python runner.') config_loader = ContentPackConfigLoader(pack_name=action_db.pack, user=user) config = config_loader.get_config() runner = get_runner( name=runner_type_db.name, config=config) # TODO: Pass those arguments to the constructor instead of late # assignment, late assignment is awful runner.runner_type = runner_type_db runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.execution = ActionExecution.get(liveaction__id=runner.liveaction_id) runner.execution_id = str(runner.execution.id) runner.entry_point = resolved_entry_point runner.context = context runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path(action_db.pack, action_db.entry_point) # For re-run, get the ActionExecutionDB in which the re-run is based on. rerun_ref_id = runner.context.get('re-run', {}).get('ref') runner.rerun_ex_ref = ActionExecution.get(id=rerun_ref_id) if rerun_ref_id else None return runner
def get_runner_class(cls, runner_name): return runners.get_runner(runner_name, runner_name).__class__
def test_get_runner_module(self): runner = get_runner(name='local-shell-script') self.assertIsNotNone(runner, 'TestRunner must be valid.')
def test_get_runner_module(self): runnertype_db = RunnerContainerTest.runnertype_db runner = get_runner(runnertype_db.runner_module) self.assertTrue(runner is not None, 'TestRunner must be valid.')
def test_get_runner_success(self): runner = get_runner('local-shell-cmd') self.assertTrue(runner) self.assertEqual(runner.__class__.__name__, 'LocalShellCommandRunner')
def get_runner_class(cls, package_name, module_name): return runners.get_runner(package_name, module_name).__class__
def test_get_runner_module(self): runnertype_db = RunnerContainerTest.runnertype_db runner = get_runner(runnertype_db.runner_module, runnertype_db.runner_module) self.assertTrue(runner is not None, 'TestRunner must be valid.')
def test_get_runner_success(self): runner = get_runner("local-shell-cmd") self.assertTrue(runner) self.assertEqual(runner.__class__.__name__, "LocalShellCommandRunner")
def test_get_runner_module(self): runner = get_runner(name='local-shell-script') self.assertTrue(runner is not None, 'TestRunner must be valid.')