GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — regana/mac-dev ( 625243...be7637 )
by
unknown
09:18 queued 03:37
created

st2actions.runners.Action._set_up_logger()   A

Complexity

Conditions 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 17
rs 9.4285
cc 1

2 Methods

Rating   Name   Duplication   Size   Complexity  
A st2actions.runners.PythonRunner.__init__() 0 7 1
A st2actions.runners.PythonRunner.pre_run() 0 6 1
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
import os
17
import sys
18
import abc
19
import json
20
import uuid
21
22
import six
23
from eventlet.green import subprocess
24
25
from st2actions.runners import ActionRunner
26
from st2common.util.green.shell import run_command
27
from st2common.constants.action import ACTION_OUTPUT_RESULT_DELIMITER
28
from st2common.constants.action import LIVEACTION_STATUS_SUCCEEDED
29
from st2common.constants.action import LIVEACTION_STATUS_FAILED
30
from st2common.constants.action import LIVEACTION_STATUS_TIMED_OUT
31
from st2common.constants.error_messages import PACK_VIRTUALENV_DOESNT_EXIST
32
from st2common.util.sandboxing import get_sandbox_path
33
from st2common.util.sandboxing import get_sandbox_python_path
34
from st2common.util.sandboxing import get_sandbox_python_binary_path
35
from st2common.util.sandboxing import get_sandbox_virtualenv_path
36
from st2common.constants.runners import PYTHON_RUNNER_DEFAULT_ACTION_TIMEOUT
37
38
__all__ = [
39
    'get_runner',
40
41
    'PythonRunner',
42
    'Action'
43
]
44
45
# constants to lookup in runner_parameters.
46
RUNNER_ENV = 'env'
47
RUNNER_TIMEOUT = 'timeout'
48
49
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
50
WRAPPER_SCRIPT_NAME = 'python_action_wrapper.py'
51
WRAPPER_SCRIPT_PATH = os.path.join(BASE_DIR, WRAPPER_SCRIPT_NAME)
52
53
54
def get_runner():
55
    return PythonRunner(str(uuid.uuid4()))
56
57
58
@six.add_metaclass(abc.ABCMeta)
59
class Action(object):
60
    """
61
    Base action class other Python actions should inherit from.
62
    """
63
64
    description = None
65
66
    def __init__(self, config=None):
67
        """
68
        :param config: Action config.
69
        :type config: ``dict``
70
        """
71
        self.config = config or {}
72
        # logger and datastore are assigned in PythonActionWrapper._get_action_instance
73
        self.logger = None
74
        self.datastore = None
75
76
    @abc.abstractmethod
77
    def run(self, **kwargs):
78
        pass
79
80
81
class PythonRunner(ActionRunner):
82
83
    def __init__(self, runner_id, timeout=PYTHON_RUNNER_DEFAULT_ACTION_TIMEOUT):
84
        """
85
        :param timeout: Action execution timeout in seconds.
86
        :type timeout: ``int``
87
        """
88
        super(PythonRunner, self).__init__(runner_id=runner_id)
89
        self._timeout = timeout
90
91
    def pre_run(self):
92
        # TODO :This is awful, but the way "runner_parameters" and other variables get
93
        # assigned on the runner instance is even worse. Those arguments should
94
        # be passed to the constructor.
95
        self._env = self.runner_parameters.get(RUNNER_ENV, {})
96
        self._timeout = self.runner_parameters.get(RUNNER_TIMEOUT, self._timeout)
97
98
    def run(self, action_parameters):
99
        pack = self.get_pack_name()
100
        serialized_parameters = json.dumps(action_parameters) if action_parameters else ''
101
        virtualenv_path = get_sandbox_virtualenv_path(pack=pack)
102
        python_path = get_sandbox_python_binary_path(pack=pack)
103
104
        if virtualenv_path and not os.path.isdir(virtualenv_path):
105
            format_values = {'pack': pack, 'virtualenv_path': virtualenv_path}
106
            msg = PACK_VIRTUALENV_DOESNT_EXIST % format_values
107
            raise Exception(msg)
108
109
        if not self.entry_point:
110
            raise Exception('Action "%s" is missing entry_point attribute' % (self.action.name))
111
112
        args = [
113
            python_path,
114
            WRAPPER_SCRIPT_PATH,
115
            '--pack=%s' % (pack),
116
            '--file-path=%s' % (self.entry_point),
117
            '--parameters=%s' % (serialized_parameters),
118
            '--parent-args=%s' % (json.dumps(sys.argv[1:]))
119
        ]
120
121
        # We need to ensure all the st2 dependencies are also available to the
122
        # subprocess
123
        env = os.environ.copy()
124
        env['PATH'] = get_sandbox_path(virtualenv_path=virtualenv_path)
125
        env['PYTHONPATH'] = get_sandbox_python_path(inherit_from_parent=True,
126
                                                    inherit_parent_virtualenv=True)
127
128
        # Include user provided environment variables (if any)
129
        user_env_vars = self._get_env_vars()
130
        env.update(user_env_vars)
131
132
        # Include common st2 environment variables
133
        st2_env_vars = self._get_common_action_env_variables()
134
        env.update(st2_env_vars)
135
136
        exit_code, stdout, stderr, timed_out = run_command(cmd=args, stdout=subprocess.PIPE,
137
                                                           stderr=subprocess.PIPE, shell=False,
138
                                                           env=env, timeout=self._timeout)
139
140
        if timed_out:
141
            error = 'Action failed to complete in %s seconds' % (self._timeout)
142
        else:
143
            error = None
144
145
        if ACTION_OUTPUT_RESULT_DELIMITER in stdout:
146
            split = stdout.split(ACTION_OUTPUT_RESULT_DELIMITER)
147
            assert len(split) == 3
148
            result = split[1].strip()
149
            stdout = split[0] + split[2]
150
        else:
151
            result = None
152
153
        try:
154
            result = json.loads(result)
155
        except:
156
            pass
157
158
        output = {
159
            'stdout': stdout,
160
            'stderr': stderr,
161
            'exit_code': exit_code,
162
            'result': result
163
        }
164
165
        if error:
166
            output['error'] = error
167
168
        if exit_code == 0:
169
            status = LIVEACTION_STATUS_SUCCEEDED
170
        elif timed_out:
171
            status = LIVEACTION_STATUS_TIMED_OUT
172
        else:
173
            status = LIVEACTION_STATUS_FAILED
174
175
        return (status, output, None)
176
177
    def _get_env_vars(self):
178
        """
179
        Return sanitized environment variables which will be used when launching
180
        a subprocess.
181
182
        :rtype: ``dict``
183
        """
184
        # Don't allow user to override PYTHONPATH since this would break things
185
        blacklisted_vars = ['pythonpath']
186
        env_vars = {}
187
188
        if self._env:
189
            env_vars.update(self._env)
190
191
        # Remove "blacklisted" environment variables
192
        to_delete = []
193
        for key, value in env_vars.items():
194
            if key.lower() in blacklisted_vars:
195
                to_delete.append(key)
196
197
        for key in to_delete:
198
            del env_vars[key]
199
200
        return env_vars
201