Example #1
0
    def _construct_st2_context(self):
        st2_ctx = {
            "st2": {
                "action_execution_id":
                str(self.execution.id),
                "api_url":
                api_util.get_full_public_api_url(),
                "user":
                self.execution.context.get("user", cfg.CONF.system_user.user),
                "pack":
                self.execution.context.get("pack", None),
                "action":
                self.execution.action.get("ref", None),
                "runner":
                self.execution.action.get("runner_type", None),
            }
        }

        if self.execution.context.get("api_user"):
            st2_ctx["st2"]["api_user"] = self.execution.context.get("api_user")

        if self.execution.context.get("source_channel"):
            st2_ctx["st2"]["source_channel"] = self.execution.context.get(
                "source_channel")

        if self.execution.context:
            st2_ctx["parent"] = self.execution.context

        return st2_ctx
Example #2
0
    def _construct_st2_context(self):
        st2_ctx = {
            'st2': {
                'action_execution_id':
                str(self.execution.id),
                'api_url':
                api_util.get_full_public_api_url(),
                'user':
                self.execution.context.get('user', cfg.CONF.system_user.user),
                'pack':
                self.execution.context.get('pack', None),
                'action':
                self.execution.action.get('ref', None),
                'runner':
                self.execution.action.get('runner_type', None)
            }
        }

        if self.execution.context.get('api_user'):
            st2_ctx['st2']['api_user'] = self.execution.context.get('api_user')

        if self.execution.context.get('source_channel'):
            st2_ctx['st2']['source_channel'] = self.execution.context.get(
                'source_channel')

        if self.execution.context:
            st2_ctx['parent'] = self.execution.context

        return st2_ctx
    def _construct_workflow_execution_options(self):
        # This URL is used by Mistral to talk back to the API
        api_url = get_mistral_api_url()
        endpoint = api_url + '/actionexecutions'

        # This URL is available in the context and can be used by the users inside a workflow,
        # similar to "ST2_ACTION_API_URL" environment variable available to actions
        public_api_url = get_full_public_api_url()

        # Build context with additional information
        parent_context = {'execution_id': self.execution_id}

        if getattr(self.liveaction, 'context', None):
            parent_context.update(self.liveaction.context)

        # Convert jinja expressions in the params of Action Chain under the parent context
        # into raw block. If there is any jinja expressions, Mistral will try to evaulate
        # the expression. If there is a local context reference, the evaluation will fail
        # because the local context reference is out of scope.
        chain_ctx = parent_context.get('chain') or {}

        for attr in ['params', 'parameters']:
            chain_params_ctx = chain_ctx.get(attr) or {}

            for k, v in six.iteritems(chain_params_ctx):
                parent_context['chain'][attr][
                    k] = jinja.convert_jinja_to_raw_block(v)

        st2_execution_context = {
            'api_url': api_url,
            'endpoint': endpoint,
            'parent': parent_context,
            'notify': {},
            'skip_notify_tasks': self._skip_notify_tasks
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(
                notify_model=self._notify)
            st2_execution_context['notify'] = notify_dict

        if self.auth_token:
            st2_execution_context['auth_token'] = self.auth_token.token

        options = {
            'env': {
                'st2_execution_id': self.execution_id,
                'st2_liveaction_id': self.liveaction_id,
                'st2_action_api_url': public_api_url,
                '__actions': {
                    'st2.action': {
                        'st2_context': st2_execution_context
                    }
                }
            }
        }

        return options
Example #4
0
    def assertCommonSt2EnvVarsAvailableInEnv(self, env):
        """
        Method which asserts that the common ST2 environment variables are present in the provided
        environment.
        """
        for var_name in COMMON_ACTION_ENV_VARIABLES:
            self.assertTrue(var_name in env)

        self.assertEqual(env['ST2_ACTION_API_URL'], get_full_public_api_url())
Example #5
0
File: base.py Project: zsjohny/st2
 def assertCommonSt2EnvVarsAvailableInEnv(self, env):
     """
     Method which asserts that the common ST2 environment variables are present in the provided
     environment.
     """
     for var_name in COMMON_ACTION_ENV_VARIABLES:
         self.assertIn(var_name, env)
     self.assertEqual(env['ST2_ACTION_API_URL'], get_full_public_api_url())
     self.assertIsNotNone(env[AUTH_TOKEN_ENV_VARIABLE_NAME])
Example #6
0
    def mock_st2_ctx(self):
        st2_ctx = {
            'st2': {
                'api_url': api_utils.get_full_public_api_url(),
                'action_execution_id': uuid.uuid4().hex,
                'user': cfg.CONF.system_user.user
            }
        }

        return st2_ctx
Example #7
0
    def mock_st2_ctx(self):
        st2_ctx = {
            "st2": {
                "api_url": api_utils.get_full_public_api_url(),
                "action_execution_id": uuid.uuid4().hex,
                "user": cfg.CONF.system_user.user,
            }
        }

        return st2_ctx
Example #8
0
    def _get_api_client(self):
        """
        Retrieve API client instance.
        """
        if not self._client:
            ttl = (24 * 60 * 60)
            temporary_token = create_token(username=self._api_username, ttl=ttl)
            api_url = get_full_public_api_url()
            self._client = Client(api_url=api_url, token=temporary_token.token)

        return self._client
Example #9
0
    def _construct_st2_context(self):
        st2_ctx = {
            'st2': {
                'api_url': api_util.get_full_public_api_url(),
                'action_execution_id': str(self.execution.id)
            }
        }

        if self.execution.context:
            st2_ctx['parent'] = self.execution.context

        return st2_ctx
Example #10
0
    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)
            }
        }

        if context:
            st2_ctx['parent'] = context

        return st2_ctx
Example #11
0
    def _get_api_client(self):
        """
        Retrieve API client instance.
        """
        if not self._client:
            self._logger.audit('Creating new Client object.')

            api_url = get_full_public_api_url()
            client = Client(api_url=api_url, token=self._auth_token)
            self._client = client

        return self._client
Example #12
0
    def get_api_client(self):
        """
        Retrieve API client instance.
        """
        if not self._client:
            self._logger.debug('Creating new Client object.')

            api_url = get_full_public_api_url()
            client = Client(api_url=api_url, token=self._auth_token)
            self._client = client

        return self._client
Example #13
0
File: base.py Project: nzlosh/st2
    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),
                'user': '******'
            }
        }

        if context:
            st2_ctx['parent'] = context

        return st2_ctx
Example #14
0
    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
Example #15
0
    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
Example #16
0
    def _construct_st2_context(self):
        st2_ctx = {
            'st2': {
                'api_url': api_util.get_full_public_api_url(),
                'action_execution_id': str(self.execution.id),
                'user': self.execution.context.get('user', cfg.CONF.system_user.user)
            }
        }

        if self.execution.context:
            st2_ctx['parent'] = self.execution.context

        return st2_ctx
Example #17
0
File: base.py Project: chadpatt/st2
    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),
                "user": "******",
                "action": ac_ex_db.action["ref"],
                "runner": ac_ex_db.runner["name"],
            }
        }

        if context:
            st2_ctx["parent"] = context

        return st2_ctx
Example #18
0
    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),
                'user': '******',
                'action': ac_ex_db.action['ref'],
                'runner': ac_ex_db.runner['name']
            }
        }

        if context:
            st2_ctx['parent'] = context

        return st2_ctx
Example #19
0
    def _get_api_client(self):
        """
        Retrieve API client instance.
        """
        token_expire = self._token_expire <= get_datetime_utc_now()

        if not self._client or token_expire:
            self._logger.audit('Creating new Client object.')
            ttl = cfg.CONF.auth.service_token_ttl
            self._token_expire = get_datetime_utc_now() + timedelta(seconds=ttl)
            temporary_token = create_token(username=self._api_username, ttl=ttl, service=True)
            api_url = get_full_public_api_url()
            self._client = Client(api_url=api_url, token=temporary_token.token)

        return self._client
Example #20
0
    def _get_api_client(self):
        """
        Retrieve API client instance.
        """
        token_expire = self._token_expire <= get_datetime_utc_now()

        if not self._client or token_expire:
            self._logger.audit('Creating new Client object.')
            ttl = (24 * 60 * 60)
            self._token_expire = get_datetime_utc_now() + timedelta(seconds=ttl)
            temporary_token = create_token(username=self._api_username, ttl=ttl)
            api_url = get_full_public_api_url()
            self._client = Client(api_url=api_url, token=temporary_token.token)

        return self._client
Example #21
0
    def _construct_st2_context(self):
        st2_ctx = {
            'st2': {
                'action_execution_id': str(self.execution.id),
                'api_url': api_util.get_full_public_api_url(),
                'user': self.execution.context.get('user', cfg.CONF.system_user.user),
                'pack': self.execution.context.get('pack', None)
            }
        }

        if self.execution.context.get('api_user'):
            st2_ctx['st2']['api_user'] = self.execution.context.get('api_user')

        if self.execution.context:
            st2_ctx['parent'] = self.execution.context

        return st2_ctx
Example #22
0
    def _construct_workflow_execution_options(self):
        # This URL is used by Mistral to talk back to the API
        api_url = get_mistral_api_url()
        endpoint = api_url + '/actionexecutions'

        # This URL is available in the context and can be used by the users inside a workflow,
        # similar to "ST2_ACTION_API_URL" environment variable available to actions
        public_api_url = get_full_public_api_url()

        # Build context with additional information
        parent_context = {
            'execution_id': self.execution_id
        }
        if getattr(self.liveaction, 'context', None):
            parent_context.update(self.liveaction.context)

        st2_execution_context = {
            'api_url': api_url,
            'endpoint': endpoint,
            'parent': parent_context,
            'notify': {},
            'skip_notify_tasks': self._skip_notify_tasks
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(notify_model=self._notify)
            st2_execution_context['notify'] = notify_dict

        if self.auth_token:
            st2_execution_context['auth_token'] = self.auth_token.token

        options = {
            'env': {
                'st2_execution_id': self.execution_id,
                'st2_liveaction_id': self.liveaction_id,
                'st2_action_api_url': public_api_url,
                '__actions': {
                    'st2.action': {
                        'st2_context': st2_execution_context
                    }
                }
            }
        }

        return options
Example #23
0
    def _construct_workflow_execution_options(self):
        # This URL is used by Mistral to talk back to the API
        api_url = get_mistral_api_url()
        endpoint = api_url + '/actionexecutions'

        # This URL is available in the context and can be used by the users inside a workflow,
        # similar to "ST2_ACTION_API_URL" environment variable available to actions
        public_api_url = get_full_public_api_url()

        # Build context with additional information
        parent_context = {'execution_id': self.execution_id}
        if getattr(self.liveaction, 'context', None):
            parent_context.update(self.liveaction.context)

        st2_execution_context = {
            'api_url': api_url,
            'endpoint': endpoint,
            'parent': parent_context,
            'notify': {},
            'skip_notify_tasks': self._skip_notify_tasks
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(
                notify_model=self._notify)
            st2_execution_context['notify'] = notify_dict

        if self.auth_token:
            st2_execution_context['auth_token'] = self.auth_token.token

        options = {
            'env': {
                'st2_execution_id': self.execution_id,
                'st2_liveaction_id': self.liveaction_id,
                'st2_action_api_url': public_api_url,
                '__actions': {
                    'st2.action': {
                        'st2_context': st2_execution_context
                    }
                }
            }
        }

        return options
Example #24
0
    def _get_common_action_env_variables(self):
        """
        Retrieve common ST2_ACTION_ environment variables which will be available to the action.

        Note: Environment variables are prefixed with ST2_ACTION_* so they don't clash with CLI
        environment variables.

        :rtype: ``dict``
        """
        result = {}
        result['ST2_ACTION_PACK_NAME'] = self.get_pack_name()
        result['ST2_ACTION_EXECUTION_ID'] = str(self.liveaction_id)
        result['ST2_ACTION_API_URL'] = get_full_public_api_url()

        if self.auth_token:
            result['ST2_ACTION_AUTH_TOKEN'] = self.auth_token.token

        return result
Example #25
0
    def _get_common_action_env_variables(self):
        """
        Retrieve common ST2_ACTION_ environment variables which will be available to the action.

        Note: Environment variables are prefixed with ST2_ACTION_* so they don't clash with CLI
        environment variables.

        :rtype: ``dict``
        """
        result = {}
        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()

        if self.auth_token:
            result['ST2_ACTION_AUTH_TOKEN'] = self.auth_token.token

        return result
Example #26
0
    def test_common_st2_env_vars_are_available_to_the_action(self):
        models = self.fixtures_loader.load_models(fixtures_pack="generic", fixtures_dict={"actions": ["local.yaml"]})
        action_db = models["actions"]["local.yaml"]

        runner = self._get_runner(action_db, cmd="echo $ST2_ACTION_API_URL")
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result["stdout"].strip(), get_full_public_api_url())

        runner = self._get_runner(action_db, cmd="echo $ST2_ACTION_AUTH_TOKEN")
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result["stdout"].strip(), "mock-token")
Example #27
0
    def get_api_client(self):
        """
        Retrieve API client instance.
        """
        token_expire = self._token_expire <= get_datetime_utc_now()

        if not self._client or token_expire:
            # Note: Late import to avoid high import cost (time wise)
            from st2common.services.access import create_token
            self._logger.debug('Creating new Client object.')

            ttl = cfg.CONF.auth.service_token_ttl
            api_url = get_full_public_api_url()

            temporary_token = create_token(username=self._api_username, ttl=ttl, service=True)
            self._client = Client(api_url=api_url, token=temporary_token.token)
            self._token_expire = get_datetime_utc_now() + timedelta(seconds=ttl)

        return self._client
Example #28
0
    def get_api_client(self):
        """
        Retrieve API client instance.
        """
        token_expire = self._token_expire <= get_datetime_utc_now()

        if not self._client or token_expire:
            # Note: Late import to avoid high import cost (time wise)
            from st2common.services.access import create_token
            self._logger.debug('Creating new Client object.')

            ttl = cfg.CONF.auth.service_token_ttl
            api_url = get_full_public_api_url()

            temporary_token = create_token(username=self._api_username, ttl=ttl, service=True)
            self._client = Client(api_url=api_url, token=temporary_token.token)
            self._token_expire = get_datetime_utc_now() + timedelta(seconds=ttl)

        return self._client
Example #29
0
    def test_get_full_public_api_url(self):
        values = [
            'http://foo.bar.com',
            'http://foo.bar.com/',
            'http://foo.bar.com:8080',
            'http://foo.bar.com:8080/',
            'http://localhost:8080/',
        ]
        expected = [
            'http://foo.bar.com/' + DEFAULT_API_VERSION,
            'http://foo.bar.com/' + DEFAULT_API_VERSION,
            'http://foo.bar.com:8080/' + DEFAULT_API_VERSION,
            'http://foo.bar.com:8080/' + DEFAULT_API_VERSION,
            'http://localhost:8080/' + DEFAULT_API_VERSION,
        ]

        for mock_value, expected_result in zip(values, expected):
            cfg.CONF.auth.api_url = mock_value
            actual = get_full_public_api_url()
            self.assertEqual(actual, expected_result)
Example #30
0
    def test_common_st2_env_vars_are_available_to_the_action(self):
        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local.yaml']})
        action_db = models['actions']['local.yaml']

        runner = self._get_runner(action_db, cmd='echo $ST2_ACTION_API_URL')
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result['stdout'].strip(), get_full_public_api_url())

        runner = self._get_runner(action_db, cmd='echo $ST2_ACTION_AUTH_TOKEN')
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result['stdout'].strip(), 'mock-token')
    def test_common_st2_env_vars_are_available_to_the_action(self):
        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local.yaml']})
        action_db = models['actions']['local.yaml']

        runner = self._get_runner(action_db, cmd='echo $ST2_ACTION_API_URL')
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result['stdout'].strip(), get_full_public_api_url())

        runner = self._get_runner(action_db, cmd='echo $ST2_ACTION_AUTH_TOKEN')
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result['stdout'].strip(), 'mock-token')
Example #32
0
    def test_common_st2_env_vars_are_available_to_the_action(self):
        models = self.fixtures_loader.load_models(
            fixtures_pack="generic", fixtures_dict={"actions": ["local.yaml"]})
        action_db = models["actions"]["local.yaml"]

        runner = self._get_runner(action_db, cmd="echo $ST2_ACTION_API_URL")
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result["stdout"].strip(), get_full_public_api_url())

        runner = self._get_runner(action_db, cmd="echo $ST2_ACTION_AUTH_TOKEN")
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertEqual(result["stdout"].strip(), "mock-token")
Example #33
0
File: v2.py Project: enykeev/st2
    def _construct_workflow_execution_options(self):
        # This URL is used by Mistral to talk back to the API
        api_url = get_mistral_api_url()
        endpoint = api_url + "/actionexecutions"

        # This URL is available in the context and can be used by the users inside a workflow,
        # similar to "ST2_ACTION_API_URL" environment variable available to actions
        public_api_url = get_full_public_api_url()

        # Build context with additional information
        parent_context = {"execution_id": self.execution_id}
        if getattr(self.liveaction, "context", None):
            parent_context.update(self.liveaction.context)

        st2_execution_context = {
            "endpoint": endpoint,
            "parent": parent_context,
            "notify": {},
            "skip_notify_tasks": self._skip_notify_tasks,
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(notify_model=self._notify)
            st2_execution_context["notify"] = notify_dict

        if self.auth_token:
            st2_execution_context["auth_token"] = self.auth_token.token

        options = {
            "env": {
                "st2_execution_id": self.execution_id,
                "st2_liveaction_id": self.liveaction_id,
                "st2_action_api_url": public_api_url,
                "__actions": {"st2.action": {"st2_context": st2_execution_context}},
            }
        }

        return options
Example #34
0
    def _construct_workflow_execution_options(self):
        # This URL is used by Mistral to talk back to the API
        api_url = get_mistral_api_url()
        endpoint = api_url + '/actionexecutions'

        # This URL is available in the context and can be used by the users inside a workflow,
        # similar to "ST2_ACTION_API_URL" environment variable available to actions
        public_api_url = get_full_public_api_url()

        # Build context with additional information
        parent_context = {
            'execution_id': self.execution_id
        }

        if getattr(self.liveaction, 'context', None):
            parent_context.update(self.liveaction.context)

        # Convert jinja expressions in the params of Action Chain under the parent context
        # into raw block. If there is any jinja expressions, Mistral will try to evaulate
        # the expression. If there is a local context reference, the evaluation will fail
        # because the local context reference is out of scope.
        chain_ctx = parent_context.get('chain') or {}

        for attr in ['params', 'parameters']:
            chain_params_ctx = chain_ctx.get(attr) or {}

            for k, v in six.iteritems(chain_params_ctx):
                parent_context['chain'][attr][k] = jinja.convert_jinja_to_raw_block(v)

        st2_execution_context = {
            'api_url': api_url,
            'endpoint': endpoint,
            'parent': parent_context,
            'notify': {},
            'skip_notify_tasks': self._skip_notify_tasks
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(notify_model=self._notify)
            st2_execution_context['notify'] = notify_dict

        if self.auth_token:
            st2_execution_context['auth_token'] = self.auth_token.token

        options = {
            'env': {
                'st2_execution_id': self.execution_id,
                'st2_liveaction_id': self.liveaction_id,
                'st2_action_api_url': public_api_url,
                '__actions': {
                    'st2.action': {
                        'st2_context': st2_execution_context
                    }
                }
            }
        }

        if not self.is_polling_enabled():
            options['notify'] = [{'type': 'st2'}]

        # Only used on reverse type workflows
        task_name = self.runner_parameters.get('task_name', None)
        if task_name is not None:
            options['task_name'] = task_name

        return options
Example #35
0
    def _spawn_sensor_process(self, sensor):
        """
        Spawn a new process for the provided sensor.

        New process uses isolated Python binary from a virtual environment
        belonging to the sensor pack.
        """
        sensor_id = self._get_sensor_id(sensor=sensor)
        pack_ref = sensor['pack']

        virtualenv_path = get_sandbox_virtualenv_path(pack=pack_ref)
        python_path = get_sandbox_python_binary_path(pack=pack_ref)

        if virtualenv_path and not os.path.isdir(virtualenv_path):
            format_values = {'pack': sensor['pack'], 'virtualenv_path': virtualenv_path}
            msg = PACK_VIRTUALENV_DOESNT_EXIST % format_values
            raise Exception(msg)

        trigger_type_refs = sensor['trigger_types'] or []
        trigger_type_refs = ','.join(trigger_type_refs)

        parent_args = json.dumps(sys.argv[1:])

        args = [
            python_path,
            WRAPPER_SCRIPT_PATH,
            '--pack=%s' % (sensor['pack']),
            '--file-path=%s' % (sensor['file_path']),
            '--class-name=%s' % (sensor['class_name']),
            '--trigger-type-refs=%s' % (trigger_type_refs),
            '--parent-args=%s' % (parent_args)
        ]

        if sensor['poll_interval']:
            args.append('--poll-interval=%s' % (sensor['poll_interval']))

        sandbox_python_path = get_sandbox_python_path(inherit_from_parent=True,
                                                      inherit_parent_virtualenv=True)

        if self._enable_common_pack_libs:
            pack_common_libs_path = get_pack_common_libs_path_for_pack_ref(pack_ref=pack_ref)
        else:
            pack_common_libs_path = None

        env = os.environ.copy()

        if self._enable_common_pack_libs and pack_common_libs_path:
            env['PYTHONPATH'] = pack_common_libs_path + ':' + sandbox_python_path
        else:
            env['PYTHONPATH'] = sandbox_python_path

        # Include full api URL and API token specific to that sensor
        ttl = cfg.CONF.auth.service_token_ttl
        metadata = {
            'service': 'sensors_container',
            'sensor_path': sensor['file_path'],
            'sensor_class': sensor['class_name']
        }
        temporary_token = create_token(username='******', ttl=ttl, metadata=metadata,
                                       service=True)

        env[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url()
        env[AUTH_TOKEN_ENV_VARIABLE_NAME] = temporary_token.token

        # TODO 1: Purge temporary token when service stops or sensor process dies
        # TODO 2: Store metadata (wrapper process id) with the token and delete
        # tokens for old, dead processes on startup
        cmd = ' '.join(args)
        LOG.debug('Running sensor subprocess (cmd="%s")', cmd)

        # TODO: Intercept stdout and stderr for aggregated logging purposes
        try:
            process = subprocess.Popen(args=args, stdin=None, stdout=None,
                                       stderr=None, shell=False, env=env,
                                       preexec_fn=on_parent_exit('SIGTERM'))
        except Exception as e:
            cmd = ' '.join(args)
            message = ('Failed to spawn process for sensor %s ("%s"): %s' %
                       (sensor_id, cmd, str(e)))
            raise Exception(message)

        self._processes[sensor_id] = process
        self._sensors[sensor_id] = sensor
        self._sensor_start_times[sensor_id] = int(time.time())

        self._dispatch_trigger_for_sensor_spawn(sensor=sensor, process=process, cmd=cmd)

        return process
Example #36
0
    def _spawn_sensor_process(self, sensor):
        """
        Spawn a new process for the provided sensor.

        New process uses isolated Python binary from a virtual environment
        belonging to the sensor pack.
        """
        sensor_id = self._get_sensor_id(sensor=sensor)
        pack_ref = sensor["pack"]

        virtualenv_path = get_sandbox_virtualenv_path(pack=pack_ref)
        python_path = get_sandbox_python_binary_path(pack=pack_ref)

        if virtualenv_path and not os.path.isdir(virtualenv_path):
            format_values = {
                "pack": sensor["pack"],
                "virtualenv_path": virtualenv_path
            }
            msg = PACK_VIRTUALENV_DOESNT_EXIST % format_values
            raise Exception(msg)

        args = self._get_args_for_wrapper_script(python_binary=python_path,
                                                 sensor=sensor)

        if self._enable_common_pack_libs:
            pack_common_libs_path = get_pack_common_libs_path_for_pack_ref(
                pack_ref=pack_ref)
        else:
            pack_common_libs_path = None

        env = os.environ.copy()

        sandbox_python_path = get_sandbox_python_path(
            inherit_from_parent=True, inherit_parent_virtualenv=True)

        if self._enable_common_pack_libs and pack_common_libs_path:
            env["PYTHONPATH"] = pack_common_libs_path + ":" + sandbox_python_path
        else:
            env["PYTHONPATH"] = sandbox_python_path

        if self._create_token:
            # Include full api URL and API token specific to that sensor
            LOG.debug("Creating temporary auth token for sensor %s" %
                      (sensor["class_name"]))

            ttl = cfg.CONF.auth.service_token_ttl
            metadata = {
                "service": "sensors_container",
                "sensor_path": sensor["file_path"],
                "sensor_class": sensor["class_name"],
            }
            temporary_token = create_token(username="******",
                                           ttl=ttl,
                                           metadata=metadata,
                                           service=True)

            env[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url()
            env[AUTH_TOKEN_ENV_VARIABLE_NAME] = temporary_token.token

            # TODO 1: Purge temporary token when service stops or sensor process dies
            # TODO 2: Store metadata (wrapper process id) with the token and delete
            # tokens for old, dead processes on startup

        cmd = " ".join(args)
        LOG.debug('Running sensor subprocess (cmd="%s")', cmd)

        # TODO: Intercept stdout and stderr for aggregated logging purposes
        try:
            process = subprocess.Popen(
                args=args,
                stdin=None,
                stdout=None,
                stderr=None,
                shell=False,
                env=env,
                preexec_fn=on_parent_exit("SIGTERM"),
            )
        except Exception as e:
            cmd = " ".join(args)
            message = 'Failed to spawn process for sensor %s ("%s"): %s' % (
                sensor_id,
                cmd,
                six.text_type(e),
            )
            raise Exception(message)

        self._processes[sensor_id] = process
        self._sensors[sensor_id] = sensor
        self._sensor_start_times[sensor_id] = int(time.time())

        self._dispatch_trigger_for_sensor_spawn(sensor=sensor,
                                                process=process,
                                                cmd=cmd)

        return process
Example #37
0
    def run(self, action_parameters):
        # Test connection
        self._client.workflows.list()

        # Setup inputs for the workflow execution.
        inputs = self.runner_parameters.get('context', dict())
        inputs.update(action_parameters)

        # This URL is used by Mistral to talk back to the API
        api_url = get_mistral_api_url()
        endpoint = api_url + '/actionexecutions'

        # This URL is available in the context and can be used by the users inside a workflow,
        # similar to "ST2_ACTION_API_URL" environment variable available to actions
        public_api_url = get_full_public_api_url()

        # Build context with additional information
        parent_context = {
            'execution_id': self.execution_id
        }
        if getattr(self.liveaction, 'context', None):
            parent_context.update(self.liveaction.context)

        st2_execution_context = {
            'endpoint': endpoint,
            'parent': parent_context,
            'notify': {},
            'skip_notify_tasks': self._skip_notify_tasks
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(notify_model=self._notify)
            st2_execution_context['notify'] = notify_dict

        if self.auth_token:
            st2_execution_context['auth_token'] = self.auth_token.token

        options = {
            'env': {
                'st2_execution_id': self.execution_id,
                'st2_liveaction_id': self.liveaction_id,
                'st2_action_api_url': public_api_url,
                '__actions': {
                    'st2.action': {
                        'st2_context': st2_execution_context
                    }
                }
            }
        }

        # Get workbook/workflow definition from file.
        with open(self.entry_point, 'r') as def_file:
            def_yaml = def_file.read()

        def_dict = yaml.safe_load(def_yaml)
        is_workbook = ('workflows' in def_dict)

        if not is_workbook:
            # Non-workbook definition containing multiple workflows is not supported.
            if len([k for k, _ in six.iteritems(def_dict) if k != 'version']) != 1:
                raise Exception('Workflow (not workbook) definition is detected. '
                                'Multiple workflows is not supported.')

        action_ref = '%s.%s' % (self.action.pack, self.action.name)
        self._check_name(action_ref, is_workbook, def_dict)
        def_dict_xformed = utils.transform_definition(def_dict)
        def_yaml_xformed = yaml.safe_dump(def_dict_xformed, default_flow_style=False)

        # Save workbook/workflow definition.
        if is_workbook:
            self._save_workbook(action_ref, def_yaml_xformed)
            default_workflow = self._find_default_workflow(def_dict_xformed)
            execution = self._client.executions.create(default_workflow,
                                                       workflow_input=inputs,
                                                       **options)
        else:
            self._save_workflow(action_ref, def_yaml_xformed)
            execution = self._client.executions.create(action_ref,
                                                       workflow_input=inputs,
                                                       **options)

        status = LIVEACTION_STATUS_RUNNING
        partial_results = {'tasks': []}

        # pylint: disable=no-member
        current_context = {
            'execution_id': str(execution.id),
            'workflow_name': execution.workflow_name
        }

        exec_context = self.context
        exec_context = self._build_mistral_context(exec_context, current_context)
        LOG.info('Mistral query context is %s' % exec_context)

        return (status, partial_results, exec_context)
Example #38
0
File: v2.py Project: mikeatm/st2
    def try_run(self, action_parameters):
        # Test connection
        self._client.workflows.list()

        # Setup inputs for the workflow execution.
        inputs = self.runner_parameters.get('context', dict())
        inputs.update(action_parameters)

        api_url = get_full_public_api_url()
        endpoint = api_url + '/actionexecutions'

        # Build context with additional information
        parent_context = {'execution_id': self.execution_id}
        if getattr(self.liveaction, 'context', None):
            parent_context.update(self.liveaction.context)

        st2_execution_context = {
            'endpoint': endpoint,
            'parent': parent_context,
            'notify': {},
            'skip_notify_tasks': self._skip_notify_tasks
        }

        # Include notification information
        if self._notify:
            notify_dict = NotificationsHelper.from_model(
                notify_model=self._notify)
            st2_execution_context['notify'] = notify_dict

        if self.auth_token:
            st2_execution_context['auth_token'] = self.auth_token.token

        options = {
            'env': {
                'st2_execution_id': self.execution_id,
                'st2_liveaction_id': self.liveaction_id,
                '__actions': {
                    'st2.action': {
                        'st2_context': st2_execution_context
                    }
                }
            }
        }

        # Get workbook/workflow definition from file.
        with open(self.entry_point, 'r') as def_file:
            def_yaml = def_file.read()

        def_dict = yaml.safe_load(def_yaml)
        is_workbook = ('workflows' in def_dict)

        if not is_workbook:
            # Non-workbook definition containing multiple workflows is not supported.
            if len([k for k, _ in six.iteritems(def_dict) if k != 'version'
                    ]) != 1:
                raise Exception(
                    'Workflow (not workbook) definition is detected. '
                    'Multiple workflows is not supported.')

        action_ref = '%s.%s' % (self.action.pack, self.action.name)
        self._check_name(action_ref, is_workbook, def_dict)
        def_dict_xformed = utils.transform_definition(def_dict)
        def_yaml_xformed = yaml.safe_dump(def_dict_xformed,
                                          default_flow_style=False)

        # Save workbook/workflow definition.
        if is_workbook:
            self._save_workbook(action_ref, def_yaml_xformed)
            default_workflow = self._find_default_workflow(def_dict_xformed)
            execution = self._client.executions.create(default_workflow,
                                                       workflow_input=inputs,
                                                       **options)
        else:
            self._save_workflow(action_ref, def_yaml_xformed)
            execution = self._client.executions.create(action_ref,
                                                       workflow_input=inputs,
                                                       **options)

        status = LIVEACTION_STATUS_RUNNING
        partial_results = {'tasks': []}

        # pylint: disable=no-member
        current_context = {
            'execution_id': str(execution.id),
            'workflow_name': execution.workflow_name
        }

        exec_context = self.context
        exec_context = self._build_mistral_context(exec_context,
                                                   current_context)
        LOG.info('Mistral query context is %s' % exec_context)

        return (status, partial_results, exec_context)
Example #39
0
    def _spawn_sensor_process(self, sensor):
        """
        Spawn a new process for the provided sensor.

        New process uses isolated Python binary from a virtual environment
        belonging to the sensor pack.
        """
        sensor_id = self._get_sensor_id(sensor=sensor)
        virtualenv_path = get_sandbox_virtualenv_path(pack=sensor['pack'])
        python_path = get_sandbox_python_binary_path(pack=sensor['pack'])

        if virtualenv_path and not os.path.isdir(virtualenv_path):
            format_values = {'pack': sensor['pack'], 'virtualenv_path': virtualenv_path}
            msg = PACK_VIRTUALENV_DOESNT_EXIST % format_values
            raise Exception(msg)

        trigger_type_refs = sensor['trigger_types'] or []
        trigger_type_refs = ','.join(trigger_type_refs)

        parent_args = json.dumps(sys.argv[1:])

        args = [
            python_path,
            WRAPPER_SCRIPT_PATH,
            '--pack=%s' % (sensor['pack']),
            '--file-path=%s' % (sensor['file_path']),
            '--class-name=%s' % (sensor['class_name']),
            '--trigger-type-refs=%s' % (trigger_type_refs),
            '--parent-args=%s' % (parent_args)
        ]

        if sensor['poll_interval']:
            args.append('--poll-interval=%s' % (sensor['poll_interval']))

        env = os.environ.copy()
        env['PYTHONPATH'] = get_sandbox_python_path(inherit_from_parent=True,
                                                    inherit_parent_virtualenv=True)

        # Include full api URL and API token specific to that sensor
        ttl = (24 * 60 * 60)
        temporary_token = create_token(username='******', ttl=ttl)

        env[API_URL_ENV_VARIABLE_NAME] = get_full_public_api_url()
        env[AUTH_TOKEN_ENV_VARIABLE_NAME] = temporary_token.token

        # TODO 1: Purge temporary token when service stops or sensor process dies
        # TODO 2: Store metadata (wrapper process id) with the token and delete
        # tokens for old, dead processes on startup
        cmd = ' '.join(args)
        LOG.debug('Running sensor subprocess (cmd="%s")', cmd)

        # TODO: Intercept stdout and stderr for aggregated logging purposes
        try:
            process = subprocess.Popen(args=args, stdin=None, stdout=None,
                                       stderr=None, shell=False, env=env,
                                       preexec_fn=on_parent_exit('SIGTERM'))
        except Exception as e:
            cmd = ' '.join(args)
            message = ('Failed to spawn process for sensor %s ("%s"): %s' %
                       (sensor_id, cmd, str(e)))
            raise Exception(message)

        self._processes[sensor_id] = process
        self._sensors[sensor_id] = sensor
        self._sensor_start_times[sensor_id] = int(time.time())

        self._dispatch_trigger_for_sensor_spawn(sensor=sensor, process=process, cmd=cmd)

        return process