diff --git a/orquesta/rehearsing.py b/orquesta/rehearsing.py index 23bc6a6a..c8dbf954 100644 --- a/orquesta/rehearsing.py +++ b/orquesta/rehearsing.py @@ -184,6 +184,7 @@ class WorkflowTestCase(native_v1_specs.Spec, WorkflowTestCaseMixin): "type": "object", "properties": { "workflow": spec_types.NONEMPTY_STRING, + "context": {"type": "object", "default": {}}, "inputs": {"type": "object", "default": {}}, "expected_inspection_errors": MockInspectionErrors, "expected_routes": {"type": "array", "items": {"type": "array"}, "default": [[]]}, @@ -224,6 +225,7 @@ class WorkflowRerunTestCase(native_v1_specs.Spec, WorkflowTestCaseMixin): "workflow_state": {"type": "object"}, "rerun_tasks": requests.TaskRerunRequestSequenceSpec, "expected_inspection_errors": MockInspectionErrors, + "context": {"type": "object", "default": {}}, "expected_routes": {"type": "array", "items": {"type": "array"}, "default": [[]]}, "expected_task_sequence": {"type": "array", "items": spec_types.NONEMPTY_STRING}, "mock_action_executions": MockActionExecutionSequenceSpec, @@ -314,7 +316,7 @@ def runTest(self): pass def assert_spec_inspection(self): - self.inspection_errors = self.wf_spec.inspect() + self.inspection_errors = self.wf_spec.inspect(app_ctx=self.session.context) self.assertDictEqual(self.inspection_errors, self.session.expected_inspection_errors) def assert_conducting_sequence(self): @@ -334,7 +336,9 @@ def assert_conducting_sequence(self): if not self.rerun: # Instantiate a workflow conductor to check conducting sequences. - self.conductor = conducting.WorkflowConductor(self.wf_spec, inputs=self.session.inputs) + self.conductor = conducting.WorkflowConductor( + self.wf_spec, inputs=self.session.inputs, context=self.session.context + ) self.conductor.request_workflow_status(statuses.RUNNING) else: # Request workflow rerun and assert workflow status is running. diff --git a/orquesta/tests/fixtures/rehearsals/tests/sequential_success_w_context.yaml b/orquesta/tests/fixtures/rehearsals/tests/sequential_success_w_context.yaml new file mode 100644 index 00000000..f20e5330 --- /dev/null +++ b/orquesta/tests/fixtures/rehearsals/tests/sequential_success_w_context.yaml @@ -0,0 +1,24 @@ +--- +workflow: workflows/sequential_w_context.yaml +inputs: + name: Stanley +context: + st2: + api_url: http://localhost + token: faketoken +expected_task_sequence: + - task1 + - task2 + - task3 + - continue +mock_action_executions: + - task_id: task1 + result: Stanley + - task_id: task2 + result: All your base are belong to us! + - task_id: task3 + result: Stanley, All your base are belong to us! +expected_output: + greeting: Stanley, All your base are belong to us! + api_url: http://localhost + token: faketoken diff --git a/orquesta/tests/fixtures/rehearsals/workflows/sequential_w_context.yaml b/orquesta/tests/fixtures/rehearsals/workflows/sequential_w_context.yaml new file mode 100644 index 00000000..5640f057 --- /dev/null +++ b/orquesta/tests/fixtures/rehearsals/workflows/sequential_w_context.yaml @@ -0,0 +1,37 @@ +version: 1.0 + +description: A basic sequential workflow. + +input: + - name + +vars: + - greeting: null + +output: + - greeting: <% ctx().greeting %> + - api_url: <% ctx().st2.api_url %> + - token: <% ctx().st2.token %> + +tasks: + task1: + action: core.echo message=<% ctx().name %> + next: + - when: <% succeeded() %> + publish: greeting=<% result() %> + do: task2 + task2: + action: core.echo + input: + message: "All your base are belong to us!" + next: + - when: <% succeeded() %> + publish: + - greeting: <% ctx("greeting") %>, <% result() %> + do: + - task3 + task3: + action: core.echo message=<% ctx('greeting') %> + next: + - when: <% succeeded() %> + publish: greeting=<% result() %> diff --git a/orquesta/tests/fixtures/workflows/native/sequential_w_context.yaml b/orquesta/tests/fixtures/workflows/native/sequential_w_context.yaml new file mode 100644 index 00000000..5640f057 --- /dev/null +++ b/orquesta/tests/fixtures/workflows/native/sequential_w_context.yaml @@ -0,0 +1,37 @@ +version: 1.0 + +description: A basic sequential workflow. + +input: + - name + +vars: + - greeting: null + +output: + - greeting: <% ctx().greeting %> + - api_url: <% ctx().st2.api_url %> + - token: <% ctx().st2.token %> + +tasks: + task1: + action: core.echo message=<% ctx().name %> + next: + - when: <% succeeded() %> + publish: greeting=<% result() %> + do: task2 + task2: + action: core.echo + input: + message: "All your base are belong to us!" + next: + - when: <% succeeded() %> + publish: + - greeting: <% ctx("greeting") %>, <% result() %> + do: + - task3 + task3: + action: core.echo message=<% ctx('greeting') %> + next: + - when: <% succeeded() %> + publish: greeting=<% result() %> diff --git a/orquesta/tests/unit/commands/test_rehearse_command.py b/orquesta/tests/unit/commands/test_rehearse_command.py index 86cd7a7a..035e2632 100644 --- a/orquesta/tests/unit/commands/test_rehearse_command.py +++ b/orquesta/tests/unit/commands/test_rehearse_command.py @@ -147,3 +147,18 @@ def test_rehearse_multiple(self): "There are errors processing test specs. Please review details above.", rehearsal.rehearse, ) + + @mock.patch.object( + argparse.ArgumentParser, + "parse_args", + mock.MagicMock( + return_value=argparse.Namespace( + base_path=fixture_loader.get_rehearsal_fixtures_base_path(), + test_spec="tests/sequential_success_w_context.yaml", + test_spec_dir=None, + debug=False, + ) + ), + ) + def test_rehearse_success_w_context(self): + rehearsal.rehearse() diff --git a/orquesta/tests/unit/specs/native/test_workflow_rehearsal_spec.py b/orquesta/tests/unit/specs/native/test_workflow_rehearsal_spec.py index a431134b..949fd790 100644 --- a/orquesta/tests/unit/specs/native/test_workflow_rehearsal_spec.py +++ b/orquesta/tests/unit/specs/native/test_workflow_rehearsal_spec.py @@ -598,3 +598,28 @@ def test_init_test_spec_bad_result_path(self): rehearsing.WorkflowRehearsal, test_case, ) + + def test_load_test_spec_dict_with_context(self): + test_spec = { + "workflow": self.get_wf_file_path("sequential_w_context"), + "context": {"st2": {"api_url": "http://localhost", "token": "faketoken"}}, + "expected_task_sequence": ["task1", "task2", "task3", "continue"], + "mock_action_executions": [{"task_id": "task1"}, {"task_id": "task2"}], + } + + rehearsal = rehearsing.load_test_spec(test_spec) + + self.assertEqual(len(rehearsal.session.mock_action_executions), 2) + self.assertEqual(rehearsal.session.mock_action_executions[0].task_id, "task1") + self.assertEqual(rehearsal.session.mock_action_executions[1].task_id, "task2") + self.assertEqual(rehearsal.session.context, test_spec["context"]) + + for ac_ex in rehearsal.session.mock_action_executions: + self.assertIsInstance(ac_ex, rehearsing.MockActionExecution) + self.assertEqual(ac_ex.route, 0) + self.assertIsNone(ac_ex.seq_id) + self.assertIsNone(ac_ex.item_id) + self.assertEqual(ac_ex.iter_id, 0) + self.assertEqual(ac_ex.num_iter, 1) + self.assertEqual(ac_ex.status, statuses.SUCCEEDED) + self.assertIsNone(ac_ex.result)