diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 00e8ba2c40..31a5327b42 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -32,6 +32,7 @@ in development future, pack configs will be validated against the schema (if available). (new feature) * Add data model and API changes for supporting user scoped variables. (new-feature, experimental) * Add missing `pytz` dependency to ``st2client`` requirements file. (bug-fix) +* Fix datastore access on Python runner actions. (bug-fix) 1.4.0 - April 18, 2016 ---------------------- diff --git a/st2actions/st2actions/runners/pythonrunner.py b/st2actions/st2actions/runners/pythonrunner.py index 58f66bcded..0b6ef8a516 100644 --- a/st2actions/st2actions/runners/pythonrunner.py +++ b/st2actions/st2actions/runners/pythonrunner.py @@ -25,11 +25,14 @@ from st2actions.runners import ActionRunner from st2actions.runners.utils import get_logger_for_python_runner_action from st2common.util.green.shell import run_command +from st2common.constants.system import API_URL_ENV_VARIABLE_NAME +from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from st2common.constants.action import ACTION_OUTPUT_RESULT_DELIMITER from st2common.constants.action import LIVEACTION_STATUS_SUCCEEDED from st2common.constants.action import LIVEACTION_STATUS_FAILED from st2common.constants.action import LIVEACTION_STATUS_TIMED_OUT from st2common.constants.error_messages import PACK_VIRTUALENV_DOESNT_EXIST +from st2common.util.api import get_full_public_api_url from st2common.util.sandboxing import get_sandbox_path from st2common.util.sandboxing import get_sandbox_python_path from st2common.util.sandboxing import get_sandbox_python_binary_path @@ -130,6 +133,18 @@ def run(self, action_parameters): env['PYTHONPATH'] = get_sandbox_python_path(inherit_from_parent=True, inherit_parent_virtualenv=True) + # Include full api URL and API token specific to this action. This is required to + # action_service can access the datastore via the API. + # TODO: Better approach would be to pass token to the client constructor inside the wrapper + # process + + # Note: Temporary auth token is generated by the runner container service + auth_token_db = getattr(self, 'auth_token', None) + auth_token = getattr(auth_token_db, 'token', '') + + env[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url() + env[AUTH_TOKEN_ENV_VARIABLE_NAME] = auth_token + # Include user provided environment variables (if any) user_env_vars = self._get_env_vars() env.update(user_env_vars) diff --git a/st2actions/tests/unit/test_pythonrunner.py b/st2actions/tests/unit/test_pythonrunner.py index eb3e4ba31e..7f44cebca9 100644 --- a/st2actions/tests/unit/test_pythonrunner.py +++ b/st2actions/tests/unit/test_pythonrunner.py @@ -21,9 +21,12 @@ from st2actions.runners.pythonrunner import Action from st2actions.container import service from st2actions.runners.utils import get_action_class_instance +from st2common.constants.system import API_URL_ENV_VARIABLE_NAME +from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from st2common.constants.action import ACTION_OUTPUT_RESULT_DELIMITER from st2common.constants.action import LIVEACTION_STATUS_SUCCEEDED, LIVEACTION_STATUS_FAILED from st2common.constants.pack import SYSTEM_PACK_NAME +from st2common.util.api import get_full_public_api_url from base import RunnerTestCase import st2tests.base as tests_base import st2tests.config as tests_config @@ -186,6 +189,28 @@ def test_common_st2_env_vars_are_available_to_the_action(self, mock_popen): actual_env = call_kwargs['env'] self.assertCommonSt2EnvVarsAvailableInEnv(env=actual_env) + @mock.patch('st2common.util.green.shell.subprocess.Popen') + def test_auth_token_and_api_url_env_variable_is_available_to_the_action(self, mock_popen): + mock_process = mock.Mock() + mock_process.communicate.return_value = ('', '') + mock_popen.return_value = mock_process + + runner = pythonrunner.get_runner() + runner.auth_token = mock.Mock() + runner.auth_token.token = 'ponies' + runner.action = self._get_mock_action_obj() + runner.runner_parameters = {} + runner.entry_point = PACAL_ROW_ACTION_PATH + runner.container_service = service.RunnerContainerService() + runner.pre_run() + (_, _, _) = runner.run({'row_index': 4}) + + _, call_kwargs = mock_popen.call_args + actual_env = call_kwargs['env'] + + self.assertEqual(actual_env[API_URL_ENV_VARIABLE_NAME], get_full_public_api_url()) + self.assertEqual(actual_env[AUTH_TOKEN_ENV_VARIABLE_NAME], 'ponies') + def test_action_class_instantiation_action_service_argument(self): class Action1(Action): # Constructor not overriden so no issue here