def _run_step_implementer_test( self, config, step, expected_step_results, test_dir, environment=None ): working_dir_path = os.path.join(test_dir.path, 'step-runner-working') factory = StepRunner( config=config, results_file_name='step-runner-results.yml', work_dir_path=working_dir_path ) factory.run_step( step_name=step, environment=environment ) pickle = f'{working_dir_path}/step-runner-results.pkl' workflow_result = WorkflowResult.load_from_pickle_file(pickle) step_result = workflow_result.get_step_result( step_name=step ) self.assertEqual(step_result, expected_step_results)
def test_run_step_config_only_sub_step_and_is_dict_rather_then_array(self): config = { 'step-runner-config': { 'foo': { 'implementer': 'tests.helpers.sample_step_implementers.FooStepImplementer' } } } with TempDirectory() as temp_dir: factory = StepRunner(config) factory.run_step('foo')
def test_run_step_with_no_config(self): config = { 'step-runner-config': { } } factory = StepRunner(config) with self.assertRaisesRegex( AssertionError, r"Can not run step \(foo\) because no step configuration provided."): factory.run_step('foo')
def test_run_step_config_implementer_specified_and_no_sub_step_config_specified_StepImplementer(self): config = { 'step-runner-config': { 'foo': [ { 'implementer': 'tests.helpers.sample_step_implementers.FooStepImplementer' } ] } } with TempDirectory() as temp_dir: factory = StepRunner(config) factory.run_step('foo')
def test_run_step_config_specified_StepImplementer_does_not_exist(self): config = { 'step-runner-config': { 'foo': [ { 'implementer': 'DoesNotExist' } ] } } factory = StepRunner(config) with self.assertRaisesRegex( StepRunnerException, r"Could not dynamically load step \(foo\) step implementer \(DoesNotExist\)" r" from module \(ploigos_step_runner.step_implementers.foo\) with class name \(DoesNotExist\)"): factory.run_step('foo')
def test_run_step_multiple_sub_steps_first_sub_step_fail_contine_sub_steps_on_failure_str( self, foo_step_implementer_run_step_mock, foo_step_implementer2_run_step_mock ): config = { 'step-runner-config': { 'foo': [ { 'name': 'Mock Sub Step 1', 'continue-sub-steps-on-failure': 'true', 'implementer': 'tests.helpers.sample_step_implementers.FooStepImplementer' }, { 'name': 'Mock Sub Step 2', 'implementer': 'tests.helpers.sample_step_implementers.FooStepImplementer2' } ] } } # mock return value mock_sub_step_1_result = StepResult( step_name='foo', sub_step_name='Mock Sub Step 1', sub_step_implementer_name='tests.helpers.sample_step_implementers.FooStepImplementer' ) mock_sub_step_1_result.success = False mock_sub_step_2_result = StepResult( step_name='foo', sub_step_name='Mock Sub Step 2', sub_step_implementer_name='tests.helpers.sample_step_implementers.FooStepImplementer' ) mock_sub_step_2_result.success = True foo_step_implementer_run_step_mock.return_value = mock_sub_step_1_result foo_step_implementer2_run_step_mock.return_value = mock_sub_step_2_result # run test step_runner = StepRunner(config) actual_success = step_runner.run_step('foo') # validate self.assertFalse(actual_success) foo_step_implementer_run_step_mock.assert_called_once() foo_step_implementer2_run_step_mock.assert_called_once()
def main(argv=None): """Main entry point for Ploigos step runner. """ parser = argparse.ArgumentParser(description='Ploigos Step Runner (psr)') parser.add_argument( '-s', '--step', required=True, help='Workflow step to run' ) parser.add_argument( '-e', '--environment', required=False, help='The environment to run this step against.' ) parser.add_argument( '-c', '--config', required=True, nargs='+', help='Workflow configuration files, or directories containing files, in yml or json' ) parser.add_argument( '--step-config', metavar='STEP_CONFIG_KEY=STEP_CONFIG_VALUE', nargs='+', help='Override step config provided by the given config-file with these arguments.', action=ParseKeyValueArge ) args = parser.parse_args(argv) obfuscated_stdout = TextIOSelectiveObfuscator(sys.stdout) obfuscated_stderr = TextIOSelectiveObfuscator(sys.stderr) DecryptionUtils.register_obfuscation_stream(obfuscated_stdout) DecryptionUtils.register_obfuscation_stream(obfuscated_stderr) with redirect_stdout(obfuscated_stdout), redirect_stderr(obfuscated_stderr): # validate args for config_file in args.config: if not os.path.exists(config_file) or os.stat(config_file).st_size == 0: print_error('specified -c/--config must exist and not be empty') sys.exit(101) try: config = Config(args.config) except (ValueError, AssertionError) as error: print_error(f"specified -c/--config is invalid configuration: {error}") sys.exit(102) config.set_step_config_overrides(args.step, args.step_config) # it is VERY important that the working dir be an absolute path because some # commands (looking at you maven) will change the context of relative paths on you step_runner = StepRunner( config=config, work_dir_path=os.path.abspath('step-runner-working') ) try: if not step_runner.run_step(args.step, args.environment): print_error(f"Step {args.step} not successful") sys.exit(200) except Exception as error: # pylint: disable=broad-except print_error(f"Fatal error calling step ({args.step}): {str(error)}") track = traceback.format_exc() print(track) sys.exit(300)