mirror of
https://github.com/saltstack/salt.git
synced 2025-04-15 09:10:20 +00:00
Switch to proving the proper hooks to PyInstaller
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
This commit is contained in:
parent
8266505c99
commit
0d16398787
15 changed files with 387 additions and 161 deletions
1
changelog/61864.added
Normal file
1
changelog/61864.added
Normal file
|
@ -0,0 +1 @@
|
|||
Provide PyInstaller hooks that provide some runtime adjustments when Salt is running from a Tiamat(PyInstaller) bundled package.
|
|
@ -134,7 +134,3 @@ del __define_global_system_encoding_variable__
|
|||
|
||||
# Import Salt's logging machinery
|
||||
import salt._logging.impl # isort:skip pylint: disable=unused-import
|
||||
|
||||
# Do any nessessary patching when salt is running from a tiamat package
|
||||
# This code is temporary and will exist until we can handle this on salt-pkg
|
||||
import salt.utils.tiamatpkg # isort:skip pylint: disable=unused-import
|
||||
|
|
21
salt/utils/pyinstaller/__init__.py
Normal file
21
salt/utils/pyinstaller/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
"""
|
||||
This module exists to help PyInstaller bundle Salt
|
||||
"""
|
||||
import pathlib
|
||||
|
||||
PYINSTALLER_UTILS_DIR_PATH = pathlib.Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def get_hook_dirs():
|
||||
"""
|
||||
Return a list of paths that PyInstaller can search for hooks.
|
||||
"""
|
||||
hook_dirs = {PYINSTALLER_UTILS_DIR_PATH}
|
||||
for path in PYINSTALLER_UTILS_DIR_PATH.iterdir():
|
||||
if not path.is_dir():
|
||||
continue
|
||||
if "__pycache__" in path.parts:
|
||||
continue
|
||||
hook_dirs.add(path)
|
||||
|
||||
return sorted(str(p) for p in hook_dirs)
|
4
salt/utils/pyinstaller/rthooks.dat
Normal file
4
salt/utils/pyinstaller/rthooks.dat
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"subprocess": ["pyi_rth_subprocess.py"],
|
||||
"salt.utils.vt": ["pyi_rth_salt.utils.vt.py"],
|
||||
}
|
3
salt/utils/pyinstaller/rthooks/__init__.py
Normal file
3
salt/utils/pyinstaller/rthooks/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
This package contains support code to package Salt with PyInstaller.
|
||||
"""
|
70
salt/utils/pyinstaller/rthooks/_overrides.py
Normal file
70
salt/utils/pyinstaller/rthooks/_overrides.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
"""
|
||||
This package contains the runtime hooks support code for when Salt is pacakged with PyInstaller.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import salt.utils.vt
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def clean_pyinstaller_vars(environ):
|
||||
"""
|
||||
Restore or cleanup PyInstaller specific environent variable behavior.
|
||||
"""
|
||||
if environ is None:
|
||||
environ = {}
|
||||
# When Salt is bundled with tiamat, it MUST NOT contain LD_LIBRARY_PATH
|
||||
# when shelling out, or, at least the value of LD_LIBRARY_PATH set by
|
||||
# pyinstaller.
|
||||
# See:
|
||||
# https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#ld-library-path-libpath-considerations
|
||||
for varname in ("LD_LIBRARY_PATH", "LIBPATH"):
|
||||
original_varname = "{}_ORIG".format(varname)
|
||||
if varname in environ and environ[varname] == sys._MEIPASS:
|
||||
# If we find the varname on the user provided environment we need to at least
|
||||
# check if it's not the value set by PyInstaller, if it is, remove it.
|
||||
log.trace(
|
||||
"User provided environment variable %r with value %r which is "
|
||||
"the value that PyInstaller set's. Removing it",
|
||||
varname,
|
||||
environ[varname],
|
||||
)
|
||||
environ.pop(varname)
|
||||
|
||||
if original_varname in environ and varname not in environ:
|
||||
# We found the original variable set by PyInstaller, and we didn't find
|
||||
# any user provided variable, let's rename it.
|
||||
log.trace(
|
||||
"The %r variable was found in the passed environment, renaming it to %r",
|
||||
original_varname,
|
||||
varname,
|
||||
)
|
||||
environ[varname] = environ.pop(original_varname)
|
||||
|
||||
if varname not in environ:
|
||||
if original_varname in os.environ:
|
||||
log.trace(
|
||||
"Renaming environment variable %r to %r", original_varname, varname
|
||||
)
|
||||
environ[varname] = os.environ[original_varname]
|
||||
elif varname in os.environ:
|
||||
# Override the system environ variable with an empty one
|
||||
log.trace("Setting environment variable %r to an empty string", varname)
|
||||
environ[varname] = ""
|
||||
return environ
|
||||
|
||||
|
||||
class PyinstallerPopen(subprocess.Popen):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["env"] = clean_pyinstaller_vars(kwargs.pop("env", None))
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class PyinstallerTerminal(salt.utils.vt.Terminal): # pylint: disable=abstract-method
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["env"] = clean_pyinstaller_vars(kwargs.pop("env", None))
|
||||
super().__init__(*args, **kwargs)
|
13
salt/utils/pyinstaller/rthooks/pyi_rth_salt.utils.vt.py
Normal file
13
salt/utils/pyinstaller/rthooks/pyi_rth_salt.utils.vt.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
"""
|
||||
PyInstaller runtime hook to patch salt.utils.vt.Terminal
|
||||
"""
|
||||
import logging
|
||||
|
||||
import salt.utils.vt
|
||||
from salt.utils.pyinstaller.rthooks._overrides import PyinstallerTerminal
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
# Patch salt.utils.vt.Terminal when running within a pyinstalled bundled package
|
||||
salt.utils.vt.Terminal = PyinstallerTerminal
|
||||
|
||||
log.debug("Replaced 'salt.utils.vt.Terminal' with 'PyinstallerTerminal'")
|
13
salt/utils/pyinstaller/rthooks/pyi_rth_subprocess.py
Normal file
13
salt/utils/pyinstaller/rthooks/pyi_rth_subprocess.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
"""
|
||||
PyInstaller runtime hook to patch subprocess.Popen
|
||||
"""
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
from salt.utils.pyinstaller.rthooks._overrides import PyinstallerPopen
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
# Patch subprocess.Popen when running within a pyinstalled bundled package
|
||||
subprocess.Popen = PyinstallerPopen
|
||||
|
||||
log.debug("Replaced 'subprocess.Popen' with 'PyinstallerTerminal'")
|
|
@ -1,51 +0,0 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import salt.utils.vt
|
||||
from salt.utils.decorators import memoize
|
||||
|
||||
# This code is temporary and will exist until we can handle this on salt-pkg
|
||||
|
||||
|
||||
@memoize
|
||||
def is_tiamat_packaged():
|
||||
"""
|
||||
Returns True if salt is running from a tiamat pacakge, False otherwise
|
||||
"""
|
||||
return hasattr(sys, "_MEIPASS")
|
||||
|
||||
|
||||
def _cleanup_environ(environ):
|
||||
if environ is None:
|
||||
environ = os.environ.copy()
|
||||
|
||||
# When Salt is bundled with tiamat, it MUST NOT contain LD_LIBRARY_PATH
|
||||
# when shelling out, or, at least the value of LD_LIBRARY_PATH set by
|
||||
# pyinstaller.
|
||||
# See:
|
||||
# https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#ld-library-path-libpath-considerations
|
||||
for varname in ("LD_LIBRARY_PATH", "LIBPATH"):
|
||||
original_varname = "{}_ORIG".format(varname)
|
||||
if original_varname in environ:
|
||||
environ[varname] = environ.pop(original_varname)
|
||||
elif varname in environ:
|
||||
environ.pop(varname)
|
||||
return environ
|
||||
|
||||
|
||||
class TiamatPopen(subprocess.Popen):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["env"] = _cleanup_environ(kwargs.pop("env", None))
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class TiamatTerminal(salt.utils.vt.Terminal): # pylint: disable=abstract-method
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["env"] = _cleanup_environ(kwargs.pop("env", None))
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
if is_tiamat_packaged():
|
||||
subprocess.Popen = TiamatPopen
|
||||
salt.utils.vt.Terminal = TiamatTerminal
|
14
setup.py
14
setup.py
|
@ -1258,6 +1258,11 @@ class SaltDistribution(distutils.dist.Distribution):
|
|||
|
||||
@property
|
||||
def _property_entry_points(self):
|
||||
entrypoints = {
|
||||
"pyinstaller40": [
|
||||
"hook-dirs = salt.utils.pyinstaller:get_hook_dirs",
|
||||
],
|
||||
}
|
||||
# console scripts common to all scenarios
|
||||
scripts = [
|
||||
"salt-call = salt.scripts:salt_call",
|
||||
|
@ -1268,7 +1273,8 @@ class SaltDistribution(distutils.dist.Distribution):
|
|||
if IS_WINDOWS_PLATFORM:
|
||||
return {"console_scripts": scripts}
|
||||
scripts.append("salt-cloud = salt.scripts:salt_cloud")
|
||||
return {"console_scripts": scripts}
|
||||
entrypoints["console_scripts"] = scripts
|
||||
return entrypoints
|
||||
|
||||
if IS_WINDOWS_PLATFORM:
|
||||
scripts.extend(
|
||||
|
@ -1281,7 +1287,8 @@ class SaltDistribution(distutils.dist.Distribution):
|
|||
"spm = salt.scripts:salt_spm",
|
||||
]
|
||||
)
|
||||
return {"console_scripts": scripts}
|
||||
entrypoints["console_scripts"] = scripts
|
||||
return entrypoints
|
||||
|
||||
# *nix, so, we need all scripts
|
||||
scripts.extend(
|
||||
|
@ -1298,7 +1305,8 @@ class SaltDistribution(distutils.dist.Distribution):
|
|||
"spm = salt.scripts:salt_spm",
|
||||
]
|
||||
)
|
||||
return {"console_scripts": scripts}
|
||||
entrypoints["console_scripts"] = scripts
|
||||
return entrypoints
|
||||
|
||||
# <---- Dynamic Data ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
0
tests/pytests/functional/utils/pyinstaller/__init__.py
Normal file
0
tests/pytests/functional/utils/pyinstaller/__init__.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
import salt.utils.pyinstaller.rthooks._overrides as overrides
|
||||
from tests.support import mock
|
||||
from tests.support.helpers import PatchedEnviron
|
||||
|
||||
|
||||
@pytest.fixture(params=("LD_LIBRARY_PATH", "LIBPATH"))
|
||||
def envvar(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def meipass(envvar):
|
||||
with mock.patch("salt.utils.pyinstaller.rthooks._overrides.sys") as patched_sys:
|
||||
patched_sys._MEIPASS = envvar
|
||||
assert overrides.sys._MEIPASS == envvar
|
||||
yield "{}_VALUE".format(envvar)
|
||||
assert not hasattr(sys, "_MEIPASS")
|
||||
assert not hasattr(overrides.sys, "_MEIPASS")
|
||||
|
||||
|
||||
def test_vt_terminal_environ_cleanup_original(envvar, meipass):
|
||||
orig_envvar = "{}_ORIG".format(envvar)
|
||||
with PatchedEnviron(**{orig_envvar: meipass}):
|
||||
original_env = dict(os.environ)
|
||||
assert orig_envvar in original_env
|
||||
instance = overrides.PyinstallerTerminal(
|
||||
[
|
||||
sys.executable,
|
||||
"-c",
|
||||
"import os, json; print(json.dumps(dict(os.environ)))",
|
||||
],
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
buffer_o = buffer_e = ""
|
||||
while instance.has_unread_data:
|
||||
stdout, stderr = instance.recv()
|
||||
if stdout:
|
||||
buffer_o += stdout
|
||||
if stderr:
|
||||
buffer_e += stderr
|
||||
instance.terminate()
|
||||
|
||||
assert instance.exitstatus == 0
|
||||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert orig_envvar not in returned_env
|
||||
assert returned_env[envvar] == meipass
|
||||
|
||||
|
||||
def test_vt_terminal_environ_cleanup_original_passed_directly(envvar, meipass):
|
||||
orig_envvar = "{}_ORIG".format(envvar)
|
||||
env = {
|
||||
orig_envvar: meipass,
|
||||
}
|
||||
original_env = dict(os.environ)
|
||||
|
||||
instance = overrides.PyinstallerTerminal(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
buffer_o = buffer_e = ""
|
||||
while instance.has_unread_data:
|
||||
stdout, stderr = instance.recv()
|
||||
if stdout:
|
||||
buffer_o += stdout
|
||||
if stderr:
|
||||
buffer_e += stderr
|
||||
instance.terminate()
|
||||
|
||||
assert instance.exitstatus == 0
|
||||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert orig_envvar not in returned_env
|
||||
assert returned_env[envvar] == meipass
|
||||
|
||||
|
||||
def test_vt_terminal_environ_cleanup(envvar, meipass):
|
||||
with PatchedEnviron(**{envvar: meipass}):
|
||||
original_env = dict(os.environ)
|
||||
assert envvar in original_env
|
||||
instance = overrides.PyinstallerTerminal(
|
||||
[
|
||||
sys.executable,
|
||||
"-c",
|
||||
"import os, json; print(json.dumps(dict(os.environ)))",
|
||||
],
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
buffer_o = buffer_e = ""
|
||||
while instance.has_unread_data:
|
||||
stdout, stderr = instance.recv()
|
||||
if stdout:
|
||||
buffer_o += stdout
|
||||
if stderr:
|
||||
buffer_e += stderr
|
||||
instance.terminate()
|
||||
|
||||
assert instance.exitstatus == 0
|
||||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert returned_env[envvar] == ""
|
||||
|
||||
|
||||
def test_vt_terminal_environ_cleanup_passed_directly_not_removed(envvar, meipass):
|
||||
env = {
|
||||
envvar: meipass,
|
||||
}
|
||||
original_env = dict(os.environ)
|
||||
|
||||
instance = overrides.PyinstallerTerminal(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
buffer_o = buffer_e = ""
|
||||
while instance.has_unread_data:
|
||||
stdout, stderr = instance.recv()
|
||||
if stdout:
|
||||
buffer_o += stdout
|
||||
if stderr:
|
||||
buffer_e += stderr
|
||||
instance.terminate()
|
||||
|
||||
assert instance.exitstatus == 0
|
||||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert returned_env[envvar] == meipass
|
|
@ -0,0 +1,110 @@
|
|||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
import salt.utils.pyinstaller.rthooks._overrides as overrides
|
||||
from tests.support import mock
|
||||
from tests.support.helpers import PatchedEnviron
|
||||
|
||||
|
||||
@pytest.fixture(params=("LD_LIBRARY_PATH", "LIBPATH"))
|
||||
def envvar(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def meipass(envvar):
|
||||
with mock.patch("salt.utils.pyinstaller.rthooks._overrides.sys") as patched_sys:
|
||||
patched_sys._MEIPASS = envvar
|
||||
assert overrides.sys._MEIPASS == envvar
|
||||
yield "{}_VALUE".format(envvar)
|
||||
assert not hasattr(sys, "_MEIPASS")
|
||||
assert not hasattr(overrides.sys, "_MEIPASS")
|
||||
|
||||
|
||||
def test_subprocess_popen_environ_cleanup_original(envvar, meipass):
|
||||
orig_envvar = "{}_ORIG".format(envvar)
|
||||
with PatchedEnviron(**{orig_envvar: meipass}):
|
||||
original_env = dict(os.environ)
|
||||
assert orig_envvar in original_env
|
||||
instance = overrides.PyinstallerPopen(
|
||||
[
|
||||
sys.executable,
|
||||
"-c",
|
||||
"import os, json; print(json.dumps(dict(os.environ)))",
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
)
|
||||
stdout, _ = instance.communicate()
|
||||
assert instance.returncode == 0
|
||||
returned_env = json.loads(stdout)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert orig_envvar not in returned_env
|
||||
assert returned_env[envvar] == meipass
|
||||
|
||||
|
||||
def test_subprocess_popen_environ_cleanup_original_passed_directly(envvar, meipass):
|
||||
orig_envvar = "{}_ORIG".format(envvar)
|
||||
env = {
|
||||
orig_envvar: meipass,
|
||||
}
|
||||
original_env = dict(os.environ)
|
||||
|
||||
instance = overrides.PyinstallerPopen(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
)
|
||||
stdout, _ = instance.communicate()
|
||||
assert instance.returncode == 0
|
||||
returned_env = json.loads(stdout)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert orig_envvar not in returned_env
|
||||
assert returned_env[envvar] == meipass
|
||||
|
||||
|
||||
def test_subprocess_popen_environ_cleanup(envvar, meipass):
|
||||
with PatchedEnviron(**{envvar: meipass}):
|
||||
original_env = dict(os.environ)
|
||||
assert envvar in original_env
|
||||
instance = overrides.PyinstallerPopen(
|
||||
[
|
||||
sys.executable,
|
||||
"-c",
|
||||
"import os, json; print(json.dumps(dict(os.environ)))",
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
)
|
||||
stdout, _ = instance.communicate()
|
||||
assert instance.returncode == 0
|
||||
returned_env = json.loads(stdout)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert returned_env[envvar] == ""
|
||||
|
||||
|
||||
def test_subprocess_popen_environ_cleanup_passed_directly_not_removed(envvar, meipass):
|
||||
env = {
|
||||
envvar: meipass,
|
||||
}
|
||||
original_env = dict(os.environ)
|
||||
|
||||
instance = overrides.PyinstallerPopen(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True,
|
||||
)
|
||||
stdout, _ = instance.communicate()
|
||||
assert instance.returncode == 0
|
||||
returned_env = json.loads(stdout)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert returned_env[envvar] == meipass
|
|
@ -1,103 +0,0 @@
|
|||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
import salt.utils.tiamatpkg
|
||||
|
||||
|
||||
@pytest.fixture(params=("LD_LIBRARY_PATH", "LIBPATH"))
|
||||
def envvar(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_subprocess_popen_environ_cleanup_existing(envvar):
|
||||
envvar_value = "foo"
|
||||
orig_envvar = "{}_ORIG".format(envvar)
|
||||
env = {
|
||||
orig_envvar: envvar_value,
|
||||
}
|
||||
instance = salt.utils.tiamatpkg.TiamatPopen(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
stdout, _ = instance.communicate()
|
||||
assert instance.returncode == 0
|
||||
returned_env = json.loads(stdout)
|
||||
assert returned_env != env
|
||||
assert envvar in returned_env
|
||||
assert orig_envvar not in returned_env
|
||||
assert returned_env[envvar] == envvar_value
|
||||
|
||||
|
||||
def test_subprocess_popen_environ_cleanup(envvar):
|
||||
envvar_value = "foo"
|
||||
env = {
|
||||
envvar: envvar_value,
|
||||
}
|
||||
instance = salt.utils.tiamatpkg.TiamatPopen(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
stdout, _ = instance.communicate()
|
||||
assert instance.returncode == 0
|
||||
returned_env = json.loads(stdout)
|
||||
assert returned_env != env
|
||||
assert envvar not in returned_env
|
||||
|
||||
|
||||
def test_vt_terminal_environ_cleanup_existing(envvar):
|
||||
envvar_value = "foo"
|
||||
orig_envvar = "{}_ORIG".format(envvar)
|
||||
env = {
|
||||
orig_envvar: envvar_value,
|
||||
}
|
||||
instance = salt.utils.tiamatpkg.TiamatTerminal(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
buffer_o = buffer_e = ""
|
||||
while instance.has_unread_data:
|
||||
stdout, stderr = instance.recv()
|
||||
if stdout:
|
||||
buffer_o += stdout
|
||||
if stderr:
|
||||
buffer_e += stderr
|
||||
instance.terminate()
|
||||
|
||||
assert instance.exitstatus == 0
|
||||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != env
|
||||
assert envvar in returned_env
|
||||
assert orig_envvar not in returned_env
|
||||
assert returned_env[envvar] == envvar_value
|
||||
|
||||
|
||||
def test_vt_terminal_environ_cleanup(envvar):
|
||||
envvar_value = "foo"
|
||||
env = {
|
||||
envvar: envvar_value,
|
||||
}
|
||||
instance = salt.utils.tiamatpkg.TiamatTerminal(
|
||||
[sys.executable, "-c", "import os, json; print(json.dumps(dict(os.environ)))"],
|
||||
env=env.copy(),
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
buffer_o = buffer_e = ""
|
||||
while instance.has_unread_data:
|
||||
stdout, stderr = instance.recv()
|
||||
if stdout:
|
||||
buffer_o += stdout
|
||||
if stderr:
|
||||
buffer_e += stderr
|
||||
instance.terminate()
|
||||
|
||||
assert instance.exitstatus == 0
|
||||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != env
|
||||
assert envvar not in returned_env
|
Loading…
Add table
Reference in a new issue