From 7f48fa01295e85f94437041688fb898e870c5154 Mon Sep 17 00:00:00 2001 From: Dmitriy Rabotyagov Date: Tue, 2 May 2023 09:52:11 +0200 Subject: [PATCH] Better parse virtualenv_command option for pip (#80624) Atthe moment if a users wants to protect virtualenv_command by using quotes around 'venv', module will fail out as literal parsing is used at the moment. In order to imrpove things, argparse is leveraged to parse out passed value to the virtualenv_command Closes-Bug: #76372 Signed-off-by: Dmitriy Rabotyagov --- ...372-fix-pip-virtualenv-command-parsing.yml | 6 +++++ lib/ansible/modules/pip.py | 15 ++++++++++++- test/integration/targets/pip/tasks/pip.yml | 22 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/76372-fix-pip-virtualenv-command-parsing.yml diff --git a/changelogs/fragments/76372-fix-pip-virtualenv-command-parsing.yml b/changelogs/fragments/76372-fix-pip-virtualenv-command-parsing.yml new file mode 100644 index 00000000000..96cd8b646aa --- /dev/null +++ b/changelogs/fragments/76372-fix-pip-virtualenv-command-parsing.yml @@ -0,0 +1,6 @@ +--- +bugfixes: + - >- + Fixed `pip` module failure in case of usage quotes for + `virtualenv_command` option for the venv command. + (https://github.com/ansible/ansible/issues/76372) diff --git a/lib/ansible/modules/pip.py b/lib/ansible/modules/pip.py index 15c8c4420aa..a77d2fdabd0 100644 --- a/lib/ansible/modules/pip.py +++ b/lib/ansible/modules/pip.py @@ -264,6 +264,7 @@ virtualenv: sample: "/tmp/virtualenv" ''' +import argparse import os import re import sys @@ -306,6 +307,18 @@ def _is_vcs_url(name): return re.match(_VCS_RE, name) +def _is_venv_command(command): + venv_parser = argparse.ArgumentParser() + venv_parser.add_argument('-m', type=str) + argv = shlex.split(command) + if argv[0] == 'pyvenv': + return True + args, dummy = venv_parser.parse_known_args(argv[1:]) + if args.m == 'venv': + return True + return False + + def _is_package_name(name): """Test whether the name is a package name or a version specifier.""" return not name.lstrip().startswith(tuple(op_dict.keys())) @@ -540,7 +553,7 @@ def setup_virtualenv(module, env, chdir, out, err): virtualenv_python = module.params['virtualenv_python'] # -p is a virtualenv option, not compatible with pyenv or venv # this conditional validates if the command being used is not any of them - if not any(ex in module.params['virtualenv_command'] for ex in ('pyvenv', '-m venv')): + if not _is_venv_command(module.params['virtualenv_command']): if virtualenv_python: cmd.append('-p%s' % virtualenv_python) elif PY3: diff --git a/test/integration/targets/pip/tasks/pip.yml b/test/integration/targets/pip/tasks/pip.yml index 39480614ab5..9f1034d29a9 100644 --- a/test/integration/targets/pip/tasks/pip.yml +++ b/test/integration/targets/pip/tasks/pip.yml @@ -568,6 +568,28 @@ that: - "version13 is success" +- name: Test virtualenv command with venv formatting + when: ansible_python.version.major > 2 + block: + - name: Clean up the virtualenv + file: + state: absent + name: "{{ remote_tmp_dir }}/pipenv" + + # ref: https://github.com/ansible/ansible/issues/76372 + - name: install using different venv formatting + pip: + name: "{{ pip_test_package }}" + virtualenv: "{{ remote_tmp_dir }}/pipenv" + virtualenv_command: "{{ ansible_python_interpreter ~ ' -mvenv' }}" + state: present + register: version14 + + - name: ensure install using virtualenv_command with venv formatting + assert: + that: + - "version14 is changed" + ### test virtualenv_command end ### # https://github.com/ansible/ansible/issues/68592