Giter VIP home page Giter VIP logo

relenv's People

Contributors

cro avatar dwoz avatar felippeb avatar garethgreenaway avatar ggiesen avatar mkleb avatar mrflynn avatar rrrix avatar s0undt3ch avatar twangboy avatar whytewolf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

relenv's Issues

Installing packages with Salt-Pip fails: JSONDecodeError

Installing packages with salt-pip (Salt 3006.0) fails with a JSONDecodeError and what appears to be some recursive behavior.

To reproduce, set up a fresh Almalinux 8.7 box (I use Vagrant on QEMU) and manually install the Salt 3006.0 minion. Add a symlink according to #114:

ln -s /opt/saltstack/salt/bin/python3 /usr/bin/python3

Then, attempt to install pycryptodome (or any other package in my experience):

/opt/saltstack/salt/salt-pip install pycryptodome
Stack Trace
Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/saltstack/salt/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/__main__.py", line 29, in <module>
    from pip._internal.cli.main import main as _main
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/main.py", line 9, in <module>
    from pip._internal.cli.autocompletion import autocomplete
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/autocompletion.py", line 10, in <module>
    from pip._internal.cli.main_parser import create_main_parser
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/main_parser.py", line 9, in <module>
    from pip._internal.build_env import get_runnable_pip
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/build_env.py", line 20, in <module>
    from pip._internal.cli.spinners import open_spinner
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/spinners.py", line 9, in <module>
    from pip._internal.utils.logging import get_indentation
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/utils/logging.py", line 29, in <module>
    from pip._internal.utils.misc import ensure_dir
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/utils/misc.py", line 42, in <module>
    from pip._internal.locations import get_major_minor_version
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/locations/__init__.py", line 14, in <module>
    from . import _sysconfig
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/locations/_sysconfig.py", line 11, in <module>
    from .base import change_root, get_major_minor_version, is_osx_framework
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/locations/base.py", line 16, in <module>
    site_packages: typing.Optional[str] = sysconfig.get_path("purelib")
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 572, in get_path
    return get_paths(scheme, vars, expand)[name]
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 167, in wrapped
    paths = func(scheme=scheme, vars=vars, expand=expand)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 562, in get_paths
    return _expand_vars(scheme, vars)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 218, in _expand_vars
    _extend_dict(vars, get_config_vars())
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 131, in wrapped
    _CONFIG_VARS = func()
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 640, in get_config_vars
    srcdir = os.path.dirname(get_makefile_filename())
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 399, in get_makefile_filename
    return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 572, in get_path
    return get_paths(scheme, vars, expand)[name]
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 167, in wrapped
    paths = func(scheme=scheme, vars=vars, expand=expand)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 562, in get_paths
    return _expand_vars(scheme, vars)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 218, in _expand_vars
    _extend_dict(vars, get_config_vars())
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 140, in wrapped
    _SYSTEM_CONFIG_VARS = json.loads(p.stdout[:-1])
  File "/opt/saltstack/salt/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/opt/saltstack/salt/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/opt/saltstack/salt/lib/python3.10/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The JSONDecodeError is due to get_config_vars_wrapper(...) parsing the stdout of a subprocess Python call to sysconfig: in my environment, calling sysconfig.get_config_vars() actually prints nothing (stdout empty), causing JSON decoding to fail. (Side note: did Rube Goldberg write this function? I'm sure there's a reason for the way this is implemented; could someone elaborate?)

Digging deeper into sysconfig.get_config_vars() reveals some apparently recursive behavior. The following is what I have observed in my environment when calling sysconfig.get_config_vars() in the same manner as get_config_vars_wrapper() from Salt 3006.0's Python 3.10 REPL:

  1. sysconfig.get_config_vars() is called without arguments. _CONFIG_VARS is None, the os.name is posix and _PYTHON_BUILD is falsy. Execution continues to get_makefile_filename().
  2. Execution continues to a call to get_path('stdlib').
  3. get_paths('posix_prefix', None, True) is called. It in turn calls _expand_vars('posix_prefix', None).
  4. _expand_vars calls _extend_dict(None, get_config_vars()). Notice that get_config_vars() is now being recursively called.
  5. At this point in practice, the wrapper is called instead of get_config_vars. The wrapper, again, calls sysconfig.get_config_vars(None) within a new Python subprocess, and this time _CONFIG_VARS has a bunch (722 for me) of variables, which it returns.
  6. For some reason I haven't wrapped my mind around, the now non-empty variables result is not returned from the wrapper back to _extend_dict. In fact, _extend_dict is never called. Instead, the wrapper recursively calls itself. I've seen it do so up to 1,024 times, and have heard from another user with this problem that it is accompanied by a spike in memory and crash of the Salt minion and master.

Interestingly, this behavior seems to only occur when using Salt's bundled Python at /usr/bin/python3. Compiling Python 3.10.11 from source and adding the appropriate symlink for that scenario (ln -s /usr/local/bin/python3 /usr/bin/python3) does not present this problem.

relenv create -h | --help is broken

$ relenv --version
0.11.2
$ relenv create --help
Traceback (most recent call last):
  File "/Users/rick.bowen/git/saltstack/relative-environment-for-python/.venv/bin/relenv", line 8, in <module>
    sys.exit(main())
  File "/Users/rick.bowen/git/saltstack/relative-environment-for-python/relenv/__main__.py", line 49, in main
    args = parser.parse_args()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1826, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1859, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 2050, in _parse_known_args
    positionals_end_index = consume_positionals(start_index)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 2027, in consume_positionals
    take_action(action, args)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1936, in take_action
    action(self, namespace, argument_values, option_string)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1214, in __call__
    subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1859, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 2068, in _parse_known_args
    start_index = consume_optional(start_index)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 2008, in consume_optional
    take_action(action, args, option_string)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1936, in take_action
    action(self, namespace, argument_values, option_string)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 1099, in __call__
    parser.print_help()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 2556, in print_help
    self._print_message(self.format_help(), file)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 2540, in format_help
    return formatter.format_help()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 283, in format_help
    help = self._root_section.format_help()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 214, in format_help
    item_help = join([func(*args) for func, args in self.items])
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 214, in <listcomp>
    item_help = join([func(*args) for func, args in self.items])
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 501, in _format_text
    return self._fill_text(text, text_width, indent) + '\n\n'
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/argparse.py", line 650, in _fill_text
    text = self._whitespace_matcher.sub(' ', text).strip()
TypeError: expected string or bytes-like object

Address warnings for cleaner runtime

A couple warnings started popping up.

2023-08-28T21:30:28.2106254Z <frozen importlib._bootstrap>:283: DeprecationWarning: the load_module() method is deprecated and slated for removal in Python 3.12; use exec_module() instead
2023-08-28T21:30:28.8675492Z <frozen importlib._bootstrap>:914: ImportWarning: RelenvImporter.find_spec() not found; falling back to find_module()

Weird includes when installing salt using `USE_STATIC_REQUIREMENTS=1`

Installing salt using USE_STATIC_REQUIREMENTS=1, which selects a different set of requirements, fails.

ubuntu@ip-10-1-102-50:~$ salt/bin/python3 -m pip install downloaded-requirements/cffi-1.14.6.tar.gz
Processing ./downloaded-requirements/cffi-1.14.6.tar.gz
  Preparing metadata (setup.py) ... done
Requirement already satisfied: pycparser in ./salt/lib/python3.10/site-packages (from cffi==1.14.6) (2.21)
Building wheels for collected packages: cffi
  Building wheel for cffi (setup.py) ... error
  error: subprocess-exited-with-error

  × python setup.py bdist_wheel did not run successfully.
  │ exit code: 1
  ╰─> [38 lines of output]
      /home/ubuntu/salt/lib/python3.10/site-packages/setuptools/config/setupcfg.py:463: SetuptoolsDeprecationWarning: The license_file parameter is deprecated, use license_files instead.
        warnings.warn(msg, warning_class)
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.linux-x86_64-cpython-310
      creating build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/recompiler.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/vengine_cpy.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/backend_ctypes.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/setuptools_ext.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/error.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/pkgconfig.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/api.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/commontypes.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/model.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/cffi_opcode.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/vengine_gen.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/ffiplatform.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/verifier.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/__init__.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/cparser.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/lock.py -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/_cffi_include.h -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/parse_c_type.h -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/_embedding.h -> build/lib.linux-x86_64-cpython-310/cffi
      copying cffi/_cffi_errors.h -> build/lib.linux-x86_64-cpython-310/cffi
      running build_ext
      building '_cffi_backend' extension
      creating build/temp.linux-x86_64-cpython-310
      creating build/temp.linux-x86_64-cpython-310/c
      /home/ubuntu/.local/relenv/toolchain/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc -no-pie -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -O3 -Wall -L/home/ubuntu/.local/lib -L/home/ubuntu/.local/relenv/
toolchain/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib -I/home/ubuntu/.local/include -I/home/ubuntu/.local/include/readline -I/home/ubuntu/.local/include/ncursesw -I/home/ubuntu/.local/relenv/toolchain/x86_64-lin
ux-gnu/x86_64-linux-gnu/sysroot/usr/include -L/home/ubuntu/.local/lib -L/home/ubuntu/.local/relenv/toolchain/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib -I/home/ubuntu/.local/include -I/home/ubuntu/.local/includ
e/readline -I/home/ubuntu/.local/include/ncursesw -I/home/ubuntu/.local/relenv/toolchain/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/usr/include -fPIC -DUSE__THREAD -DHAVE_SYNC_SYNCHRONIZE -I/home/ubuntu/salt/includ
e/python3.10 -c c/_cffi_backend.c -o build/temp.linux-x86_64-cpython-310/c/_cffi_backend.o
      c/_cffi_backend.c:15:10: fatal error: ffi.h: No such file or directory
         15 | #include <ffi.h>
            |          ^~~~~~~
      compilation terminated.
      error: command '/home/ubuntu/.local/relenv/toolchain/x86_64-linux-gnu/bin/x86_64-linux-gnu-gcc' failed with exit code 1

RELENV_PIP_DIR environment not working on windows

Defining the RELENV_PIP_DIR environment variable should cause pip to install scripts into the root the environment instead of the bin directory. This functionality works on linux but not on windows. I suspect this has to do with the version of python on windows and not something platform specific.

sys.path Sanitizing Breaks When Relenv is Within a Symlinked Directory

When attempting to install salt using the onedir method I encountered a failure where some imports in the relenv Python environment could not be found (ex. runpy). After doing some digging, I was able to identify that the mechanism relenv uses to sanitize sys.path will remove valid entries if the Python interpreter is called from a path that contains a symlink anywhere along the path.

Steps to Reproduce

  1. Create a target directory and link it to a directory called parent: mkdir -p target/ && ln -sf target/ parent/.
  2. Create a new relenv inside the parent directory: cd parent/ && relenv create testenv.
  3. Go up one directory and launch the python interpreter inside the relenv with debugging enabled and observe that sys.path has been cleared.
$ RELENV_DEBUG=true parent/testenv/bin/python3
Unable to get the modules directory from openssl: version: Option unknown option -m
version: Use -help for summary.

original sys.path was ['/root/parent/testenv/lib/python310.zip', '/root/parent/testenv/lib/python3.10', '/root/parent/testenv/lib/python3.10/lib-dynload', '/root/parent/testenv/lib/python3.10/site-packages']
new sys.path is []
After site customize wrapper
Python 3.10.13 (main, Nov  8 2023, 12:14:32) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Root Cause

After digging into the code, I identified that the sanitize_sys_path function incorrectly removes entries in sys.path because it doesn't resolve symlinks properly. Specifically this code:

https://github.com/saltstack/relative-environment-for-python/blob/78b8dbf8d5d76612bc79e8ab8760ffc82223e072/relenv/common.py#L471-L472

A call to resolve() needs to happen before checking if the sys.path entry is relative to the valid prefix. Something like the following would resolve this issue.

__resolved_path = pathlib.Path(__path).resolve()
__resolved_path.relative_to(__valid_path_prefix)
__sys_path.append(str(__resolved_path))

Currently the lack of proper path resolving breaks installing salt in onedir mode if /opt is symlinked to another directory.

Toolchain build documentation is out of date/wrong

https://relenv.readthedocs.io/en/latest/toolchain.html references [email protected]:saltstack/relenv.git (by ssh, not https, too) which doesn't exist, and tells the user to use relenv toolchain build which doesn't exist:

(venv) frebib@frebib-PC /t/relenv.NCsd7Umb> python3.11 -m relenv toolchain download
usage: relenv toolchain [-h] [--arch {x86_64,aarch64}] [--clean] [--crosstool-only] {build,fetch}
relenv toolchain: error: argument command: invalid choice: 'download' (choose from 'build', 'fetch')

Add ability to choose architecture to build

We need to be able to build 32-bit Python on Windows. As per the output of --help the only options are x86_64 and aarch64:

C:\src\Mayflower>python -m mayflower build --help
usage: __main__.py build [-h] [--arch {x86_64,aarch64}] [--clean] [--no-cleanup] [--no-download] [--step STEP]

Build Mayflower Python Environments from source

optional arguments:
  -h, --help            show this help message and exit
  --arch {x86_64,aarch64}
                        The host architecture [default: x86_64]
  --clean               Clean up before running the build. This option will remove the logs, src, build, and previous tarball.
  --no-cleanup          By default the build directory is removed after the build tarball is created. Setting this option will leave the build directory in place.
  --no-download         Skip downloading source tarballs
  --step STEP           A step to run alone, can use multiple of this argument. When this option is used to invoke builds, depenencies of the steps are ignored. This option should be used with care, as it's easy to request a situation that has no chance of
                        being succesful.```

Fips module not loading

We see the following error on photon os with fips enabled. The fips module mac between the module shipped with photon and the module shipped with relenv differ. Rather than having to run relenv with it's own ssl config; default to the system's openssl modules location.

ValueError: [digital envelope routines] unsupported

Add native aarch64 builds on linux

Currently we're cross compiling python aarch64 for linux on x86_64.

Add a build which builds aarch64 on aarch64 to make sure we're testing this case for now.

Hardcoded Python executable path depends upon system Python being installed

get_config_vars_wrapper(...) runs Python as a subprocess (more explanation on why this is necessary would be great). The path to Python to run in the subprocess is hard coded to /usr/bin/python3, which is not always installed and would require either a symlink to Salt's salt-pip or a system Python installation.

To reproduce, spin up Almalinux 8.7 (I do so in Vagrant on QEMU) and manually install the Salt minion, confirming there is no Python installed on the system. Then, log in and execute:

/opt/saltstack/salt/salt-pip install pycryptodome
Exception
Traceback (most recent call last):
  File "/opt/saltstack/salt/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/saltstack/salt/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/__main__.py", line 29, in <module>
    from pip._internal.cli.main import main as _main
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/main.py", line 9, in <module>
    from pip._internal.cli.autocompletion import autocomplete
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/autocompletion.py", line 10, in <module>
    from pip._internal.cli.main_parser import create_main_parser
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/main_parser.py", line 9, in <module>
    from pip._internal.build_env import get_runnable_pip
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/build_env.py", line 20, in <module>
    from pip._internal.cli.spinners import open_spinner
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/cli/spinners.py", line 9, in <module>
    from pip._internal.utils.logging import get_indentation
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/utils/logging.py", line 29, in <module>
    from pip._internal.utils.misc import ensure_dir
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/utils/misc.py", line 42, in <module>
    from pip._internal.locations import get_major_minor_version
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/locations/__init__.py", line 14, in <module>
    from . import _sysconfig
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/locations/_sysconfig.py", line 11, in <module>
    from .base import change_root, get_major_minor_version, is_osx_framework
  File "/opt/saltstack/salt/lib/python3.10/site-packages/pip/_internal/locations/base.py", line 16, in <module>
    site_packages: typing.Optional[str] = sysconfig.get_path("purelib")
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 572, in get_path
    return get_paths(scheme, vars, expand)[name]
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 167, in wrapped
    paths = func(scheme=scheme, vars=vars, expand=expand)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 562, in get_paths
    return _expand_vars(scheme, vars)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 218, in _expand_vars
    _extend_dict(vars, get_config_vars())
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 131, in wrapped
    _CONFIG_VARS = func()
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 640, in get_config_vars
    srcdir = os.path.dirname(get_makefile_filename())
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 399, in get_makefile_filename
    return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 572, in get_path
    return get_paths(scheme, vars, expand)[name]
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 167, in wrapped
    paths = func(scheme=scheme, vars=vars, expand=expand)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 562, in get_paths
    return _expand_vars(scheme, vars)
  File "/opt/saltstack/salt/lib/python3.10/sysconfig.py", line 218, in _expand_vars
    _extend_dict(vars, get_config_vars())
  File "/opt/saltstack/salt/lib/python3.10/site-packages/relenv/runtime.py", line 132, in wrapped
    p = subprocess.run(
  File "/opt/saltstack/salt/lib/python3.10/subprocess.py", line 503, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/opt/saltstack/salt/lib/python3.10/subprocess.py", line 971, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/opt/saltstack/salt/lib/python3.10/subprocess.py", line 1863, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/python3'

This issue can be bypassed by:

  • installing Python on the system
  • creating a symlink:
    ln -s /opt/saltstack/salt/bin/python3 /usr/bin/python3

Additional Key Types

Add two more types of keys. In addition to minion; add master and client (cli) keys.

Docs publishing broken

Looks like docs have not been updated during the last few releases. We need to investigate why docs were not publish and If docs fail the build should fail.

Unable to run pip binary on MacOS

When I try to run pip commands I get the following:

Salts-Mac:osx saltadmin$ /Users/saltadmin/src/salt/pkg/osx/build/opt/salt/bin/pip3 list
readlink: illegal option -- f
usage: readlink [-n] [file ...]
usage: dirname path
/Users/saltadmin/src/salt/pkg/osx/build/opt/salt/bin/pip3: line 2: /python3: No such file or directory
/Users/saltadmin/src/salt/pkg/osx/build/opt/salt/bin/pip3: line 2: exec: /python3: cannot execute: No such file or directory

Running pip from python works:

Salts-Mac:osx saltadmin$ /Users/saltadmin/src/salt/pkg/osx/build/opt/salt/bin/python3 -m pip list
Package    Version
---------- -------
pip        22.3.1
relenv     0.4.9
setuptools 65.5.0
wheel      0.38.4

Most/all of the bundled libraries are somewhat/significantly out-of-date

Looking through the long list of bundled dependencies, I'm slightly concerned about how old some of the software releases are, especially given that the whole point of this tool is to have zero dependencies. Some are somewhat unimportant/irrelevant, but others like libssl and python are frankly quite important

Looking through the bundled software (for Linux at least; it's the only platform that interests me) here https://github.com/saltstack/relative-environment-for-python/blob/b848c6f7cf7a36587935db349c42e89e0fb0e5b6/relenv/build/linux.py#L353

Package Relenv version Latest version Notes
glibc 2.17 2.36 This was released 2012-12-25 so is over 10 years old. I don't think there's really any excuse for this one
libssl 1.1.1q 3.0.7 (or at least the latest security patch: 1.1.1s) OpenSSL is security software, so by definition being behind means it's vulnerable. There's also no reason to not use 3.x here; 1.1.x is not going to be supported forever
python 3.10.6 3.11.1 3.11 has been out only 13 weeks, but there's strong evidence that it has significant performance gains, especially for Salt in some of the ..less performant parts of the code. I've seen 3.11 drop minutes off some highstate times
zlib 1.12.12 1.12.13 1.12.13 fixes a couple of CVEs in 1.12.12. Not critical, but still security related

From what I can see, this doesn't even have the excuse of "it was latest when we started" because many of these "latest" versions even predate the initial commit of this data: b48d9ca

I would consider these issues above significant enough to not consider using relenv-based Salt packages until these have been addressed. To me, the whole (and only) reason to go to all of the effort to build what is effectively an isolated system of libraries (like you would in a container) like this is to be able to break away from the grasp of "stable" distributions with old versions and to be able to use new features, bug/security fixes and performance enhancements. Instead, what relenv provides currently is a liability to fork, build and maintain newer versions of libraries to stay secure, but no perceivable benefits for the user

Not compatible with VSCode debug protocol adapter

Salt 3006.5, Ubuntu 22.04:

salt-pip install debugpy
/opt/saltstack/salt/bin/python3 -c 'import debugpy; debugpy.listen(5678); debugpy.wait_for_client()'
0.69s - Error patching args (debugger not attached to subprocess).

Traceback (most recent call last):
  File "/opt/saltstack/salt/extras-3.10/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py", line 526, in patch_args
    host, port = _get_host_port()
  File "/opt/saltstack/salt/extras-3.10/debugpy/_vendored/pydevd/_pydev_bundle/pydev_monkey.py", line 212, in _get_host_port
    host, port = pydevd.dispatch()
  File "/opt/saltstack/salt/extras-3.10/debugpy/_vendored/pydevd/pydevd.py", line 3084, in dispatch
    host = setup['client']
TypeError: 'NoneType' object is not subscriptable

The same command works with system Python binary.

Mac build linking against /usr/local

We discovered this when using the pre-built macos python build to make the Salt Mac package. It seems we're linking to gettext in /usr/local for some reason. When installing salt into the environment we get the following traceback.

dyld: Library not loaded: /usr/local/opt/gettext/lib/libintl.8.dylib
  Referenced from: /Users/saltadmin/src/salt/pkg/osx/build/opt/salt/bin/python3
  Reason: image not found
/Users/saltadmin/src/salt/pkg/osx/install_salt.sh: line 102:   968 Abort trap: 6   

Everything works when using relenv build to build the python on the macos box where this was tested.

Build libcurl against correct glibc

Installing Pycurl needs a libcurl that is compiled against the proper glibc version. Document the process of building libcurl to work with relenv.

[Feature Request] Build Environment Build Customization

Firstly, I've been watching relenv for a while - I think it's rad. Great work 😎

I would like to add support for customizing the build environment (e.g. what's created with relenv build). Specifically:

  • Custom [Cc]onfigure flags for CPython, OpenSSL, SQLite, etc.
  • Custom CFLAGS / LDFLAGS / CXXFLAGS
  • Other Custom environment variables (e.g. MACOSX_DEPLOYMENT_TARGET)
  • Make flags
  • Customization of source tarballs (Download URL's, Versions, Checksums)

Although my primary focus is on macOS (as I support my Company's fleet of macOS devices, including its use of Salt), I think customization would be valuable for all platforms.

As a good example, take issue #114, where the default /usr/bin/python3 executable is hard-coded in relenv, and is actually immutable on macOS (due to System Integrity Protection), but can "point" to different Xcode environments (via xcode-select).

If I wanted to use zlib or libzmq from Homebrew (instead of building it myself), currently relenv doesn't allow me to do that.

I want to be able use a different Python version (e.g. a pre-release version, 3.9.x, or any other version not specifically hard-coded into relenv.

relocate fails on cross compiled builds

relocate is not setting rpath properly on cross compiled builds. The root of the problem seems to be the cross toolchain's ldd is not returning the expected output.

Add introspection

There should be a way to detect if the python being used is a relenv onedir or not.

Checking if relenv is installed is not enough. Relenv can be installed into python environments to bootstrap onedir environments, in fact, that's how relenv works.

So, how can we detect?

Python has built-in support for frozen(sys.frozen). PyInstaller uses sys.MEIPASS.

Set sys.relenv = True when relenv is bootstrapped at runtime?

Relenv breaks virtualenvs (At least in FIPS enabled systems)

Using the system python

No virtualenv:

Python 3.11.0 (main, Sep 12 2023, 18:26:57) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.md5()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines] unsupported
>>> hashlib.sha256()
<sha256 _hashlib.HASH object @ 0x7f030577b7d0>
>>>

Virtualenv created using the system python:

root@ip-10-2-3-37 [ ~ ]# python3 -m virtualenv /tmp/ve1
created virtual environment CPython3.11.0.final.0-64 in 346ms
  creator CPython3Posix(dest=/tmp/ve1, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
    added seed packages: pip==23.2.1, setuptools==68.2.2, wheel==0.41.2
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
root@ip-10-2-3-37 [ ~ ]# source /tmp/ve1/bin/activate
(ve1) root@ip-10-2-3-37 [ ~ ]# python
Python 3.11.0 (main, Sep 12 2023, 18:26:57) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.md5()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines] unsupported
>>> hashlib.sha256()
<sha256 _hashlib.HASH object @ 0x7f4c324e6670>
>>>

Now using relenv

No virtualenv

root@ip-10-2-3-37 [ ~ ]# /tmp/testing/artifacts/salt/bin/python3
Python 3.10.13 (main, Sep  9 2023, 07:21:14) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.md5()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines] unsupported
>>> hashlib.sha256()
<sha256 _hashlib.HASH object @ 0x7f0b18d01d50>
>>>

A virtualenv using relenv

root@ip-10-2-3-37 [ ~ ]# /tmp/testing/artifacts/salt/bin/python3 -m pip install virtualenv
Collecting virtualenv
  Downloading virtualenv-20.24.5-py3-none-any.whl (3.7 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.7/3.7 MB 14.6 MB/s eta 0:00:00
Collecting filelock<4,>=3.12.2
  Downloading filelock-3.12.4-py3-none-any.whl (11 kB)
Collecting platformdirs<4,>=3.9.1
  Downloading platformdirs-3.11.0-py3-none-any.whl (17 kB)
Collecting distlib<1,>=0.3.7
  Downloading distlib-0.3.7-py2.py3-none-any.whl (468 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 468.9/468.9 kB 30.3 MB/s eta 0:00:00
Installing collected packages: distlib, platformdirs, filelock, virtualenv
Successfully installed distlib-0.3.7 filelock-3.12.4 platformdirs-3.11.0 virtualenv-20.24.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

[notice] A new release of pip available: 22.3.1 -> 23.3.1
[notice] To update, run: /tmp/testing/artifacts/salt/bin/python3 -m pip install --upgrade pip
root@ip-10-2-3-37 [ ~ ]# /tmp/testing/artifacts/salt/bin/python3 -m virtualenv /tmp/ve2
created virtual environment CPython3.10.13.final.0-64 in 314ms
  creator CPython3Posix(dest=/tmp/ve2, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
    added seed packages: pip==23.2.1, setuptools==68.2.2, wheel==0.41.2
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
root@ip-10-2-3-37 [ ~ ]# source /tmp/ve2/bin/activate
(ve2) root@ip-10-2-3-37 [ ~ ]# python
Python 3.10.13 (main, Sep  9 2023, 07:21:14) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.md5()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines] unsupported
>>> hashlib.sha256()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines] unsupported
>>>

Refs saltstack/salt#65444

Setting OPENSSL_MODULES breaks non-Salt tooling that uses OpenSSL

The 3006.2 release of Salt introduced a new version of relenv, which added code to runtime.py that sets OPENSSL_MODULES. It also added openssl modules to the relenv. However, this transparent environment mangling breaks (at least some) non-Salt tooling that uses OpenSSL.

For example, when using Salt to manage maas, we utilize a cmd.script state to run several shell commands that initialize a new maas instance, configure TLS, etc. With the latest changes to relenv released with Salt 3006.2, OPENSSL_MODULES is pointed at the OpenSSL within the relenv, and any commands that Salt runs inherit this modified environment. This means that, when Salt runs maas CLI commands, the maas CLI tools try (and fail) to load legacy.so, resulting in a cryptic OpenSSL error.

I was able to work around this by manually unsetting OPENSSL_MODULES in the shell script, but other tools are likely to be similarly affected.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.