Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ Fixed

* StackStorm now explicitly decodes pack files as utf-8 instead of implicitly as ascii (bug fix) #5106, #5107

* Kept functionality for implicit relative imports in Python actions (regression, bug fix) #5127

Identified by @amanda11

Removed
~~~~~~~~
* Removed --python3 pack install option #5100
Expand Down
61 changes: 60 additions & 1 deletion st2common/st2common/util/sandboxing.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@

from __future__ import absolute_import

import fnmatch
import os
import sys
from distutils.sysconfig import get_python_lib

from oslo_config import cfg

from st2common.constants.pack import SYSTEM_PACK_NAMES
from st2common.content.utils import get_pack_base_path

__all__ = [
'get_sandbox_python_binary_path',
Expand Down Expand Up @@ -132,10 +134,67 @@ def get_sandbox_python_path_for_python_action(pack, inherit_from_parent=True,
Same as get_sandbox_python_path() function, but it's intended to be used for Python runner
actions.
"""
return get_sandbox_python_path(
sandbox_python_path = get_sandbox_python_path(
inherit_from_parent=inherit_from_parent,
inherit_parent_virtualenv=inherit_parent_virtualenv)

virtualenv_path = get_sandbox_virtualenv_path(pack=pack)

if virtualenv_path and os.path.isdir(virtualenv_path):
# Get the pack's virtualenv site-packages directory
# There should only be one, but we don't know what version of Python it
# will be using, so we use a glob and ensure it exists
virtualenv_lib_path = os.path.join(virtualenv_path, 'lib')
virtualenv_lib_directories = [
dir_name for dir_name in os.listdir(virtualenv_lib_path)
if fnmatch.fnmatch(dir_name, 'python*')
]

if virtualenv_lib_directories:
pack_base_path = get_pack_base_path(pack_name=pack)
# This will be just the virtualenv's Python version - eg: python3.6
virtualenv_lib_directory = virtualenv_lib_directories[0]

# Get the pack's actions/lib directory
pack_actions_lib_paths = os.path.join(pack_base_path, 'actions', 'lib')
# Get the pack's virtualenv's site-packages directory
virtualenv_lib_directory = os.path.join(virtualenv_lib_path, virtualenv_lib_directory)

# Work around to make sure we also add system lib dir to PYTHONPATH
# and not just virtualenv one (e.g. /usr/lib/python3.6)
# This code will pick the same sytem Python version as exists in
# the virtualenv, since virtualenv_lib_directory identifies that
# directory within the virtualenv and it should have the same name
# as the system Python executable.

# NOTE: We can't simply use sys.prefix dir since it will be set to /opt/stackstorm/st2

# By default, Python libs are installed either in /usr/lib/python3.x or
# /usr/local/lib/python3.x
for system_prefix_dir in ['/usr/lib', '/usr/local/lib']:
system_lib_directory = os.path.join(system_prefix_dir,
virtualenv_lib_directory)

if os.path.exists(system_lib_directory):
break
else:
# If no system library is found
system_lib_directory = None

full_sandbox_python_path = []

# NOTE: Order here is very important for imports to function correctly
if system_lib_directory:
full_sandbox_python_path.append(system_lib_directory)

full_sandbox_python_path.append(virtualenv_lib_directory)
full_sandbox_python_path.append(pack_actions_lib_paths)
full_sandbox_python_path.append(sandbox_python_path)

sandbox_python_path = ':'.join(full_sandbox_python_path)

return sandbox_python_path


def get_sandbox_virtualenv_path(pack):
"""
Expand Down
2 changes: 2 additions & 0 deletions st2common/tests/unit/test_util_sandboxing.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ def test_get_sandbox_python_path(self, mock_get_python_lib):

@mock.patch('os.path.isdir', mock.Mock(return_value=True))
@mock.patch('os.listdir', mock.Mock(return_value=['python2.7']))
@mock.patch('st2common.util.sandboxing.get_sandbox_virtualenv_path',
mock.Mock(return_value=None))
@mock.patch('st2common.util.sandboxing.get_python_lib')
def test_get_sandbox_python_path_for_python_action_python2_used_for_venv(self,
mock_get_python_lib):
Expand Down