diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 99bad03245..5174e90086 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -59,6 +59,8 @@ Fixed * Make sure we don't log auth token and api key inside st2api log file if those values are provided via query parameter and not header (``?x-auth-token=foo``, ``?st2-api-key=bar``). (bug fix) #4592 #4589 +* Fix rendering of config_context in orquesta task that references action in different pack + (bug fix) #4570 2.10.3 - March 06, 2019 ----------------------- diff --git a/contrib/examples/actions/render_config_context.yaml b/contrib/examples/actions/render_config_context.yaml new file mode 100644 index 0000000000..f9c307f130 --- /dev/null +++ b/contrib/examples/actions/render_config_context.yaml @@ -0,0 +1,8 @@ +--- +name: render_config_context +pack: examples +description: Run render config context workflow +runner_type: orquesta +entry_point: workflows/render_config_context.yaml +enabled: true +parameters: {} diff --git a/contrib/examples/actions/workflows/render_config_context.yaml b/contrib/examples/actions/workflows/render_config_context.yaml new file mode 100644 index 0000000000..24f2d5394d --- /dev/null +++ b/contrib/examples/actions/workflows/render_config_context.yaml @@ -0,0 +1,7 @@ +version: 1.0 +description: Testing config context render". +tasks: + task1: + action: tests.render_config_context +output: + - context_value: <% task(task1).result.result.context_value %> diff --git a/st2common/st2common/services/workflows.py b/st2common/st2common/services/workflows.py index 192e6e1f1c..fb36e069ca 100644 --- a/st2common/st2common/services/workflows.py +++ b/st2common/st2common/services/workflows.py @@ -548,9 +548,12 @@ def request_action_execution(wf_ex_db, task_ex_db, st2_ctx, ac_ex_req, delay=Non # Identify the runner for the action. runner_type_db = action_utils.get_runnertype_by_name(action_db.runner_type['name']) + # Identify action pack name + pack_name = action_ref.split('.')[0] if action_ref else st2_ctx.get('pack') + # Set context for the action execution. ac_ex_ctx = { - 'pack': st2_ctx.get('pack'), + 'pack': pack_name, 'user': st2_ctx.get('user'), 'parent': st2_ctx, 'orquesta': { diff --git a/st2common/tests/unit/services/test_workflow.py b/st2common/tests/unit/services/test_workflow.py index fee8c52926..98269eb9d0 100644 --- a/st2common/tests/unit/services/test_workflow.py +++ b/st2common/tests/unit/services/test_workflow.py @@ -32,7 +32,9 @@ from st2common.exceptions import action as action_exc from st2common.models.db import liveaction as lv_db_models from st2common.models.db import execution as ex_db_models +from st2common.models.db import pack as pk_db_models from st2common.persistence import execution as ex_db_access +from st2common.persistence import pack as pk_db_access from st2common.persistence import workflow as wf_db_access from st2common.services import action as action_service from st2common.services import workflows as workflow_service @@ -44,8 +46,12 @@ TEST_PACK = 'orquesta_tests' TEST_PACK_PATH = st2tests.fixturesloader.get_fixtures_packs_base_path() + '/' + TEST_PACK +PACK_7 = 'dummy_pack_7' +PACK_7_PATH = st2tests.fixturesloader.get_fixtures_packs_base_path() + '/' + PACK_7 + PACKS = [ TEST_PACK_PATH, + PACK_7_PATH, st2tests.fixturesloader.get_fixtures_packs_base_path() + '/core' ] @@ -363,3 +369,67 @@ def test_evaluate_action_execution_delay(self): ac_ex_req = {'action': 'core.noop', 'input': None, 'item_id': 1} actual_delay = workflow_service.eval_action_execution_delay(task_ex_req, ac_ex_req, True) self.assertIsNone(actual_delay) + + 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) diff --git a/st2tests/integration/orquesta/test_wiring.py b/st2tests/integration/orquesta/test_wiring.py index 0306897810..e62e957377 100644 --- a/st2tests/integration/orquesta/test_wiring.py +++ b/st2tests/integration/orquesta/test_wiring.py @@ -144,3 +144,16 @@ def test_output_on_error(self): self.assertEqual(ex.status, ac_const.LIVEACTION_STATUS_FAILED) self.assertDictEqual(ex.result, expected_result) + + def test_config_context_renders(self): + config_value = "Testing" + wf_name = 'examples.render_config_context' + + expected_output = {'context_value': config_value} + expected_result = {'output': expected_output} + + ex = self._execute_workflow(wf_name) + ex = self._wait_for_completion(ex) + + self.assertEqual(ex.status, ac_const.LIVEACTION_STATUS_SUCCEEDED) + self.assertDictEqual(ex.result, expected_result) diff --git a/st2tests/st2tests/base.py b/st2tests/st2tests/base.py index ec5bb1ca0b..04344365ab 100644 --- a/st2tests/st2tests/base.py +++ b/st2tests/st2tests/base.py @@ -618,7 +618,8 @@ def mock_st2_context(self, ac_ex_db, context=None): st2_ctx = { 'st2': { 'api_url': api_util.get_full_public_api_url(), - 'action_execution_id': str(ac_ex_db.id) + 'action_execution_id': str(ac_ex_db.id), + 'user': 'stanley' } } diff --git a/st2tests/st2tests/fixtures/packs/configs/dummy_pack_7.yaml b/st2tests/st2tests/fixtures/packs/configs/dummy_pack_7.yaml new file mode 100644 index 0000000000..6b01d06715 --- /dev/null +++ b/st2tests/st2tests/fixtures/packs/configs/dummy_pack_7.yaml @@ -0,0 +1,2 @@ +--- +config_item_one: "testing" diff --git a/st2tests/st2tests/fixtures/packs/dummy_pack_7/actions/render_config_context.py b/st2tests/st2tests/fixtures/packs/dummy_pack_7/actions/render_config_context.py new file mode 100644 index 0000000000..97ab48fea0 --- /dev/null +++ b/st2tests/st2tests/fixtures/packs/dummy_pack_7/actions/render_config_context.py @@ -0,0 +1,7 @@ +from st2common.runners.base_action import Action + + +class PrintPythonVersionAction(Action): + + def run(self, value1): + return {"context_value": value1} diff --git a/st2tests/st2tests/fixtures/packs/dummy_pack_7/actions/render_config_context.yaml b/st2tests/st2tests/fixtures/packs/dummy_pack_7/actions/render_config_context.yaml new file mode 100644 index 0000000000..e67d323c65 --- /dev/null +++ b/st2tests/st2tests/fixtures/packs/dummy_pack_7/actions/render_config_context.yaml @@ -0,0 +1,12 @@ +--- +name: render_config_context +runner_type: python-script +description: Action that uses config context +enabled: true +entry_point: render_config_context.py +parameters: + value1: + description: Input for render_config_context. Defaults to config_context value. + required: false + type: "string" + default: "{{ config_context.config_item_one }}" diff --git a/st2tests/st2tests/fixtures/packs/dummy_pack_7/config.schema.yaml b/st2tests/st2tests/fixtures/packs/dummy_pack_7/config.schema.yaml new file mode 100644 index 0000000000..731f42d98c --- /dev/null +++ b/st2tests/st2tests/fixtures/packs/dummy_pack_7/config.schema.yaml @@ -0,0 +1,5 @@ +--- +config_item_one: + description: "Item use to test config context." + type: "string" + required: true diff --git a/st2tests/st2tests/fixtures/packs/orquesta_tests/actions/render_config_context.yaml b/st2tests/st2tests/fixtures/packs/orquesta_tests/actions/render_config_context.yaml new file mode 100644 index 0000000000..2f720cfd25 --- /dev/null +++ b/st2tests/st2tests/fixtures/packs/orquesta_tests/actions/render_config_context.yaml @@ -0,0 +1,8 @@ +--- +name: render_config_context +pack: orquesta_tests +description: Run render config context workflow +runner_type: orquesta +entry_point: workflows/render_config_context.yaml +enabled: true +parameters: {} diff --git a/st2tests/st2tests/fixtures/packs/orquesta_tests/actions/workflows/render_config_context.yaml b/st2tests/st2tests/fixtures/packs/orquesta_tests/actions/workflows/render_config_context.yaml new file mode 100644 index 0000000000..5683cbe98f --- /dev/null +++ b/st2tests/st2tests/fixtures/packs/orquesta_tests/actions/workflows/render_config_context.yaml @@ -0,0 +1,7 @@ +version: 1.0 +description: Testing config context render". +tasks: + task1: + action: dummy_pack_7.render_config_context +output: + - context_value: <% task(task1).result.result.context_value %> diff --git a/tools/launchdev.sh b/tools/launchdev.sh index 765104ae87..1f37336ea8 100755 --- a/tools/launchdev.sh +++ b/tools/launchdev.sh @@ -9,7 +9,7 @@ runner_count=1 scheduler_count=1 workflow_engine_count=1 use_gunicorn=true -copy_examples=false +copy_test_packs=false load_content=true use_ipv6=false include_mistral=false @@ -29,7 +29,7 @@ while getopts ":r:s:w:gxcu6m" o; do use_gunicorn=false ;; x) - copy_examples=true + copy_test_packs=true ;; c) load_content=false @@ -209,9 +209,20 @@ function st2start(){ cp -Rp ./contrib/core/ $PACKS_BASE_DIR cp -Rp ./contrib/packs/ $PACKS_BASE_DIR - if [ "$copy_examples" = true ]; then - echo "Copying examples from ./contrib/examples to $PACKS_BASE_DIR" + if [ "$copy_test_packs" = true ]; then + echo "Copying test packs examples and tests to $PACKS_BASE_DIR" cp -Rp ./contrib/examples $PACKS_BASE_DIR + # Clone st2tests in /tmp directory. + pushd /tmp + git clone https://github.com/StackStorm/st2tests.git + ret=$? + if [ ${ret} -eq 0 ]; then + cp -Rp ./st2tests/packs/tests $PACKS_BASE_DIR + rm -R st2tests/ + else + echo "Failed to clone st2tests repo" + fi + popd fi # activate virtualenv to set PYTHONPATH @@ -413,6 +424,13 @@ function st2start(){ --config-file $ST2_CONF --register-all fi + if [ "$copy_test_packs" = true ]; then + st2 run packs.setup_virtualenv packs=tests + if [ $? != 0 ]; then + echo "Warning: Unable to setup virtualenv for the \"tests\" pack. Please setup virtualenv for the \"tests\" pack before running integration tests" + fi + fi + # List screen sessions screen -ls || exit 0 }