From bb5b333726f29f6b9b6a99d83909816e71eee711 Mon Sep 17 00:00:00 2001 From: Lakshmi Kannan Date: Wed, 18 May 2016 17:36:02 -0700 Subject: [PATCH 1/5] Set same env variables as sensor --- st2actions/st2actions/runners/__init__.py | 6 ++++++ st2actions/tests/unit/base.py | 2 ++ st2actions/tests/unit/test_pythonrunner.py | 2 ++ st2reactor/st2reactor/sensor/base.py | 6 ++++-- st2reactor/tests/unit/test_sensor_wrapper.py | 12 ++++++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/st2actions/st2actions/runners/__init__.py b/st2actions/st2actions/runners/__init__.py index 4c21c975b0..b523fb5b28 100644 --- a/st2actions/st2actions/runners/__init__.py +++ b/st2actions/st2actions/runners/__init__.py @@ -21,6 +21,8 @@ from st2actions import handlers from st2common import log as logging from st2common.constants.pack import DEFAULT_PACK_NAME +from st2common.constants.system import API_URL_ENV_VARIABLE_NAME +from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from st2common.exceptions.actionrunner import ActionRunnerCreateError from st2common.util import action_db as action_utils from st2common.util.api import get_full_public_api_url @@ -136,9 +138,13 @@ def _get_common_action_env_variables(self): result['ST2_ACTION_PACK_NAME'] = self.get_pack_name() result['ST2_ACTION_EXECUTION_ID'] = str(self.execution_id) result['ST2_ACTION_API_URL'] = get_full_public_api_url() + # Compatibility with sensors + result[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url() if self.auth_token: result['ST2_ACTION_AUTH_TOKEN'] = self.auth_token.token + # Compatibility with sensors + result[AUTH_TOKEN_ENV_VARIABLE_NAME] = self.auth_token.token return result diff --git a/st2actions/tests/unit/base.py b/st2actions/tests/unit/base.py index 6fdafce59e..360519a840 100644 --- a/st2actions/tests/unit/base.py +++ b/st2actions/tests/unit/base.py @@ -24,6 +24,7 @@ from st2actions import scheduler from st2actions.notifier import notifier from st2common.constants import action as action_constants +from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from st2common.models.db.liveaction import LiveActionDB from st2common.util.api import get_full_public_api_url from st2common.constants.runners import COMMON_ACTION_ENV_VARIABLES @@ -44,6 +45,7 @@ def assertCommonSt2EnvVarsAvailableInEnv(self, env): self.assertTrue(var_name in env) self.assertEqual(env['ST2_ACTION_API_URL'], get_full_public_api_url()) + self.assertTrue(env[AUTH_TOKEN_ENV_VARIABLE_NAME] is not None) class MockLiveActionPublisher(object): diff --git a/st2actions/tests/unit/test_pythonrunner.py b/st2actions/tests/unit/test_pythonrunner.py index eb3e4ba31e..885792e26c 100644 --- a/st2actions/tests/unit/test_pythonrunner.py +++ b/st2actions/tests/unit/test_pythonrunner.py @@ -24,6 +24,8 @@ 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.constants.system import API_URL_ENV_VARIABLE_NAME +from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from base import RunnerTestCase import st2tests.base as tests_base import st2tests.config as tests_config diff --git a/st2reactor/st2reactor/sensor/base.py b/st2reactor/st2reactor/sensor/base.py index b81efd20dd..91ae0b6034 100644 --- a/st2reactor/st2reactor/sensor/base.py +++ b/st2reactor/st2reactor/sensor/base.py @@ -23,8 +23,10 @@ def __init__(self, sensor_service, config=None): :keyword config: Sensor config. :type config: ``dict`` or None """ - self._sensor_service = sensor_service - self._config = config or {} + self._sensor_service = sensor_service # Deprecate in the future + self.sensor_service = sensor_service + self._config = config or {} # Deprecate in the future + self.config = self._config @abc.abstractmethod def setup(self): diff --git a/st2reactor/tests/unit/test_sensor_wrapper.py b/st2reactor/tests/unit/test_sensor_wrapper.py index 6560e449e3..9f76af4f95 100644 --- a/st2reactor/tests/unit/test_sensor_wrapper.py +++ b/st2reactor/tests/unit/test_sensor_wrapper.py @@ -26,6 +26,18 @@ def setUpClass(cls): super(SensorWrapperTestCase, cls).setUpClass() tests_config.parse_args() + def test_sensor_instance_has_sensor_service(self): + file_path = os.path.join(RESOURCES_DIR, 'test_sensor.py') + trigger_types = ['trigger1', 'trigger2'] + parent_args = ['--config-file', TESTS_CONFIG_PATH] + + wrapper = SensorWrapper(pack='core', file_path=file_path, + class_name='TestSensor', + trigger_types=trigger_types, + parent_args=parent_args) + self.assertTrue(getattr(wrapper._sensor_instance, 'sensor_service', None) is not None) + self.assertTrue(getattr(wrapper._sensor_instance, 'config', None) is not None) + def test_trigger_cud_event_handlers(self): file_path = os.path.join(RESOURCES_DIR, 'test_sensor.py') trigger_types = ['trigger1', 'trigger2'] From 8137e37b046aaea11823fc5fd5be9a59f9d3bf79 Mon Sep 17 00:00:00 2001 From: Lakshmi Kannan Date: Wed, 18 May 2016 17:42:16 -0700 Subject: [PATCH 2/5] Update CHANGELOG --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 00e8ba2c40..d881f5550b 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) +* Set ``ST2_AUTH_TOKEN`` and ``ST2_API_URL`` env variables in actions to match sensors. (bug-fix) 1.4.0 - April 18, 2016 ---------------------- From 5b937d5551c1a8208bedff97f553b092bdeaf046 Mon Sep 17 00:00:00 2001 From: Lakshmi Kannan Date: Wed, 18 May 2016 17:48:27 -0700 Subject: [PATCH 3/5] Use sensor_service in examples --- contrib/default/sensors/README.md | 2 +- contrib/examples/sensors/sample_polling_sensor.py | 4 ++-- contrib/examples/sensors/sample_sensor.py | 4 ++-- contrib/hello-st2/sensors/sensor1.py | 8 ++++---- contrib/linux/sensors/file_watch_sensor.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/default/sensors/README.md b/contrib/default/sensors/README.md index 1f603dbac2..c7852a8858 100644 --- a/contrib/default/sensors/README.md +++ b/contrib/default/sensors/README.md @@ -1,4 +1,4 @@ # sensors -The sensors folder contains sensoros. See [Sensors](http://docs.stackstorm.com/sensors.html) for specifics on writing +The sensors folder contains sensors. See [Sensors](http://docs.stackstorm.com/sensors.html) for specifics on writing sensors and registering TriggerTypes. diff --git a/contrib/examples/sensors/sample_polling_sensor.py b/contrib/examples/sensors/sample_polling_sensor.py index 34d069f01a..155bfe1272 100644 --- a/contrib/examples/sensors/sample_polling_sensor.py +++ b/contrib/examples/sensors/sample_polling_sensor.py @@ -3,7 +3,7 @@ class SamplePollingSensor(PollingSensor): """ - * self._sensor_service + * self.sensor_service - provides utilities like get_logger() for writing to logs. dispatch() for dispatching triggers into the system. @@ -29,7 +29,7 @@ def poll(self): # # _to_triggers is something you'd write to convert the data format you have # # into a standard python dictionary. This should follow the payload schema # # registered for the trigger. - # self._sensor_service.dispatch(trigger, payload) + # self.sensor_service.dispatch(trigger, payload) # # You can refer to the trigger as dict # # { "name": ${trigger_name}, "pack": ${trigger_pack} } # # or just simply by reference as string. diff --git a/contrib/examples/sensors/sample_sensor.py b/contrib/examples/sensors/sample_sensor.py index 583026ff7e..dbbee88a4e 100644 --- a/contrib/examples/sensors/sample_sensor.py +++ b/contrib/examples/sensors/sample_sensor.py @@ -3,7 +3,7 @@ class SampleSensor(Sensor): """ - * self._sensor_service + * self.sensor_service - provides utilities like - get_logger() - returns logger instance specific to this sensor. - dispatch() for dispatching triggers into the system. @@ -24,7 +24,7 @@ def run(self): # interacting with your external system, you'd inherit from PollingSensor.) # For example, let's consider a simple flask app. You'd run the flask app here. # You can dispatch triggers using sensor_service like so: - # self._sensor_service(trigger, payload, trace_tag) + # self.sensor_service(trigger, payload, trace_tag) # # You can refer to the trigger as dict # # { "name": ${trigger_name}, "pack": ${trigger_pack} } # # or just simply by reference as string. diff --git a/contrib/hello-st2/sensors/sensor1.py b/contrib/hello-st2/sensors/sensor1.py index a061908f84..543c97df64 100644 --- a/contrib/hello-st2/sensors/sensor1.py +++ b/contrib/hello-st2/sensors/sensor1.py @@ -6,7 +6,7 @@ class HelloSensor(Sensor): def __init__(self, sensor_service, config): super(HelloSensor, self).__init__(sensor_service=sensor_service, config=config) - self._logger = self._sensor_service.get_logger(name=self.__class__.__name__) + self._logger = self.sensor_service.get_logger(name=self.__class__.__name__) self._stop = False def setup(self): @@ -15,10 +15,10 @@ def setup(self): def run(self): while not self._stop: self._logger.debug('HelloSensor dispatching trigger...') - count = self._sensor_service.get_value('hello-st2.count') or 0 + count = self.sensor_service.get_value('hello-st2.count') or 0 payload = {'greeting': 'Yo, StackStorm!', 'count': int(count) + 1} - self._sensor_service.dispatch(trigger='hello-st2.event1', payload=payload) - self._sensor_service.set_value('hello-st2.count', payload['count']) + self.sensor_service.dispatch(trigger='hello-st2.event1', payload=payload) + self.sensor_service.set_value('hello-st2.count', payload['count']) eventlet.sleep(60) def cleanup(self): diff --git a/contrib/linux/sensors/file_watch_sensor.py b/contrib/linux/sensors/file_watch_sensor.py index 9c4e32fb36..d350c87c0f 100644 --- a/contrib/linux/sensors/file_watch_sensor.py +++ b/contrib/linux/sensors/file_watch_sensor.py @@ -51,4 +51,4 @@ def _handle_line(self, file_path, line): 'file_name': os.path.basename(file_path), 'line': line } - self._sensor_service.dispatch(trigger=trigger, payload=payload) + self.sensor_service.dispatch(trigger=trigger, payload=payload) From 2fd8f3086e19a515aa9f0f11cdef45b75c51cb8c Mon Sep 17 00:00:00 2001 From: Lakshmi Kannan Date: Wed, 18 May 2016 18:03:53 -0700 Subject: [PATCH 4/5] Lint fixes --- st2actions/tests/unit/test_pythonrunner.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/st2actions/tests/unit/test_pythonrunner.py b/st2actions/tests/unit/test_pythonrunner.py index 885792e26c..eb3e4ba31e 100644 --- a/st2actions/tests/unit/test_pythonrunner.py +++ b/st2actions/tests/unit/test_pythonrunner.py @@ -24,8 +24,6 @@ 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.constants.system import API_URL_ENV_VARIABLE_NAME -from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from base import RunnerTestCase import st2tests.base as tests_base import st2tests.config as tests_config From a1cb9c472bd84707f7a6f229251c52af0de1eb84 Mon Sep 17 00:00:00 2001 From: Lakshmi Kannan Date: Thu, 19 May 2016 15:13:43 -0700 Subject: [PATCH 5/5] Datastore access env variables in own method --- st2actions/st2actions/runners/__init__.py | 6 ----- st2actions/st2actions/runners/pythonrunner.py | 22 ++++++++++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/st2actions/st2actions/runners/__init__.py b/st2actions/st2actions/runners/__init__.py index b523fb5b28..4c21c975b0 100644 --- a/st2actions/st2actions/runners/__init__.py +++ b/st2actions/st2actions/runners/__init__.py @@ -21,8 +21,6 @@ from st2actions import handlers from st2common import log as logging from st2common.constants.pack import DEFAULT_PACK_NAME -from st2common.constants.system import API_URL_ENV_VARIABLE_NAME -from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME from st2common.exceptions.actionrunner import ActionRunnerCreateError from st2common.util import action_db as action_utils from st2common.util.api import get_full_public_api_url @@ -138,13 +136,9 @@ def _get_common_action_env_variables(self): result['ST2_ACTION_PACK_NAME'] = self.get_pack_name() result['ST2_ACTION_EXECUTION_ID'] = str(self.execution_id) result['ST2_ACTION_API_URL'] = get_full_public_api_url() - # Compatibility with sensors - result[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url() if self.auth_token: result['ST2_ACTION_AUTH_TOKEN'] = self.auth_token.token - # Compatibility with sensors - result[AUTH_TOKEN_ENV_VARIABLE_NAME] = self.auth_token.token return result diff --git a/st2actions/st2actions/runners/pythonrunner.py b/st2actions/st2actions/runners/pythonrunner.py index 58f66bcded..e34abaec40 100644 --- a/st2actions/st2actions/runners/pythonrunner.py +++ b/st2actions/st2actions/runners/pythonrunner.py @@ -30,11 +30,15 @@ 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.constants.runners import PYTHON_RUNNER_DEFAULT_ACTION_TIMEOUT +from st2common.constants.system import API_URL_ENV_VARIABLE_NAME +from st2common.constants.system import AUTH_TOKEN_ENV_VARIABLE_NAME +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 from st2common.util.sandboxing import get_sandbox_virtualenv_path -from st2common.constants.runners import PYTHON_RUNNER_DEFAULT_ACTION_TIMEOUT + __all__ = [ 'get_runner', @@ -137,6 +141,8 @@ def run(self, action_parameters): # Include common st2 environment variables st2_env_vars = self._get_common_action_env_variables() env.update(st2_env_vars) + datastore_env_vars = self._get_datastore_access_env_vars() + env.update(datastore_env_vars) exit_code, stdout, stderr, timed_out = run_command(cmd=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, @@ -203,3 +209,17 @@ def _get_env_vars(self): del env_vars[key] return env_vars + + def _get_datastore_access_env_vars(self): + """ + Return environment variables so datastore access using client (from st2client) + is possible with actions. This is done to be compatible with sensors. + + :rtype: ``dict`` + """ + env_vars = {} + if self.auth_token: + env_vars[AUTH_TOKEN_ENV_VARIABLE_NAME] = self.auth_token.token + env_vars[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url() + + return env_vars