def test_chain_runner_chain_second_task_times_out(self, request): # Second task in the chain times out so the action chain status should be timeout chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_2_PATH chain_runner.action = ACTION_1 original_run_action = chain_runner._run_action def mock_run_action(*args, **kwargs): original_live_action = args[0] liveaction = original_run_action(*args, **kwargs) if original_live_action.action == 'wolfpack.a2': # Mock a timeout for second task liveaction.status = LIVEACTION_STATUS_TIMED_OUT return liveaction chain_runner._run_action = mock_run_action action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) chain_runner.liveaction = LiveActionDB(action=action_ref) chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, _, _ = chain_runner.run({}) self.assertEqual(status, LIVEACTION_STATUS_TIMED_OUT) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # based on the chain the callcount is known to be 3. Not great but works. self.assertEqual(request.call_count, 3)
def test_render_params_action_context_non_existent_member(self): runner = acr.get_runner() chain_context = { 'parent': { 'execution_id': 'some_awesome_exec_id', 'user': '******' }, 'user': '******', 'k1': 'v1' } task_params = { 'exec_id': { 'default': '{{action_context.parent.yo_gimme_tha_key}}' }, 'k2': {}, 'foo': { 'default': 1 } } action_node = Node(name='test_action_context_params', ref='core.local', params=task_params) try: runner._resolve_params(action_node, {}, {}, {}, chain_context) self.fail('Should have thrown an instance of %s' % ParameterRenderingFailedException) except ParameterRenderingFailedException: pass
def test_chain_runner_publish(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_WITH_PUBLISH chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.runner_parameters = {'display_published': True} chain_runner.pre_run() action_parameters = {'action_param_1': 'test value 1'} _, result, _ = chain_runner.run(action_parameters=action_parameters) # We also assert that the action parameters are available in the # "publish" scope self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_value = { 'inttype': 1, 'strtype': 'published', 'booltype': True, 'published_action_param': action_parameters['action_param_1'] } mock_args, _ = request.call_args self.assertEqual(mock_args[0].parameters, expected_value) # Assert that the variables are correctly published self.assertEqual(result['published'], { 'published_action_param': u'test value 1', 'o1': u'published' })
def test_chain_runner_failure_during_param_rendering_multiple_tasks( self, request): # Parameter rendering should result in a top level error which aborts # the whole chain chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_SECOND_TASK_RENDER_FAIL_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, result, _ = chain_runner.run({}) # Verify that only first task has ran self.assertEqual(status, LIVEACTION_STATUS_FAILED) self.assertEqual(len(result['tasks']), 1) self.assertEqual(result['tasks'][0]['name'], 'c1') expected_error = ( 'Failed rendering value for action parameter "p1" in ' 'task "c2" (template string={{s1}}):') self.assertTrue('error' in result) self.assertTrue('traceback' in result) self.assertTrue('Failed to run task "c2". Parameter rendering failed' in result['error']) self.assertTrue(expected_error in result['error']) self.assertTrue('Traceback' in result['traceback'])
def test_chain_runner_task_is_canceled_while_running(self, request): # Second task in the action is CANCELED, make sure runner doesn't get stuck in an infinite # loop chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_2_PATH chain_runner.action = ACTION_1 original_run_action = chain_runner._run_action def mock_run_action(*args, **kwargs): original_live_action = args[0] if original_live_action.action == 'wolfpack.a2': status = LIVEACTION_STATUS_CANCELED else: status = LIVEACTION_STATUS_SUCCEEDED request.return_value = (DummyActionExecution(status=status), None) liveaction = original_run_action(*args, **kwargs) return liveaction chain_runner._run_action = mock_run_action action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) chain_runner.liveaction = LiveActionDB(action=action_ref) chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, _, _ = chain_runner.run({}) self.assertEqual(status, LIVEACTION_STATUS_CANCELED) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # Chain count should be 2 since the last task doesn't get called since the second one was # canceled self.assertEqual(request.call_count, 2)
def test_render_params_action_context(self): runner = acr.get_runner() chain_context = { 'parent': { 'execution_id': 'some_awesome_exec_id', 'user': '******' }, 'user': '******', 'k1': 'v1' } task_params = { 'exec_id': { 'default': '{{action_context.parent.execution_id}}' }, 'k2': {}, 'foo': { 'default': 1 } } action_node = Node(name='test_action_context_params', ref='core.local', params=task_params) rendered_params = runner._resolve_params(action_node, {}, {}, {}, chain_context) self.assertEqual(rendered_params['exec_id']['default'], 'some_awesome_exec_id')
def test_chain_runner_missing_param_temp(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_STR_TEMP_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertEqual(schedule.call_count, 0, 'No call expected.')
def test_chain_runner_missing_param_temp(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_FIRST_TASK_RENDER_FAIL_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertEqual(request.call_count, 0, 'No call expected.')
def test_params_and_parameters_attributes_both_work(self, _): # "params" attribute used chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_PARAMS_ATTRIBUTE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() original_build_liveaction_object = chain_runner._build_liveaction_object def mock_build_liveaction_object(action_node, resolved_params, parent_context): # Verify parameters are correctly passed to the action self.assertEqual(resolved_params, {'pparams': 'v1'}) original_build_liveaction_object(action_node=action_node, resolved_params=resolved_params, parent_context=parent_context) chain_runner._build_liveaction_object = mock_build_liveaction_object action_parameters = {} status, output, _ = chain_runner.run( action_parameters=action_parameters) self.assertEqual(status, LIVEACTION_STATUS_SUCCEEDED) # "parameters" attribute used chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_PARAMETERS_ATTRIBUTE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() def mock_build_liveaction_object(action_node, resolved_params, parent_context): # Verify parameters are correctly passed to the action self.assertEqual(resolved_params, {'pparameters': 'v1'}) original_build_liveaction_object(action_node=action_node, resolved_params=resolved_params, parent_context=parent_context) chain_runner._build_liveaction_object = mock_build_liveaction_object action_parameters = {} status, output, _ = chain_runner.run( action_parameters=action_parameters) self.assertEqual(status, LIVEACTION_STATUS_SUCCEEDED)
def test_chain_runner_bad_default(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_BAD_DEFAULT chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() expected_msg = 'Unable to find node with name "bad_default" referenced in "default".' self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, expected_msg, chain_runner.pre_run)
def test_malformed_chain(self): try: chain_runner = acr.get_runner() chain_runner.entry_point = MALFORMED_CHAIN_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() self.assertTrue(False, 'Expected pre_run to fail.') except runnerexceptions.ActionRunnerPreRunError: self.assertTrue(True)
def test_chain_runner_str_param_temp(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_FIRST_TASK_RENDER_FAIL_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) mock_args, _ = schedule.call_args self.assertEqual(mock_args[0].parameters, {"p1": "1"})
def test_exception_is_thrown_if_both_params_and_parameters_attributes_are_provided(self): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_PARAMS_AND_PARAMETERS_ATTRIBUTE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() expected_msg = ('Either "params" or "parameters" attribute needs to be provided, but ' 'not both') self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, expected_msg, chain_runner.pre_run)
def test_chain_runner_broken_on_failure_path_static_task_name(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_BROKEN_ON_FAILURE_PATH_STATIC_TASK_NAME chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() expected_msg = ('Unable to find node with name "c6" referenced in "on-failure" ' 'in task "c2"') self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, expected_msg, chain_runner.pre_run)
def test_chain_runner_list_param_temp(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_LIST_TEMP_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) mock_args, _ = request.call_args self.assertEqual(mock_args[0].parameters, {"p1": "[2, 3, 4]"})
def test_chain_runner_action_exception(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = DummyAction() chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.action_chain, None) # based on the chain the callcount is known to be 2. Not great but works. self.assertEqual(schedule.call_count, 2)
def test_chain_runner_str_param_temp(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_STR_TEMP_PATH chain_runner.action = DummyAction() chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) self.assertNotEqual(chain_runner.action_chain, None) mock_args, _ = schedule.call_args self.assertEqual(mock_args[0].parameters, {"p1": "1"})
def test_chain_runner_success_path_with_wait(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # based on the chain the callcount is known to be 3. Not great but works. self.assertEqual(request.call_count, 3)
def test_chain_runner_action_exception(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.action_chain, None) # based on the chain the callcount is known to be 2. Not great but works. self.assertEqual(schedule.call_count, 2)
def test_chain_runner_success_path_with_wait(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = DummyAction() chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.action_chain, None) # based on the chain the callcount is known to be 3. Not great but works. self.assertEqual(schedule.call_count, 3)
def test_params_and_parameters_attributes_both_work(self, _): # "params" attribute used chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_PARAMS_ATTRIBUTE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() original_build_liveaction_object = chain_runner._build_liveaction_object def mock_build_liveaction_object(action_node, resolved_params, parent_context): # Verify parameters are correctly passed to the action self.assertEqual(resolved_params, {'pparams': 'v1'}) original_build_liveaction_object(action_node=action_node, resolved_params=resolved_params, parent_context=parent_context) chain_runner._build_liveaction_object = mock_build_liveaction_object action_parameters = {} status, output, _ = chain_runner.run(action_parameters=action_parameters) self.assertEqual(status, LIVEACTION_STATUS_SUCCEEDED) # "parameters" attribute used chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_PARAMETERS_ATTRIBUTE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() def mock_build_liveaction_object(action_node, resolved_params, parent_context): # Verify parameters are correctly passed to the action self.assertEqual(resolved_params, {'pparameters': 'v1'}) original_build_liveaction_object(action_node=action_node, resolved_params=resolved_params, parent_context=parent_context) chain_runner._build_liveaction_object = mock_build_liveaction_object action_parameters = {} status, output, _ = chain_runner.run(action_parameters=action_parameters) self.assertEqual(status, LIVEACTION_STATUS_SUCCEEDED)
def test_chain_runner_failure_path(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, _, _ = chain_runner.run({}) self.assertEqual(status, LIVEACTION_STATUS_FAILED) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # based on the chain the callcount is known to be 2. Not great but works. self.assertEqual(request.call_count, 2)
def test_chain_runner_dict_param_temp(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_DICT_TEMP_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_value = {"p1": {"p1.3": "[3, 4]", "p1.2": "2", "p1.1": "1"}} mock_args, _ = request.call_args self.assertEqual(mock_args[0].parameters, expected_value)
def test_chain_runner_vars_action_params(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_WITH_ACTIONPARAM_VARS chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'input_a': 'two'}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_value = {'inttype': 1, 'strtype': 'two', 'booltype': True} mock_args, _ = request.call_args self.assertEqual(mock_args[0].parameters, expected_value)
def test_chain_runner_broken_on_failure_path_static_task_name( self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_BROKEN_ON_FAILURE_PATH_STATIC_TASK_NAME chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() expected_msg = ( 'Unable to find node with name "c6" referenced in "on-failure" ' 'in task "c2"') self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, expected_msg, chain_runner.pre_run)
def test_exception_is_thrown_if_both_params_and_parameters_attributes_are_provided( self): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_PARAMS_AND_PARAMETERS_ATTRIBUTE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() expected_msg = ( 'Either "params" or "parameters" attribute needs to be provided, but ' 'not both') self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, expected_msg, chain_runner.pre_run)
def test_chain_task_passes_invalid_parameter_type_to_action(self, mock_request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_INVALID_PARAMETER_TYPE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() action_parameters = {} expected_msg = ('Failed to cast value "stringnotanarray" for parameter ' '"arrtype" of type "array"') self.assertRaisesRegexp(ValueError, expected_msg, chain_runner.run, action_parameters=action_parameters)
def test_chain_runner_failure_path(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = DummyAction() chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() success = chain_runner.run({}) self.assertFalse(success) self.assertEqual(chain_runner.container_service.get_status(), ACTIONEXEC_STATUS_FAILED) self.assertNotEqual(chain_runner.action_chain, None) # based on the chain the callcount is known to be 2. Not great but works. self.assertEqual(schedule.call_count, 2)
def test_chain_runner_failure_path(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() success = chain_runner.run({}) self.assertFalse(success) self.assertEqual(chain_runner.container_service.get_status(), ACTIONEXEC_STATUS_FAILED) self.assertNotEqual(chain_runner.action_chain, None) # based on the chain the callcount is known to be 2. Not great but works. self.assertEqual(schedule.call_count, 2)
def test_chain_runner_action_exception(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, results = chain_runner.run({}) self.assertEqual(status, ACTIONEXEC_STATUS_FAILED) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # based on the chain the callcount is known to be 2. Not great but works. self.assertEqual(schedule.call_count, 2) self.assertEqual(len([result['error'] for _, result in six.iteritems(results)]), 2, 'Expected errors')
def test_chain_runner_publish(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_WITH_PUBLISH chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_value = {'inttype': 1, 'strtype': 'published', 'booltype': True} mock_args, _ = schedule.call_args self.assertEqual(mock_args[0].parameters, expected_value)
def test_chain_runner_no_default(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_NO_DEFAULT chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # In case of this chain default_node is the first_node. default_node = chain_runner.chain_holder.actionchain.default first_node = chain_runner.chain_holder.actionchain.chain[0] self.assertEqual(default_node, first_node.name) # based on the chain the callcount is known to be 3. Not great but works. self.assertEqual(request.call_count, 3)
def test_chain_runner_success_path(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) chain_runner.liveaction = LiveActionDB(action=action_ref) chain_runner.liveaction.notify = CHAIN_NOTIFY_DB chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # based on the chain the callcount is known to be 3. Not great but works. self.assertEqual(request.call_count, 3)
def test_chain_runner_dependent_param_temp(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_DEP_INPUT chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_values = [{u'p1': u'1'}, {u'p1': u'1'}, {u'p2': u'1', u'p3': u'1', u'p1': u'1'}] # Each of the call_args must be one of for call_args in schedule.call_args_list: self.assertTrue(call_args[0][0].parameters in expected_values) expected_values.remove(call_args[0][0].parameters) self.assertEqual(len(expected_values), 0, 'Not all expected values received.')
def test_chain_runner_success_path(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) self.assertEqual(request.call_count, 2) first_call_args = request.call_args_list[0][0] liveaction_db = first_call_args[0] self.assertTrue(liveaction_db.notify, 'Notify property expected.') second_call_args = request.call_args_list[1][0] liveaction_db = second_call_args[0] self.assertFalse(liveaction_db.notify, 'Notify property not expected.')
def test_chain_runner_dependent_param_temp(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_DEP_INPUT chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_values = [{u'p1': u'1'}, {u'p1': u'1'}, {u'p2': u'1', u'p3': u'1', u'p1': u'1'}] # Each of the call_args must be one of for call_args in request.call_args_list: self.assertTrue(call_args[0][0].parameters in expected_values) expected_values.remove(call_args[0][0].parameters) self.assertEqual(len(expected_values), 0, 'Not all expected values received.')
def test_chain_task_passes_invalid_parameter_type_to_action( self, mock_request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_INVALID_PARAMETER_TYPE chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() action_parameters = {} expected_msg = ( 'Failed to cast value "stringnotanarray" \(type: str\) for parameter ' '"arrtype" of type "array"') self.assertRaisesRegexp(ValueError, expected_msg, chain_runner.run, action_parameters=action_parameters)
def test_action_chain_runner_referenced_action_doesnt_exist(self, mock_request): # Action referenced by a task doesn't exist, should result in a top level error chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_WITH_INVALID_ACTION chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() action_parameters = {} status, output, _ = chain_runner.run(action_parameters=action_parameters) expected_error = ('Failed to run task "c1". Action with reference "wolfpack.a2" ' 'doesn\'t exist.') self.assertEqual(status, LIVEACTION_STATUS_FAILED) self.assertTrue(expected_error in output['error']) self.assertTrue(expected_error in output['traceback'])
def test_chain_runner_success_task_action_call_with_no_params(self, request): # Make sure that the runner doesn't explode if task definition contains # no "params" section chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_ACTION_CALL_NO_PARAMS_PATH chain_runner.action = ACTION_1 action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) chain_runner.liveaction = LiveActionDB(action=action_ref) chain_runner.liveaction.notify = CHAIN_NOTIFY_DB chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) # based on the chain the callcount is known to be 3. Not great but works. self.assertEqual(request.call_count, 3)
def test_chain_runner_success_path(self, schedule): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_1_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) self.assertEqual(schedule.call_count, 2) first_call_args = schedule.call_args_list[0][0] liveaction_db = first_call_args[0] self.assertTrue(liveaction_db.notify, 'Notify property expected.') second_call_args = schedule.call_args_list[1][0] liveaction_db = second_call_args[0] self.assertFalse(liveaction_db.notify, 'Notify property not expected.')
def test_action_chain_runner_referenced_action_doesnt_exist(self, mock_schedule): # Action referenced by a task doesn't exist, should result in a top level error chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_WITH_INVALID_ACTION chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() action_parameters = {} status, output, _ = chain_runner.run(action_parameters=action_parameters) expected_error = ('Failed to run task "c1". Action with reference "wolfpack.a2" ' 'doesn\'t exist.') self.assertEqual(status, LIVEACTION_STATUS_FAILED) self.assertTrue(expected_error in output['error']) self.assertTrue(expected_error in output['traceback'])
def test_chain_runner_broken_fail_path(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_BROKEN_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, result, _ = chain_runner.run({}) self.assertEqual(status, LIVEACTION_STATUS_FAILED) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) self.assertTrue('Failed to get next node "c1". Lookup failed:' in result['error']) self.assertTrue('Unable to find node with name "c4"' in result['error']) self.assertTrue('Traceback (most recent call last):' in result['traceback']) # based on the chain the callcount is known to be 1. Not great but works. self.assertEqual(request.call_count, 1)
def test_chain_runner_dependent_results_param(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_DEP_RESULTS_INPUT chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_values = [{u'p1': u'1'}, {u'p1': u'1'}, {u'out': u"{'c2': {'o1': '1'}, 'c1': {'o1': '1'}}"}] # Each of the call_args must be one of self.assertEqual(request.call_count, 3) for call_args in request.call_args_list: self.assertTrue(call_args[0][0].parameters in expected_values) expected_values.remove(call_args[0][0].parameters) self.assertEqual(len(expected_values), 0, 'Not all expected values received.')
def test_chain_runner_failure_during_param_rendering_single_task(self, request): # Parameter rendering should result in a top level error which aborts # the whole chain chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_FIRST_TASK_RENDER_FAIL_PATH chain_runner.action = ACTION_1 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() status, result, _ = chain_runner.run({}) # No tasks ran because rendering of parameters for the first task failed self.assertEqual(status, LIVEACTION_STATUS_FAILED) self.assertEqual(result['tasks'], []) self.assertTrue('error' in result) self.assertTrue('traceback' in result) self.assertTrue('Failed to run task "c1". Parameter rendering failed' in result['error']) self.assertTrue('Traceback' in result['traceback'])
def test_chain_runner_typed_params(self, request): chain_runner = acr.get_runner() chain_runner.entry_point = CHAIN_TYPED_PARAMS chain_runner.action = ACTION_2 chain_runner.container_service = RunnerContainerService() chain_runner.pre_run() chain_runner.run({'s1': 1, 's2': 'two', 's3': 3.14}) self.assertNotEqual(chain_runner.chain_holder.actionchain, None) expected_value = {'booltype': True, 'inttype': 1, 'numbertype': 3.14, 'strtype': 'two', 'arrtype': ['1', 'two'], 'objtype': {'s2': 'two', 'k1': '1'}} mock_args, _ = request.call_args self.assertEqual(mock_args[0].parameters, expected_value)