summaryrefslogtreecommitdiffstats
path: root/lib/ansible/modules/pip.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/modules/pip.py')
-rw-r--r--lib/ansible/modules/pip.py60
1 files changed, 40 insertions, 20 deletions
diff --git a/lib/ansible/modules/pip.py b/lib/ansible/modules/pip.py
index 3a073c8..99ac446 100644
--- a/lib/ansible/modules/pip.py
+++ b/lib/ansible/modules/pip.py
@@ -3,8 +3,7 @@
# Copyright: (c) 2012, Matt Wright <matt@nobien.net>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
+from __future__ import annotations
DOCUMENTATION = '''
@@ -111,6 +110,13 @@ options:
to specify desired umask mode as an octal string, (e.g., "0022").
type: str
version_added: "2.1"
+ break_system_packages:
+ description:
+ - Allow pip to modify an externally-managed Python installation as defined by PEP 668.
+ - This is typically required when installing packages outside a virtual environment on modern systems.
+ type: bool
+ default: false
+ version_added: "2.17"
extends_documentation_fragment:
- action_common_attributes
attributes:
@@ -122,7 +128,7 @@ attributes:
platforms: posix
notes:
- Python installations marked externally-managed (as defined by PEP668) cannot be updated by pip versions >= 23.0.1 without the use of
- a virtual environment or setting the environment variable ``PIP_BREAK_SYSTEM_PACKAGES=1``.
+ a virtual environment or setting the O(break_system_packages) option.
- The virtualenv (U(http://www.virtualenv.org/)) must be
installed on the remote host if the virtualenv parameter is specified and
the virtualenv needs to be created.
@@ -236,6 +242,26 @@ EXAMPLES = '''
name: bottle
umask: "0022"
become: True
+
+- name: Run a module inside a virtual environment
+ block:
+ - name: Ensure the virtual environment exists
+ pip:
+ name: psutil
+ virtualenv: "{{ venv_dir }}"
+ # On Debian-based systems the correct python*-venv package must be installed to use the `venv` module.
+ virtualenv_command: "{{ ansible_python_interpreter }} -m venv"
+
+ - name: Run a module inside the virtual environment
+ wait_for:
+ port: 22
+ vars:
+ # Alternatively, use a block to affect multiple tasks, or use set_fact to affect the remainder of the playbook.
+ ansible_python_interpreter: "{{ venv_python }}"
+
+ vars:
+ venv_dir: /tmp/pick-a-better-venv-path
+ venv_python: "{{ venv_dir }}/bin/python"
'''
RETURN = '''
@@ -298,7 +324,6 @@ except Exception:
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.basic import AnsibleModule, is_executable, missing_required_lib
from ansible.module_utils.common.locale import get_best_parsable_locale
-from ansible.module_utils.six import PY3
#: Python one-liners to be run at the command line that will determine the
@@ -425,15 +450,7 @@ def _is_present(module, req, installed_pkgs, pkg_command):
def _get_pip(module, env=None, executable=None):
- # Older pip only installed under the "/usr/bin/pip" name. Many Linux
- # distros install it there.
- # By default, we try to use pip required for the current python
- # interpreter, so people can use pip to install modules dependencies
- candidate_pip_basenames = ('pip2', 'pip')
- if PY3:
- # pip under python3 installs the "/usr/bin/pip3" name
- candidate_pip_basenames = ('pip3',)
-
+ candidate_pip_basenames = ('pip3',)
pip = None
if executable is not None:
if os.path.isabs(executable):
@@ -574,13 +591,10 @@ def setup_virtualenv(module, env, chdir, out, err):
if not _is_venv_command(module.params['virtualenv_command']):
if virtualenv_python:
cmd.append('-p%s' % virtualenv_python)
- elif PY3:
- # Ubuntu currently has a patch making virtualenv always
- # try to use python2. Since Ubuntu16 works without
- # python2 installed, this is a problem. This code mimics
- # the upstream behaviour of using the python which invoked
- # virtualenv to determine which python is used inside of
- # the virtualenv (when none are specified).
+ else:
+ # This code mimics the upstream behaviour of using the python
+ # which invoked virtualenv to determine which python is used
+ # inside of the virtualenv (when none are specified).
cmd.append('-p%s' % sys.executable)
# if venv or pyvenv are used and virtualenv_python is defined, then
@@ -686,6 +700,7 @@ def main():
chdir=dict(type='path'),
executable=dict(type='path'),
umask=dict(type='str'),
+ break_system_packages=dict(type='bool', default=False),
),
required_one_of=[['name', 'requirements']],
mutually_exclusive=[['name', 'requirements'], ['executable', 'virtualenv']],
@@ -790,6 +805,11 @@ def main():
if extra_args:
cmd.extend(shlex.split(extra_args))
+ if module.params['break_system_packages']:
+ # Using an env var instead of the `--break-system-packages` option, to avoid failing under pip 23.0.0 and earlier.
+ # See: https://github.com/pypa/pip/pull/11780
+ os.environ['PIP_BREAK_SYSTEM_PACKAGES'] = '1'
+
if name:
cmd.extend(to_native(p) for p in packages)
elif requirements: