blob: e28afe6174ad961cc3b8a83313e1b4e778fb46b2 [file] [log] [blame]
Mike Frysinger1ca14432020-02-16 00:18:56 -05001#!/usr/bin/env python3
Aviv Keshet39853bd2016-09-22 15:12:05 -07002# Copyright 2016 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Wrapper around chromite executable scripts that use virtualenv."""
7
Aviv Keshet39853bd2016-09-22 15:12:05 -07008import os
Allen Li465a0d62016-11-30 14:55:08 -08009import subprocess
Aviv Keshet39853bd2016-09-22 15:12:05 -070010import sys
Allen Li465a0d62016-11-30 14:55:08 -080011
Mike Frysinger807d8282022-04-28 22:45:17 -040012
Greg Edelstona4c9b3b2020-01-07 17:51:13 -070013try:
14 import pytest # pylint: disable=import-error
Mike Frysinger1ca14432020-02-16 00:18:56 -050015 wrapper3 = pytest.importorskip('wrapper3', reason='File must be run in venv')
Greg Edelstona4c9b3b2020-01-07 17:51:13 -070016except ImportError:
Mike Frysinger1ca14432020-02-16 00:18:56 -050017 import wrapper3
Aviv Keshet39853bd2016-09-22 15:12:05 -070018
Don Garrett863f90b2017-04-19 17:04:20 -070019_CHROMITE_DIR = os.path.realpath(
20 os.path.join(os.path.abspath(__file__), '..', '..'))
Allen Li9f03f5b2016-12-13 15:23:52 -080021
Allen Li465a0d62016-11-30 14:55:08 -080022# _VIRTUALENV_DIR contains the scripts for working with venvs
Allen Lic5598242016-12-21 11:09:23 -080023_VIRTUALENV_DIR = os.path.join(_CHROMITE_DIR, '..', 'infra_virtualenv')
Mike Frysinger1ca14432020-02-16 00:18:56 -050024_CREATE_VENV_PATH = os.path.join(_VIRTUALENV_DIR, 'bin', 'create_venv3')
Allen Li465a0d62016-11-30 14:55:08 -080025_REQUIREMENTS = os.path.join(_CHROMITE_DIR, 'venv', 'requirements.txt')
26
Allen Li9f03f5b2016-12-13 15:23:52 -080027_VENV_MARKER = 'INSIDE_CHROMITE_VENV'
28
Allen Li465a0d62016-11-30 14:55:08 -080029
30def main():
Allen Li9f03f5b2016-12-13 15:23:52 -080031 if _IsInsideVenv(os.environ):
Mike Frysingera6de8392020-04-15 04:07:41 -040032 # Don't bleed the marker into children processes that might use the wrapper
33 # themselves to run inside of the virtualenv.
34 os.environ.pop(_VENV_MARKER)
Mike Frysinger1ca14432020-02-16 00:18:56 -050035 wrapper3.DoMain()
Allen Li465a0d62016-11-30 14:55:08 -080036 else:
Allen Li68f42e22017-03-27 17:08:59 -070037 venvdir = _CreateVenv()
38 _ExecInVenv(venvdir, sys.argv)
Allen Li465a0d62016-11-30 14:55:08 -080039
40
41def _CreateVenv():
42 """Create or update chromite venv."""
Mike Frysingercbd46ca2020-07-27 07:36:52 -040043 result = subprocess.run(
44 [_CREATE_VENV_PATH, _REQUIREMENTS],
45 check=False, stdout=subprocess.PIPE, encoding='utf-8')
46 if result.returncode:
47 print(f'{os.path.basename(sys.argv[0])}: error: {" ".join(result.args)}: '
48 f'exited {result.returncode}', file=sys.stderr)
49 sys.exit(result.returncode)
50 return result.stdout.strip()
Allen Li465a0d62016-11-30 14:55:08 -080051
52
Allen Li68f42e22017-03-27 17:08:59 -070053def _ExecInVenv(venvdir, args):
Allen Li465a0d62016-11-30 14:55:08 -080054 """Exec command in chromite venv.
55
56 Args:
Allen Li68f42e22017-03-27 17:08:59 -070057 venvdir: virtualenv directory
Allen Li465a0d62016-11-30 14:55:08 -080058 args: Sequence of arguments.
59 """
Allen Li68f42e22017-03-27 17:08:59 -070060 venv_python = os.path.join(venvdir, 'bin', 'python')
Allen Lic5598242016-12-21 11:09:23 -080061 os.execve(
Allen Li68f42e22017-03-27 17:08:59 -070062 venv_python,
63 [venv_python] + list(args),
Allen Lic5598242016-12-21 11:09:23 -080064 _CreateVenvEnvironment(os.environ))
Allen Li465a0d62016-11-30 14:55:08 -080065
66
Allen Li9f03f5b2016-12-13 15:23:52 -080067def _CreateVenvEnvironment(env_dict):
68 """Create environment for a virtualenv.
69
70 This adds a special marker variable to a copy of the input environment dict
71 and returns the copy.
72
73 Args:
74 env_dict: Environment variable dict to use as base, which is not modified.
75
76 Returns:
77 New environment dict for a virtualenv.
78 """
79 new_env_dict = env_dict.copy()
80 new_env_dict[_VENV_MARKER] = '1'
Allen Li82b48402017-03-31 18:33:24 -070081 new_env_dict.pop('PYTHONPATH', None)
Allen Li9f03f5b2016-12-13 15:23:52 -080082 return new_env_dict
83
84
85def _IsInsideVenv(env_dict):
86 """Return whether the environment dict is running inside a virtualenv.
87
88 This checks the environment dict for the special marker added by
89 _CreateVenvEnvironment().
90
91 Args:
92 env_dict: Environment variable dict to check
93
94 Returns:
95 A true value if inside virtualenv, else a false value.
96 """
97 # Checking sys.prefix or doing any kind of path check is unreliable because
98 # we check out chromite to weird places.
99 return env_dict.get(_VENV_MARKER, '')
Aviv Keshet39853bd2016-09-22 15:12:05 -0700100
101
102if __name__ == '__main__':
Allen Li465a0d62016-11-30 14:55:08 -0800103 main()