diff --git a/.ci/ansible_install.py b/.ci/ansible_install.py
index 900303f6..3b217ff2 100755
--- a/.ci/ansible_install.py
+++ b/.ci/ansible_install.py
@@ -4,7 +4,7 @@ import ci_lib
batches = [
[
- 'aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws',
+ 'if [ "${TF_BUILD:-false}" = "True" ]; then aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws; fi',
]
]
diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml
index 51908e92..a3ffa9b4 100644
--- a/.ci/azure-pipelines.yml
+++ b/.ci/azure-pipelines.yml
@@ -32,10 +32,14 @@ jobs:
tox.env: py312-mode_localhost-ansible9
Van_312_9:
tox.env: py312-mode_localhost-ansible9-strategy_linear
+ Loc_312_10:
+ tox.env: py312-mode_localhost-ansible10
+ Van_312_10:
+ tox.env: py312-mode_localhost-ansible10-strategy_linear
- job: Linux
pool:
- # https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2004-Readme.md
+ # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2004-Readme.md
vmImage: ubuntu-20.04
steps:
- template: azure-pipelines-steps.yml
@@ -152,3 +156,6 @@ jobs:
Ans_312_9:
python.version: '3.12'
tox.env: py312-mode_ansible-ansible9
+ Ans_312_10:
+ python.version: '3.12'
+ tox.env: py312-mode_ansible-ansible10
diff --git a/.ci/debops_common_install.py b/.ci/debops_common_install.py
index afafe39a..565f9488 100755
--- a/.ci/debops_common_install.py
+++ b/.ci/debops_common_install.py
@@ -10,7 +10,7 @@ ci_lib.run_batches([
'python -m pip --no-python-version-warning --disable-pip-version-check "debops[ansible]==2.1.2"',
],
[
- 'aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws',
+ 'if [ "${TF_BUILD:-false}" = "True" ]; then aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws; fi',
],
])
diff --git a/.ci/mitogen_install.py b/.ci/mitogen_install.py
index b0b1eb14..23ff384b 100755
--- a/.ci/mitogen_install.py
+++ b/.ci/mitogen_install.py
@@ -7,7 +7,7 @@ batches = [
if ci_lib.have_docker():
batches.append([
- 'aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws',
+ 'if [ "${TF_BUILD:-false}" = "True" ]; then aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws; fi',
])
diff --git a/.ci/mitogen_py24_install.py b/.ci/mitogen_py24_install.py
index bd6ecb24..8af90405 100755
--- a/.ci/mitogen_py24_install.py
+++ b/.ci/mitogen_py24_install.py
@@ -4,7 +4,7 @@ import ci_lib
batches = [
[
- 'aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws',
+ 'if [ "${TF_BUILD:-false}" = "True" ]; then aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws; fi',
],
[
'curl https://dw.github.io/mitogen/binaries/ubuntu-python-2.4.6.tar.bz2 | sudo tar -C / -jxv',
diff --git a/ansible_mitogen/loaders.py b/ansible_mitogen/loaders.py
index 9729b8a1..9d9876ac 100644
--- a/ansible_mitogen/loaders.py
+++ b/ansible_mitogen/loaders.py
@@ -49,7 +49,7 @@ __all__ = [
ANSIBLE_VERSION_MIN = (2, 10)
-ANSIBLE_VERSION_MAX = (2, 16)
+ANSIBLE_VERSION_MAX = (2, 17)
NEW_VERSION_MSG = (
"Your Ansible version (%s) is too recent. The most recent version\n"
diff --git a/ansible_mitogen/mixins.py b/ansible_mitogen/mixins.py
index 9cc97a48..0ba41aad 100644
--- a/ansible_mitogen/mixins.py
+++ b/ansible_mitogen/mixins.py
@@ -357,7 +357,9 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
def _execute_module(self, module_name=None, module_args=None, tmp=None,
task_vars=None, persist_files=False,
- delete_remote_tmp=True, wrap_async=False):
+ delete_remote_tmp=True, wrap_async=False,
+ ignore_unknown_opts=False,
+ ):
"""
Collect up a module's execution environment then use it to invoke
target.run_module() or helpers.run_module_async() in the target
@@ -370,7 +372,13 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
if task_vars is None:
task_vars = {}
- self._update_module_args(module_name, module_args, task_vars)
+ if ansible_mitogen.utils.ansible_version[:2] >= (2, 17):
+ self._update_module_args(
+ module_name, module_args, task_vars,
+ ignore_unknown_opts=ignore_unknown_opts,
+ )
+ else:
+ self._update_module_args(module_name, module_args, task_vars)
env = {}
self._compute_environment_string(env)
self._set_temp_file_args(module_args, wrap_async)
diff --git a/ansible_mitogen/planner.py b/ansible_mitogen/planner.py
index 0b1b7aab..0a91039a 100644
--- a/ansible_mitogen/planner.py
+++ b/ansible_mitogen/planner.py
@@ -54,6 +54,7 @@ import mitogen.select
import ansible_mitogen.loaders
import ansible_mitogen.parsing
import ansible_mitogen.target
+import ansible_mitogen.utils.unsafe
LOG = logging.getLogger(__name__)
@@ -215,12 +216,15 @@ class ScriptPlanner(BinaryPlanner):
"""
def _rewrite_interpreter(self, path):
"""
- Given the original interpreter binary extracted from the script's
- interpreter line, look up the associated `ansible_*_interpreter`
- variable, render it and return it.
+ Given the interpreter path (from the script's hashbang line), return
+ the desired interpreter path. This tries, in order
+
+ 1. Look up & render the `ansible_*_interpreter` variable, if set
+ 2. Look up the `discovered_interpreter_*` fact, if present
+ 3. The unmodified path from the hashbang line.
:param str path:
- Absolute UNIX path to original interpreter.
+ Absolute path to original interpreter (e.g. '/usr/bin/python').
:returns:
Shell fragment prefix used to execute the script via "/bin/sh -c".
@@ -228,13 +232,25 @@ class ScriptPlanner(BinaryPlanner):
involved here, the vanilla implementation uses it and that use is
exploited in common playbooks.
"""
- key = u'ansible_%s_interpreter' % os.path.basename(path).strip()
+ interpreter_name = os.path.basename(path).strip()
+ key = u'ansible_%s_interpreter' % interpreter_name
try:
template = self._inv.task_vars[key]
except KeyError:
- return path
+ pass
+ else:
+ configured_interpreter = self._inv.templar.template(template)
+ return ansible_mitogen.utils.unsafe.cast(configured_interpreter)
+
+ key = u'discovered_interpreter_%s' % interpreter_name
+ try:
+ discovered_interpreter = self._inv.task_vars['ansible_facts'][key]
+ except KeyError:
+ pass
+ else:
+ return ansible_mitogen.utils.unsafe.cast(discovered_interpreter)
- return mitogen.utils.cast(self._inv.templar.template(template))
+ return path
def _get_interpreter(self):
path, arg = ansible_mitogen.parsing.parse_hashbang(
@@ -249,7 +265,8 @@ class ScriptPlanner(BinaryPlanner):
if arg:
fragment += ' ' + arg
- return fragment, path.startswith('python')
+ is_python = path.startswith('python')
+ return fragment, is_python
def get_kwargs(self, **kwargs):
interpreter_fragment, is_python = self._get_interpreter()
diff --git a/docs/_templates/ansible.html b/docs/_templates/ansible.html
deleted file mode 100644
index 770e0a45..00000000
--- a/docs/_templates/ansible.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
Mitogen for Ansible (Redirect)
-
-
-
-
diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html
index 97771afa..a01b497f 100644
--- a/docs/_templates/layout.html
+++ b/docs/_templates/layout.html
@@ -14,23 +14,5 @@
{% block footer %}
{{ super() }}
-
-
-
-
-
{% endblock %}
diff --git a/docs/_templates/piwik-config.js b/docs/_templates/piwik-config.js
deleted file mode 100644
index ad24c9f6..00000000
--- a/docs/_templates/piwik-config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-window._paq = [];
-window._paq.push(['trackPageView']);
-window._paq.push(['enableLinkTracking']);
-window._paq.push(['enableHeartBeatTimer', 30]);
-window._paq.push(['setSiteId', 6]);
diff --git a/docs/ansible_detailed.rst b/docs/ansible_detailed.rst
index e6f7b42c..fed347c8 100644
--- a/docs/ansible_detailed.rst
+++ b/docs/ansible_detailed.rst
@@ -75,34 +75,6 @@ Installation
``mitogen_host_pinned`` strategies exists to mimic the ``free`` and
``host_pinned`` strategies.
-4.
-
- .. raw:: html
-
-
-
Demo
~~~~
@@ -165,7 +137,9 @@ Noteworthy Differences
+-----------------+-----------------+
| 8 | 3.9 - 3.12 |
+-----------------+-----------------+
- | 9 | 3.10 - 3.12 |
+ | 9 | |
+ +-----------------+ 3.10 - 3.12 |
+ | 10 | |
+-----------------+-----------------+
Verify your installation is running one of these versions by checking
@@ -271,15 +245,14 @@ Noteworthy Differences
* "Module Replacer" style modules are not supported. These rarely appear in
practice, and light web searches failed to reveal many examples of them.
-..
- * The ``ansible_python_interpreter`` variable is parsed using a restrictive
- :mod:`shell-like ` syntax, permitting values such as ``/usr/bin/env
- FOO=bar python`` or ``source /opt/rh/rh-python36/enable && python``, which
- occur in practice. Jinja2 templating is also supported for complex task-level
- interpreter settings. Ansible `documents this
- `_
- as an absolute path, however the implementation passes it unquoted through
- the shell, permitting arbitrary code to be injected.
+* The ``ansible_python_interpreter`` variable is parsed using a restrictive
+ :mod:`shell-like ` syntax, permitting values such as ``/usr/bin/env
+ FOO=bar python`` or ``source /opt/rh/rh-python36/enable && python``.
+ Jinja2 templating is also supported for complex task-level
+ interpreter settings. Ansible documents `ansible_python_interpreter
+ `_
+ as an absolute path and releases since June 2024 (e.g. Ansible 10.1)
+ reflect this. Older Ansible releases passed it to the shell unquoted.
..
* Configurations will break that rely on the `hashbang argument splitting
@@ -1418,20 +1391,3 @@ Despite the small margin for optimization, Mitogen still manages **6.2x less
bandwidth and 1.8x less time**.
.. image:: images/ansible/pcaps/costapp-uk-india.svg
-
-
-.. raw:: html
-
-
-
diff --git a/docs/changelog.rst b/docs/changelog.rst
index eaffc46c..ce2edf1b 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -18,6 +18,14 @@ To avail of fixes in an unreleased version, please download a ZIP file
`directly from GitHub `_.
+v0.3.9 (2024-08-13)
+-------------------
+
+* :gh:issue:`1097` Respect `ansible_facts.discovered_interpreter_python` when
+ executing non new-style modules (e.g. JSONARGS style, WANT_JSON style).
+* :gh:issue:`1074` Support Ansible 10 (ansible-core 2.17)
+
+
v0.3.8 (2024-07-30)
-------------------
diff --git a/docs/conf.py b/docs/conf.py
index fe1a5044..b7dd1525 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -2,7 +2,7 @@ import sys
sys.path.append('.')
-VERSION = '0.3.8'
+VERSION = '0.3.9'
author = u'Network Genomics'
copyright = u'2021, the Mitogen authors'
@@ -16,7 +16,6 @@ html_show_copyright = False
html_show_sourcelink = False
html_show_sphinx = False
html_sidebars = {'**': ['globaltoc.html', 'github.html']}
-html_additional_pages = {'ansible': 'ansible.html'}
html_static_path = ['_static']
html_theme = 'alabaster'
html_theme_options = {
diff --git a/mitogen/__init__.py b/mitogen/__init__.py
index 8f2741c7..b0c66793 100644
--- a/mitogen/__init__.py
+++ b/mitogen/__init__.py
@@ -35,7 +35,7 @@ be expected. On the slave, it is built dynamically during startup.
#: Library version as a tuple.
-__version__ = (0, 3, 8)
+__version__ = (0, 3, 9)
#: This is :data:`False` in slave contexts. Previously it was used to prevent
diff --git a/tests/ansible/hosts/become_same_user.hosts b/tests/ansible/hosts/become_same_user.hosts
index ac744ed7..249246cb 100644
--- a/tests/ansible/hosts/become_same_user.hosts
+++ b/tests/ansible/hosts/become_same_user.hosts
@@ -1,6 +1,9 @@
# code: language=ini
# vim: syntax=dosini
+[become_same_user]
# become_same_user.yml
bsu-joe ansible_user=joe
+[become_same_user:vars]
+ansible_python_interpreter=python3000
diff --git a/tests/ansible/hosts/connection_delegation.hosts b/tests/ansible/hosts/connection_delegation.hosts
index 4ae861b0..7de798a1 100644
--- a/tests/ansible/hosts/connection_delegation.hosts
+++ b/tests/ansible/hosts/connection_delegation.hosts
@@ -4,7 +4,7 @@
# Connection delegation scenarios. It's impossible to connect to them, but their would-be
# config can be inspected using "mitogen_get_stack" action.
-
+[cd]
# Normal inventory host, no aliasing.
cd-normal ansible_connection=mitogen_doas ansible_user=normal-user
@@ -23,6 +23,8 @@ cd-newuser-normal-normal mitogen_via=cd-normal ansible_user=newuser-normal-norma
# doas:newuser via host.
cd-newuser-doas-normal mitogen_via=cd-normal ansible_connection=mitogen_doas ansible_user=newuser-doas-normal-user
+[cd:vars]
+ansible_python_interpreter = python3000
[connection-delegation-test]
cd-bastion
diff --git a/tests/ansible/integration/connection_delegation/delegate_to_template.yml b/tests/ansible/integration/connection_delegation/delegate_to_template.yml
index 0c3f35c2..f9ad9e0b 100644
--- a/tests/ansible/integration/connection_delegation/delegate_to_template.yml
+++ b/tests/ansible/integration/connection_delegation/delegate_to_template.yml
@@ -40,7 +40,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- 'python_path': ["{{ ansible_facts.discovered_interpreter_python | default('/usr/bin/python') }}"],
+ 'python_path': ['python3000'],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -68,7 +68,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- 'python_path': ["{{ ansible_facts.discovered_interpreter_python | default('/usr/bin/python') }}"],
+ 'python_path': ['python3000'],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
diff --git a/tests/ansible/integration/connection_delegation/osa_container_standalone.yml b/tests/ansible/integration/connection_delegation/osa_container_standalone.yml
index 98788d39..df295fd0 100644
--- a/tests/ansible/integration/connection_delegation/osa_container_standalone.yml
+++ b/tests/ansible/integration/connection_delegation/osa_container_standalone.yml
@@ -19,7 +19,7 @@
'kind': 'lxc',
'lxc_info_path': null,
'machinectl_path': null,
- 'python_path': ['/usr/bin/python'],
+ 'python_path': ['python3000'],
'remote_name': null,
'username': null,
},
diff --git a/tests/ansible/integration/connection_delegation/osa_delegate_to_self.yml b/tests/ansible/integration/connection_delegation/osa_delegate_to_self.yml
index f97d1c01..53addbfe 100644
--- a/tests/ansible/integration/connection_delegation/osa_delegate_to_self.yml
+++ b/tests/ansible/integration/connection_delegation/osa_delegate_to_self.yml
@@ -23,7 +23,7 @@
'lxc_info_path': null,
'lxc_path': null,
'machinectl_path': null,
- 'python_path': ["/usr/bin/python"],
+ 'python_path': ["python3000"],
'username': 'ansible-cfg-remote-user',
},
'method': 'setns',
diff --git a/tests/ansible/integration/connection_delegation/stack_construction.yml b/tests/ansible/integration/connection_delegation/stack_construction.yml
index 784d2af2..8cf064bb 100644
--- a/tests/ansible/integration/connection_delegation/stack_construction.yml
+++ b/tests/ansible/integration/connection_delegation/stack_construction.yml
@@ -40,7 +40,7 @@
"connect_timeout": 30,
"doas_path": null,
"password": null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
"username": "normal-user",
},
@@ -73,7 +73,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -115,7 +115,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -150,7 +150,7 @@
'connect_timeout': 30,
'doas_path': null,
'password': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'username': 'normal-user',
},
@@ -168,7 +168,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -210,7 +210,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -238,7 +238,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -272,7 +272,7 @@
'connect_timeout': 30,
'doas_path': null,
'password': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'username': 'normal-user',
},
@@ -290,7 +290,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -333,7 +333,7 @@
'keepalive_count': 10,
'password': null,
'port': null,
- "python_path": ["/usr/bin/python"],
+ "python_path": ["python3000"],
'remote_name': null,
'ssh_args': [
-o, ControlMaster=auto,
@@ -388,7 +388,7 @@
'connect_timeout': 30,
'doas_path': null,
'password': null,
- 'python_path': ["/usr/bin/python"],
+ 'python_path': ["python3000"],
'remote_name': null,
'username': 'normal-user',
},
@@ -399,7 +399,7 @@
'connect_timeout': 30,
'doas_path': null,
'password': null,
- 'python_path': ["/usr/bin/python"],
+ 'python_path': ["python3000"],
'remote_name': null,
'username': 'newuser-doas-normal-user',
},
diff --git a/tests/ansible/integration/interpreter_discovery/ansible_2_8_tests.yml b/tests/ansible/integration/interpreter_discovery/ansible_2_8_tests.yml
index 6ac9bada..0c7d30c9 100644
--- a/tests/ansible/integration/interpreter_discovery/ansible_2_8_tests.yml
+++ b/tests/ansible/integration/interpreter_discovery/ansible_2_8_tests.yml
@@ -4,6 +4,55 @@
- name: integration/interpreter_discovery/ansible_2_8_tests.yml
hosts: test-targets
gather_facts: true
+ vars:
+ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_lt_2_12:
+ centos:
+ '6': /usr/bin/python
+ '7': /usr/bin/python
+ '8': /usr/libexec/platform-python
+ debian:
+ '9': /usr/bin/python
+ '10': /usr/bin/python3
+ '11': /usr/bin/python
+ 'NA': /usr/bin/python # Debian 11, Ansible <= 7 (ansible-core <= 2.14)
+ 'bullseye/sid': /usr/bin/python # Debian 11, Ansible 8 - 9 (ansible-core 2.15 - 2.16)
+ ubuntu:
+ '16': /usr/bin/python3
+ '18': /usr/bin/python3
+ '20': /usr/bin/python3
+
+ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_2_12_to_2_16:
+ centos:
+ '6': /usr/bin/python
+ '7': /usr/bin/python
+ '8': /usr/libexec/platform-python
+ debian:
+ '9': /usr/bin/python
+ '10': /usr/bin/python3
+ '11': /usr/bin/python3.9
+ 'NA': /usr/bin/python3.9 # Debian 11, Ansible <= 7 (ansible-core <= 2.14)
+ 'bullseye/sid': /usr/bin/python3.9 # Debian 11, Ansible 8 - 9 (ansible-core 2.15 - 2.16)
+ ubuntu:
+ '16': /usr/bin/python3
+ '18': /usr/bin/python3
+ '20': /usr/bin/python3
+
+ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_ge_2_17:
+ debian:
+ '10': /usr/bin/python3.7
+ '11': /usr/bin/python3.9
+ 'bullseye/sid': /usr/bin/python3.9
+ ubuntu:
+ '20': /usr/bin/python3.8
+
+ discovered_interpreter_expected: >-
+ {%- if ansible_version.full is version('2.12', '<', strict=True) -%}
+ {{ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_lt_2_12[distro][distro_major] }}
+ {%- elif ansible_version.full is version('2.17', '<', strict=True) -%}
+ {{ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_2_12_to_2_16[distro][distro_major] }}
+ {%- else -%}
+ {{ DISCOVERED_INTERPRETER_EXPECTED_MAP__ANSIBLE_ge_2_17[distro][distro_major] }}
+ {%- endif -%}
tasks:
- name: can only run these tests on ansible >= 2.8.0
block:
@@ -18,9 +67,9 @@
- name: snag some facts to validate for later
set_fact:
- distro: '{{ ansible_distribution | default("unknown") | lower }}'
- distro_version: '{{ ansible_distribution_version | default("unknown") }}'
- os_family: '{{ ansible_os_family | default("unknown") }}'
+ distro: '{{ ansible_facts.distribution | lower }}'
+ distro_major: '{{ ansible_facts.distribution_major_version }}'
+ system: '{{ ansible_facts.system }}'
- name: test that python discovery is working and that fact persistence makes it only run once
block:
@@ -159,50 +208,19 @@
- ansible_facts['ansible_bogus_interpreter'] | default('nope') == 'nope'
- ansible_facts['discovered_interpreter_bogus'] | default('nope') == 'nope'
- - name: fedora assertions
+ - name: Check discovered interpreter matches expected
assert:
that:
- - auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3'
- fail_msg: auto_out={{auto_out}}
+ - auto_out.ansible_facts.discovered_interpreter_python == discovered_interpreter_expected
+ fail_msg: >-
+ distro={{ distro }}
+ distro_major= {{ distro_major }}
+ system={{ system }}
+ auto_out={{ auto_out }}
+ discovered_interpreter_expected={{ discovered_interpreter_expected }}
+ ansible_version.full={{ ansible_version.full }}
when:
- - distro == 'fedora'
- - distro_version is version('23.0', '>=', strict=True)
-
- - name: rhel < 8 assertions
- assert:
- that:
- - auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python'
- fail_msg: auto_out={{auto_out}}
- when:
- - distro in ('redhat', 'centos')
- - distro_version is version('8.0', '<', strict=true)
-
- - name: rhel 8+ assertions
- assert:
- that:
- - auto_out.ansible_facts.discovered_interpreter_python == '/usr/libexec/platform-python'
- fail_msg: auto_out={{auto_out}}
- when:
- - distro in ('redhat', 'centos')
- - distro_version is version('8.0', '>=', strict=true)
-
- - name: ubuntu < 16.04 assertions
- assert:
- that:
- - auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python'
- fail_msg: auto_out={{auto_out}}
- when:
- - distro == 'ubuntu'
- - distro_version is version('16.04', '<', strict=true)
-
- - name: ubuntu 16.04+ assertions
- assert:
- that:
- - auto_out.ansible_facts.discovered_interpreter_python == '/usr/bin/python3'
- fail_msg: auto_out={{auto_out}}
- when:
- - distro == 'ubuntu'
- - distro_version is version('16.04', '>=', strict=True)
+ - system in ['Linux']
always:
- meta: clear_facts
diff --git a/tests/ansible/integration/interpreter_discovery/complex_args.yml b/tests/ansible/integration/interpreter_discovery/complex_args.yml
index a3755ebf..af2b5e46 100644
--- a/tests/ansible/integration/interpreter_discovery/complex_args.yml
+++ b/tests/ansible/integration/interpreter_discovery/complex_args.yml
@@ -9,6 +9,13 @@
https_proxy: "{{ lookup('env', 'https_proxy') | default(omit) }}"
no_proxy: "{{ lookup('env', 'no_proxy') | default(omit) }}"
tasks:
+ # Ansible releases after June 2024 quote ansible_python_interpreter
+ # https://github.com/ansible/ansible/pull/83365
+ - meta: end_play
+ when:
+ - not is_mitogen
+ - ansible_version.full is version('2.17.1', '>=', strict=True)
+
- name: create temp file to source
file:
path: /tmp/fake
@@ -25,8 +32,7 @@
# special_python: source /tmp/fake && python
- name: set python using sourced file
set_fact:
- # Avoid 2.x vs 3.x cross-compatiblity issues (that I can't remember the exact details of).
- special_python: "source /tmp/fake || true && python{{ ansible_facts.python.version.major }}"
+ special_python: "source /tmp/fake || true && {{ ansible_facts.python.executable }}"
- name: run get_url with specially-sourced python
uri:
diff --git a/tests/ansible/integration/module_utils/adjacent_to_role.yml b/tests/ansible/integration/module_utils/adjacent_to_role.yml
index c4fb813f..93499790 100644
--- a/tests/ansible/integration/module_utils/adjacent_to_role.yml
+++ b/tests/ansible/integration/module_utils/adjacent_to_role.yml
@@ -1,7 +1,7 @@
# external2 is loaded from config path.
# external1 is loaded from integration/module_utils/roles/modrole/module_utils/..
-- name: integration/module_utils/adjacent_to_playbook.yml
+- name: integration/module_utils/adjacent_to_role.yml
hosts: test-targets
roles:
- modrole
diff --git a/tests/ansible/integration/module_utils/roles/modrole/library/uses_external3.py b/tests/ansible/integration/module_utils/roles/modrole/library/uses_external3.py
index faf8a9a5..78f2d71d 100644
--- a/tests/ansible/integration/module_utils/roles/modrole/library/uses_external3.py
+++ b/tests/ansible/integration/module_utils/roles/modrole/library/uses_external3.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils import external3
diff --git a/tests/ansible/integration/module_utils/roles/overrides_modrole/library/uses_custom_known_hosts.py b/tests/ansible/integration/module_utils/roles/overrides_modrole/library/uses_custom_known_hosts.py
index 4fc4e04c..688fc45a 100644
--- a/tests/ansible/integration/module_utils/roles/overrides_modrole/library/uses_custom_known_hosts.py
+++ b/tests/ansible/integration/module_utils/roles/overrides_modrole/library/uses_custom_known_hosts.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
import json
import ansible.module_utils.basic
diff --git a/tests/ansible/integration/runner/custom_bash_hashbang_argument.yml b/tests/ansible/integration/runner/custom_bash_hashbang_argument.yml
index ebb7966e..82535d56 100644
--- a/tests/ansible/integration/runner/custom_bash_hashbang_argument.yml
+++ b/tests/ansible/integration/runner/custom_bash_hashbang_argument.yml
@@ -2,6 +2,12 @@
- name: integration/runner/custom_bash_hashbang_argument.yml
hosts: test-targets
tasks:
+ # Ansible releases after June 2024 quote ansible_python_interpreter
+ # https://github.com/ansible/ansible/pull/83365
+ - meta: end_play
+ when:
+ - not is_mitogen
+ - ansible_version.full is version('2.17.1', '>=', strict=True)
- custom_bash_old_style_module:
foo: true
diff --git a/tests/ansible/integration/stub_connections/kubectl.yml b/tests/ansible/integration/stub_connections/kubectl.yml
index e3e927c0..13e522d2 100644
--- a/tests/ansible/integration/stub_connections/kubectl.yml
+++ b/tests/ansible/integration/stub_connections/kubectl.yml
@@ -12,7 +12,6 @@
- custom_python_detect_environment:
vars:
ansible_connection: kubectl
- ansible_python_interpreter: python # avoid Travis virtualenv breakage
mitogen_kubectl_path: stub-kubectl.py
register: out
diff --git a/tests/ansible/integration/stub_connections/lxc.yml b/tests/ansible/integration/stub_connections/lxc.yml
index ae71a603..3f1a2282 100644
--- a/tests/ansible/integration/stub_connections/lxc.yml
+++ b/tests/ansible/integration/stub_connections/lxc.yml
@@ -8,7 +8,6 @@
- custom_python_detect_environment:
vars:
ansible_connection: lxc
- ansible_python_interpreter: python # avoid Travis virtualenv breakage
mitogen_lxc_attach_path: stub-lxc-attach.py
register: out
diff --git a/tests/ansible/integration/stub_connections/lxd.yml b/tests/ansible/integration/stub_connections/lxd.yml
index a2f8f80a..fd811fb7 100644
--- a/tests/ansible/integration/stub_connections/lxd.yml
+++ b/tests/ansible/integration/stub_connections/lxd.yml
@@ -8,7 +8,6 @@
- custom_python_detect_environment:
vars:
ansible_connection: lxd
- ansible_python_interpreter: python # avoid Travis virtualenv breakage
mitogen_lxc_path: stub-lxc.py
register: out
diff --git a/tests/ansible/integration/stub_connections/mitogen_doas.yml b/tests/ansible/integration/stub_connections/mitogen_doas.yml
index 338bc09b..a8b77edd 100644
--- a/tests/ansible/integration/stub_connections/mitogen_doas.yml
+++ b/tests/ansible/integration/stub_connections/mitogen_doas.yml
@@ -8,7 +8,6 @@
- custom_python_detect_environment:
vars:
ansible_connection: mitogen_doas
- ansible_python_interpreter: python # avoid Travis virtualenv breakage
ansible_doas_exe: stub-doas.py
ansible_user: someuser
register: out
diff --git a/tests/ansible/integration/stub_connections/mitogen_sudo.yml b/tests/ansible/integration/stub_connections/mitogen_sudo.yml
index 0ab18f3b..bcf0f22f 100644
--- a/tests/ansible/integration/stub_connections/mitogen_sudo.yml
+++ b/tests/ansible/integration/stub_connections/mitogen_sudo.yml
@@ -8,7 +8,6 @@
- custom_python_detect_environment:
vars:
ansible_connection: mitogen_sudo
- ansible_python_interpreter: python # avoid Travis virtualenv breakage
ansible_user: root
ansible_become_exe: stub-sudo.py
ansible_become_flags: -H --type=sometype --role=somerole
diff --git a/tests/ansible/integration/transport_config/python_path.yml b/tests/ansible/integration/transport_config/python_path.yml
index 0f04ed59..ecc24374 100644
--- a/tests/ansible/integration/transport_config/python_path.yml
+++ b/tests/ansible/integration/transport_config/python_path.yml
@@ -2,12 +2,17 @@
# Each case is followed by mitogen_via= case to test hostvars method.
-# When no ansible_python_interpreter is set, ansible 2.8+ automatically
-# tries to detect the desired interpreter, falling back to "/usr/bin/python" if necessary
+# If ansible_python_interpreter isn't set, Ansible 2.8+ tries to connect and
+# detect the interpreter. If that fails (e.g. connection timeout)
+# - Ansible 2.8 - 9 (ansible-core 2.8 - 2.16) assumes "/usr/bin/python"
+# - Ansible 10+ (ansible-core 2.17+) marks the target unreachable
- name: integration/transport_config/python_path.yml
hosts: tc-python-path-unset
tasks:
- include_tasks: ../_mitogen_only.yml
+ - meta: end_play
+ when:
+ - ansible_version.full is version('2.17', '>=', strict=True)
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
@@ -19,6 +24,9 @@
vars: {mitogen_via: tc-python-path-unset}
tasks:
- include_tasks: ../_mitogen_only.yml
+ - meta: end_play
+ when:
+ - ansible_version.full is version('2.17', '>=', strict=True)
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
@@ -45,6 +53,9 @@
vars: {mitogen_via: tc-python-path-hostvar}
tasks:
- include_tasks: ../_mitogen_only.yml
+ - meta: end_play
+ when:
+ - ansible_version.full is version('2.17', '>=', strict=True)
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
@@ -71,6 +82,9 @@
vars: {mitogen_via: localhost}
tasks:
- include_tasks: ../_mitogen_only.yml
+ - meta: end_play
+ when:
+ - ansible_version.full is version('2.17', '>=', strict=True)
- {mitogen_get_stack: {}, register: out}
- assert_equal:
left: out.result[0].kwargs.python_path
diff --git a/tests/ansible/lib/modules/custom_python_json_args_module.py b/tests/ansible/lib/modules/custom_python_json_args_module.py
index 61640579..846037ec 100755
--- a/tests/ansible/lib/modules/custom_python_json_args_module.py
+++ b/tests/ansible/lib/modules/custom_python_json_args_module.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
# I am an Ansible Python JSONARGS module. I should receive an encoding string.
json_arguments = """<>"""
diff --git a/tests/ansible/lib/modules/custom_python_os_getcwd.py b/tests/ansible/lib/modules/custom_python_os_getcwd.py
index c5e264ae..d465ac9e 100644
--- a/tests/ansible/lib/modules/custom_python_os_getcwd.py
+++ b/tests/ansible/lib/modules/custom_python_os_getcwd.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
# #591: call os.getcwd() before AnsibleModule ever gets a chance to fix up the
# process environment.
diff --git a/tests/ansible/lib/modules/custom_python_want_json_module.py b/tests/ansible/lib/modules/custom_python_want_json_module.py
index f5e33862..23eeeb55 100755
--- a/tests/ansible/lib/modules/custom_python_want_json_module.py
+++ b/tests/ansible/lib/modules/custom_python_want_json_module.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
# I am an Ansible Python WANT_JSON module. I should receive a JSON-encoded file.
import json
diff --git a/tests/ansible/regression/issue_1066__add_host__host_key_checking.yml b/tests/ansible/regression/issue_1066__add_host__host_key_checking.yml
index 4b4609b6..dd754f84 100644
--- a/tests/ansible/regression/issue_1066__add_host__host_key_checking.yml
+++ b/tests/ansible/regression/issue_1066__add_host__host_key_checking.yml
@@ -28,6 +28,10 @@
become: false
serial: 1
tasks:
+ # FIXME https://github.com/mitogen-hq/mitogen/issues/1096
+ - meta: end_play
+ when:
+ - ansible_version.full is version('2.17', '>=', strict=True)
- meta: reset_connection
# The host key might be in ~/.ssh/known_hosts. If it's removed then no
diff --git a/tests/ansible/regression/issue_152__virtualenv_python_fails.yml b/tests/ansible/regression/issue_152__virtualenv_python_fails.yml
index 610eaf33..e0439fdd 100644
--- a/tests/ansible/regression/issue_152__virtualenv_python_fails.yml
+++ b/tests/ansible/regression/issue_152__virtualenv_python_fails.yml
@@ -12,7 +12,9 @@
https_proxy: "{{ lookup('env', 'https_proxy')|default('') }}"
no_proxy: "{{ lookup('env', 'no_proxy')|default('') }}"
PATH: "{{ lookup('env', 'PATH') }}"
- shell: virtualenv /tmp/issue_152_virtualenv
+ command:
+ cmd: virtualenv -p "{{ ansible_facts.python.executable }}" /tmp/issue_152_virtualenv
+ creates: /tmp/issue_152_virtualenv
when:
- lout.python.version.full is version('2.7', '>=', strict=True)
diff --git a/tests/ansible/regression/issue_776__load_plugins_called_twice.yml b/tests/ansible/regression/issue_776__load_plugins_called_twice.yml
index 44ff6863..ef573276 100755
--- a/tests/ansible/regression/issue_776__load_plugins_called_twice.yml
+++ b/tests/ansible/regression/issue_776__load_plugins_called_twice.yml
@@ -3,13 +3,25 @@
- name: regression/issue_776__load_plugins_called_twice.yml
hosts: test-targets
become: "{{ groups.linux is defined and inventory_hostname in groups.linux }}"
- gather_facts: yes
+ # Delayed until after the end_play, due to Python version requirements
+ gather_facts: false
tags:
- issue_776
vars:
ansible_python_interpreter: "{{ pkg_mgr_python_interpreter }}"
package: rsync # Chosen to exist in all tested distros/package managers
tasks:
+ # The package management modules require using the same Python version
+ # as the target's package manager libraries. This is sometimes in conflict
+ # with Ansible requirements, e.g. Ansible 10 (ansible-core 2.17) does not
+ # support Python 2.x on targets.
+ - meta: end_play
+ when:
+ - ansible_version.full is version('2.17', '>=', strict=True)
+
+ - name: Gather facts manually
+ setup:
+
- name: Switch to archived package repositories
copy:
dest: "{{ item.dest }}"
diff --git a/tox.ini b/tox.ini
index a0b0e1ae..08f4c371 100644
--- a/tox.ini
+++ b/tox.ini
@@ -10,9 +10,9 @@
# 2.4 2.3? <= 3.7.1 <= 1.3.7 <= 1.1 <= 2.1.3 <= 1.4 <= 1.8
# 2.5 <= 3.7.1 <= 1.4.22 <= 1.3.1 <= 2.1.3 <= 2.8.7 <= 1.6.1 <= 1.9.1
# 2.6 <= 2.6.20 <= 2.12 <= 4.5.4 <= 1.6.11 <= 2.10.3 <= 9.0.3 <= 5.9.0 <= 3.2.5 <= 2.9.1 <= 15.2.0
-# 2.7 <= 2.11 <= 5.5 <= 1.11.29 <= 2.11.3 <= 20 <= 4.6.11 <= 3.28 <= 20.15²
+# 2.7 <= 2.11 <= 2.16 <= 5.5 <= 1.11.29 <= 2.11.3 <= 20 <= 4.6.11 <= 3.28 <= 20.15²
# 3.5 <= 2.11 <= 2.15 <= 5.5 <= 2.2.28 <= 2.11.3 <= 20 <= 5.9.5 <= 6.1.0 <= 3.28 <= 20.15²
-# 3.6 <= 2.11 <= 6.2 <= 3.2.20 <= 3.0.3 <= 21 <= 7.0.1 <= 3.28 <= 20.17²
+# 3.6 <= 2.11 <= 2.16 <= 6.2 <= 3.2.20 <= 3.0.3 <= 21 <= 7.0.1 <= 3.28 <= 20.17²
# 3.7 <= 2.12 <= 7.2.7 <= 3.2.20 <= 7.4.4 <= 4.8.0
# 3.8 <= 2.12
# 3.9 <= 2.15
@@ -46,18 +46,14 @@
# ansible == 7.x ansible-core ~= 2.14.0
# ansible == 8.x ansible-core ~= 2.15.0
# ansible == 9.x ansible-core ~= 2.16.0
-
-# pip --no-python-version-warning
-# pip --disable-pip-version-check
-
-# TODO distros=-py3
+# ansible == 10.x ansible-core ~= 2.17.0
[tox]
envlist =
init,
py{27,36}-mode_ansible-ansible{2.10,3,4},
py{311}-mode_ansible-ansible{2.10,3,4,5},
- py{312}-mode_ansible-ansible{6,7,8,9},
+ py{312}-mode_ansible-ansible{6,7,8,9,10},
py{27,36,312}-mode_mitogen-distro_centos{6,7,8},
py{27,36,312}-mode_mitogen-distro_debian{9,10,11},
py{27,36,312}-mode_mitogen-distro_ubuntu{1604,1804,2004},
@@ -86,6 +82,7 @@ deps =
ansible7: ansible~=7.0
ansible8: ansible~=8.0
ansible9: ansible~=9.0
+ ansible10: ansible~=10.0
install_command =
python -m pip --no-python-version-warning --disable-pip-version-check install {opts} {packages}
commands_pre =
@@ -104,6 +101,9 @@ passenv =
AWS_DEFAULT_REGION
AWS_SECRET_ACCESS_KEY
HOME
+ # Azure DevOps, TF_BUILD is set to 'True' when running in a build task
+ # https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables
+ TF_BUILD
setenv =
# See also azure-pipelines.yml
ANSIBLE_STRATEGY = mitogen_linear
@@ -126,8 +126,10 @@ setenv =
ansible6: DISTROS=centos7 centos8 debian9 debian10 debian11 ubuntu1604 ubuntu1804 ubuntu2004
ansible7: DISTROS=centos7 centos8 debian9 debian10 debian11 ubuntu1604 ubuntu1804 ubuntu2004
ansible8: DISTROS=centos7 centos8 debian9 debian10 debian11 ubuntu1604 ubuntu1804 ubuntu2004
- # Ansible >= 9 (ansible-core >= 2.16) require Python 2.7 or >= 3.6 on targets
+ # Ansible 9 (ansible-core 2.16) requires Python 2.7 or >= 3.6 on targets
ansible9: DISTROS=centos7 centos8 debian9 debian10 debian11 ubuntu1804 ubuntu2004
+ # Ansible 10 (ansible-core 2.17) requires Python >= 3.7 on targets
+ ansible10: DISTROS=debian10-py3 debian11-py3 ubuntu2004-py3
distros_centos: DISTROS=centos6 centos7 centos8
distros_centos5: DISTROS=centos5
distros_centos6: DISTROS=centos6