`ansible-playbook` (`ansible-core 2.17.1`) fails on target with `python 3.9`

Hi all,

I have an Ansible target machine running Rocky Linux 8 with Python 3.9.19 installed.

[ansible@punch2 ~]$ python3 --version
Python 3.9.19
[ansible@punch2 ~]$ which python3
/usr/bin/python3
[ansible@punch2 ~]$ file $(which python3)
/usr/bin/python3: symbolic link to /etc/alternatives/python3
[ansible@punch2 ~]$ file /etc/alternatives/python3
/etc/alternatives/python3: symbolic link to /usr/bin/python3.9

On my control node I have ansible-core 2.17.1 and python 3.12.4
According to the ansible-core support matrix [1] this should be a working combination.

However, running my playbook fails with

TASK [install rsync] *********************************************************************************************************************
fatal: [punch2]: FAILED! => {"changed": false, "module_stderr": "Shared connection to punch2 closed.\r\n", "module_stdout": "\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 12, in <module>\r\n  File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\r\n  File \"<frozen importlib._bootstrap>\", line 951, in _find_and_load_unlocked\r\n  File \"<frozen importlib._bootstrap>\", line 894, in _find_spec\r\n  File \"<frozen importlib._bootstrap_external>\", line 1157, in find_spec\r\n  File \"<frozen importlib._bootstrap_external>\", line 1131, in _get_spec\r\n  File \"<frozen importlib._bootstrap_external>\", line 1112, in _legacy_get_spec\r\n  File \"<frozen importlib._bootstrap>\", line 441, in spec_from_loader\r\n  File \"<frozen importlib._bootstrap_external>\", line 544, in spec_from_file_location\r\n  File \"/tmp/ansible_ansible.legacy.dnf_payload_7b004s9t/ansible_ansible.legacy.dnf_payload.zip/ansible/module_utils/basic.py\", line 5\r\nSyntaxError: future feature annotations is not defined\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

The affected task is:

    - name: "install rsync"
      ansible.builtin.dnf:
        name: "rsync"
        state: "present"

I thought perhaps ansible uses an incorrect python executable on the target host, but it looks like it uses the correct one:

$ grep -i python /tmp/ansible.log 
            "SUDO_COMMAND": "/bin/sh -c echo BECOME-SUCCESS-zjjlkkwbuieqcjgtuknfnroqnampysct ; /usr/bin/python3.9 /home/ansible/.ansible/tmp/ansible-tmp-1718955443.6279042-120117-145070664808475/AnsiballZ_setup.py",
            "_": "/usr/bin/python3.9"
            "discovered_interpreter_python": "/usr/bin/python3.9",
                "SUDO_COMMAND": "/bin/sh -c echo BECOME-SUCCESS-zjjlkkwbuieqcjgtuknfnroqnampysct ; /usr/bin/python3.9 /home/ansible/.ansible/tmp/ansible-tmp-1718955443.6279042-120117-145070664808475/AnsiballZ_setup.py",
                "_": "/usr/bin/python3.9"
            "python": {
                "executable": "/usr/bin/python3.9",
                "type": "cpython",
            "python_version": "3.9.19",
            "selinux_python_present": true,
        "ansible_playbook_python": "/usr/bin/python",
        "ansible_python": {
            "executable": "/usr/bin/python3.9",
            "type": "cpython",
        "ansible_python_version": "3.9.19",
        "ansible_selinux_python_present": true,
        "discovered_interpreter_python": "/usr/bin/python3.9",

Is this the expected behaviour?

When I downgrade ansible-core on my control node to 2.16.6, the playbook runs normally.

[1] Releases and maintenance — Ansible Community Documentation

You could run the playbook with -vvv to get more info, also which interpreter is actually used for that task.

Control node:

$ ansible-playbook -vvv -i inventory -K punch2/punch2.yml --diff > /tmp/ansiblevvv.log

$ grep -i python /tmp/ansiblevvv.log
  ansible python module location = /usr/lib/python3.12/site-packages/ansible
  python version = 3.12.4 (main, Jun  7 2024, 06:33:07) [GCC 14.1.1 20240522] (/usr/bin/python)
<punch2> Attempting python interpreter discovery
<punch2> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="ansible"' -o ConnectTimeout=10 -o 'ControlPath="[...]"' punch2 '/bin/sh -c '"'"'echo PLATFORM; uname; echo FOUND; command -v '"'"'"'"'"'"'"'"'python3.12'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.11'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.10'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.9'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.8'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3.7'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'/usr/bin/python3'"'"'"'"'"'"'"'"'; command -v '"'"'"'"'"'"'"'"'python3'"'"'"'"'"'"'"'"'; echo ENDFOUND && sleep 0'"'"''
<punch2> (0, b'PLATFORM\nLinux\nFOUND\n/usr/bin/python3.9\n/usr/bin/python3\n/usr/bin/python3\nENDFOUND\n', b"OpenSSH_9.7p1, OpenSSL 3.3.1 4 Jun 2024\r\ndebug1: Reading configuration data
[...]
 "ansible_selinux_python_present": true, "ansible_selinux": {"status": "enabled", "policyvers": 33, "config_mode": "permissive", "mode": "permissive", "type": "targeted"}, "ansible_env": {"LS_COLORS": "rs=0:di=38;5;33:ln=38;5;51:mh=00:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=01;05;37;41:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;40:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.zst=38;5;9:*.tzst=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.wim=38;5;9:*.swm=38;5;9:*.dwm=38;5;9:*.esd=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.mjpg=38;5;13:*.mjpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.m4a=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.oga=38;5;45:*.opus=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:", "LANG": "en_US.UTF-8", "SUDO_GID": "1000", "SUDO_COMMAND": "/bin/sh -c echo BECOME-SUCCESS-javmnmtzucrhyqcgcyucxbreqcmqcogf ; /usr/bin/python3.9 /home/ansible/.ansible/tmp/ansible-tmp-1718966149.599945-164060-177038502487216/AnsiballZ_setup.py", "USER": "root", "PWD": "/home/ansible", "HOME": "/root", "SUDO_USER": "ansible", "SUDO_UID": "1000", "MAIL": "/var/mail/root", "SHELL": "/bin/bash", "TERM": "xterm-256color", "SHLVL": "1", "LOGNAME": "root", "PATH": "/sbin:/bin:/usr/sbin:/usr/bin", "_": "/usr/bin/python3.9"}, "ansible_iscsi_iqn": "", "ansible_dns": {"search": ["gsi.de"], "nameservers": ["140.181.96.11", "140.181.96.29"]}, "ansible_local": {}, "ansible_hostnqn": "nqn.2014-08.org.nvmexpress:uuid:00000000-0000-0000-0000-000000000000", "ansible_python": {"version": {"major": 3, "minor": 9, "micro": 19, "releaselevel": "final", "serial": 0}, "version_info": [3, 9, 19, "final", 0], "executable": "/usr/bin/python3.9", "has_sslcontext": true, "type": "cpython"}, 
[...]
Using module file /usr/lib/python3.12/site-packages/ansible/modules/dnf.py
<punch2> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="ansible"' -o ConnectTimeout=10 -o 'ControlPath="[...]"' -tt punch2 '/bin/sh -c '"'"'sudo -H -S -p "[sudo via ansible, key=tabodqpozselrbxwgvbgexkvfbcgajss] password:" -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-tabodqpozselrbxwgvbgexkvfbcgajss ; /usr/bin/python3.9 /home/ansible/.ansible/tmp/ansible-tmp-1718966151.9287078-164118-26674811716498/AnsiballZ_dnf.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''

Trimmed the output a bit.

It appears to me it tries to use /usr/bin/python3.9.

Dnf is a special module that requires the Python dnf bindings to work. It uses a concept called module respawn that will respawn as the Python interpreter that the bindings it requires is installed on. Unfortunately for EL8 based hosts that will be an older Python version which is not compatible with Ansible 2.17. There’s unfortunately not much you can do about modules like this as they require those Python bindings and those bindings are only available on a limited set of Python versions.

2 Likes

In that case I would argue that the documentation at [1] is incorrect, since it suggests any Python version between 3.7 and 3.12 on the target is sufficient.

Also I would argue that the decision to require a relatively new Python version for a task as trivial as calling an executable (in this case dnf) and parsing its output to be inappropriate.
Implementing this using Python bindings may be a bit more luxurious for the programmer of the ansible module, but at the vast expense of everyone who needs ansible to work on EL8 targets.

4 Likes

Even i am facing the same issue after upgrading the ansible version to 2.17 and remote host python version 3.9.*

may i know how did you downgraded your ansible to 2.16 version? I was not able to find an easy way using brew install

I am unfamiliar with brew.
On Arch, I downgraded ansible-core using $ sudo pacman -U /var/cache/pacman/pkg/ansible-core-2.16.3-1-any.pkg.tar.zst

The thing with EL8 platforms is that they do support Python version 3.7 and up. However, the issue lies in /usr/libexec/platform-python, which is version 3.6.8. There’s been a few blogs about when RHEL8 was released in 2019: What, no Python in Red Hat Enterprise Linux 8? | Red Hat Developer

The reasoning behind it was, having an OS which has to use the same version of Python as it’s main interpreter for 10+ years is not technically feasable (and comes with a myriad of problems, security and otherwise). Let’s instead decouple the “system” python interpreter from the “userland” interpreter (I use these terms loosely here).

And here’s where Ansible 2.17+ breaks: using “system” modules that require platform-python to work. You can run any and all modules on your RHEL8 targets, provided they have a suitable python interpreter, except modules that use “system” python, such as DNF/YUM.

2 Likes

The problem is located in the decision to implement the DNF/YUM ansible modules in the way they are in ansible-core 2.17.

As far as I can tell, and please correct me if I’m wrong here, implementing them through the aforementioned respawn mechanism does not solve any problem. However, it introduces one, quite a considerable one I might add, namely it breaks ansible on EL8 targets. (Other targets might be affected too, I haven’t checked)

Therefore, I consider this a reckless decision and request it to be reverted.

The old DNF/YUM module was working reliably and I do not see why it needed to be changed.

I fully agree with you → Discussion: ansible-core 2.17 removing target support for Python 2.7 and 3.6 · ansible-collections/news-for-maintainers · Discussion #55 · GitHub

1 Like

You are wrong here. The respawn mechanism has no effect on what targets work, it’s just a convenience that removes the necessity for the user to specify which Python interpreter to use for modules that require the system Python.

Before implementation of respawn: if ansible_python_interpreter=/usr/local/bin/python3 and the required libraries are only available on /usr/bin/python3, the module fails. The user must specify ansible_python_interpreter=/usr/bin/python3 to get the task to work.

After implementation of respawn: Regardless of what interpreter the module initially runs under, it detects that the required library is available under/usr/bin/python3 and respawns itself using that interpreter.

In both cases the library requirements are the same and the supported targets are the same. Any modules that do not work under EL8 are because the required libraries are not available for a supported version of Python, not because of the respawn mechanism.

2 Likes

I created an experiment:

I copied all module_utils (except C#/PowerShell; and six, since the collection loader will barf if that’s around somewhere outside ansible.builtin
), doc fragments, and the action plugins/modules related to package modules that do respawning (i.e. apt, apt_repository, dnf, yum) from stable-2.16 to a collection and adjusted the imports, and some more smaller changes (mostly related to how arguments are passed to Python Ansible modules, and new hidden _ansible_* parameters added in ansible-core 2.17).

That way, I hope that respawn also works with Python 2.7 and 3.6, since there should be no syntax errors coming from module utils.

Can someone try GitHub - felixfontein/ansible-py2736compattest (the collection is called felixfontein.py2736compattest) to see whether it works as I hope?

1 Like

(This won’t work if you use package or package_facts, since they have a hard-coded list of package managing modules, or at least they had the last time I checked
)

I’ve run into some issues trying to make it work:

ansible [core 2.17.1]
  config file = None
  configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ansible/.local/share/pipx/venvs/ansible-core-2-17/lib64/python3.12/site-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ansible/.local/bin/ansible
  python version = 3.12.3 (main, Apr 17 2024, 00:00:00) [GCC 14.0.1 20240411 (Red Hat 14.0.1-0)] (/home/ansible/.local/share/pipx/venvs/ansible-core-2-17/bin/python)
  jinja version = 3.1.3
  libyaml = True

The playbook:

---
- name: 'Test compat collection for dnf/yum'
  hosts: 'ansible_controller'
  tasks:
    - name: 'Install bash with compat'
      felixfontein.py2736compattest.dnf:
        name: 'bash'
        state: 'present'
    - name: 'Install bash with normal'
      ansible.builtin.dnf:
        name: 'bash'
        state: 'present'

The error:

TASK [Install bash with compat] ******************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: SyntaxError: future feature annotations is not defined
fatal: [m-a05-01.rh.lab]: FAILED! => changed=false 
  module_stderr: |-
    Shared connection to m-a05-01.rh.lab closed.
  module_stdout: |-
    Traceback (most recent call last):
      File "<stdin>", line 12, in <module>
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 656, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 626, in _load_backward_compatible
      File "/tmp/ansible_felixfontein.py2736compattest.dnf_payload_0pdp6ito/ansible_felixfontein.py2736compattest.dnf_payload.zip/ansible_collections/felixfontein/py2736compattest/plugins/module_utils/basic.py", line 68, in <module>
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 656, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 626, in _load_backward_compatible
      File "/tmp/ansible_felixfontein.py2736compattest.dnf_payload_0pdp6ito/ansible_felixfontein.py2736compattest.dnf_payload.zip/ansible_collections/felixfontein/py2736compattest/plugins/module_utils/compat/selinux.py", line 9, in <module>
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 656, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 626, in _load_backward_compatible
      File "/tmp/ansible_felixfontein.py2736compattest.dnf_payload_0pdp6ito/ansible_felixfontein.py2736compattest.dnf_payload.zip/ansible_collections/felixfontein/py2736compattest/plugins/module_utils/common/text/converters.py", line 12, in <module>
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 951, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 894, in _find_spec
      File "<frozen importlib._bootstrap_external>", line 1157, in find_spec
      File "<frozen importlib._bootstrap_external>", line 1131, in _get_spec
      File "<frozen importlib._bootstrap_external>", line 1112, in _legacy_get_spec
      File "<frozen importlib._bootstrap>", line 441, in spec_from_loader
      File "<frozen importlib._bootstrap_external>", line 544, in spec_from_file_location
      File "/tmp/ansible_felixfontein.py2736compattest.dnf_payload_0pdp6ito/ansible_felixfontein.py2736compattest.dnf_payload.zip/ansible/module_utils/six/__init__.py", line 28
    SyntaxError: future feature annotations is not defined
  msg: |-
    MODULE FAILURE
    See stdout/stderr for the exact error
  rc: 1

I’ll get my hacksaw and try to hack it into working for me :grin:

2 Likes

Hmm, this potentially means that even the six library as included in ansible-core no longer works with Python 3.6. Since ansible-core’s collection loader prevents collections to have their own copy of six, that’s quite a bummer :frowning:

six hasn’t had a new release in +3 years, and supports Python3.3+, so I wouldn’t think six is the root of the problem.

Well, what’s also odd, I find -exec sed <magic>-ed away all import statements mentioning __future__ and it still breaks.

So I checked the AnsiballZ file and grepped for from __future:

[ansible@m-a05-01 debug_dir]$ grep -Er "^from __future"
ansible/module_utils/basic.py:from __future__ import annotations
ansible/module_utils/_text.py:from __future__ import annotations
ansible/module_utils/common/_utils.py:from __future__ import annotations
ansible/module_utils/common/arg_spec.py:from __future__ import annotations
ansible/module_utils/common/file.py:from __future__ import annotations
ansible/module_utils/common/locale.py:from __future__ import annotations
ansible/module_utils/common/parameters.py:from __future__ import annotations
ansible/module_utils/common/collections.py:from __future__ import annotations
ansible/module_utils/common/process.py:from __future__ import annotations
ansible/module_utils/common/sys_info.py:from __future__ import annotations
ansible/module_utils/common/text/converters.py:from __future__ import annotations
ansible/module_utils/common/text/formatters.py:from __future__ import annotations
ansible/module_utils/common/validation.py:from __future__ import annotations
ansible/module_utils/common/warnings.py:from __future__ import annotations
ansible/module_utils/compat/selinux.py:from __future__ import annotations
ansible/module_utils/distro/__init__.py:from __future__ import annotations
ansible/module_utils/distro/_distro.py:from __future__ import annotations
ansible/module_utils/errors.py:from __future__ import annotations
ansible/module_utils/parsing/convert_bool.py:from __future__ import annotations
ansible/module_utils/pycompat24.py:from __future__ import annotations
ansible/module_utils/six/__init__.py:from __future__ import annotations

Which was interesting to say the least. However, it also prompted me to checkout what would happen if I made the same code run with ansible 2.16:

TASK [Install bash with compat] ******************************************************************************
ok: [m-a05-01.rh.lab]

And what kind of future imports are in there you ask?

[ansible@m-a05-01 debug_dir]$ grep -Er "^from __future"
ansible/module_utils/basic.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/_text.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/common/_json_compat.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/_utils.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/arg_spec.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/file.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/common/locale.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/parameters.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/collections.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/process.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/common/sys_info.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/text/converters.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/text/formatters.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/validation.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/common/warnings.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/compat/selectors.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/compat/selinux.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/distro/__init__.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/errors.py:from __future__ import absolute_import, division, print_function
ansible/module_utils/parsing/convert_bool.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/pycompat24.py:from __future__ import (absolute_import, division, print_function)
ansible/module_utils/six/__init__.py:from __future__ import absolute_import

Consider me clueless as to why it doesn’t want to work :sweat_smile:

@Thulium-Drake 2.17 is importing annotations from __future__, which only works with Python 3.9+.

@Denney-tech well six itself didn’t have a change, but the six vendored by ansible-core did have: Require `from __future__ import annotations` (#81902) · ansible/ansible@9f899f9 · GitHub That’s the part that makes the six vendored with ansible-core incompatible with any Python version before 3.9.

1 Like

I pushed a new commit; in that I ‘unrolled’ six (kind of) so now it can be imported from the collection. It might be that not everything of it works, but it works well enough to run the apt module, which I tested with Debian Buster (which by default uses Python 3.7 for python3-apt; I manually compiled Python 3.9 on it so I can access it with ansible-core 2.17, and with the ansible.builtin.apt module I wasn’t able to do anything, but felixfontein.py2736compattest.apt worked as expected :slight_smile:

Unfortunately it is not possible to run quite a few sanity tests on this collection, since they do some dark magic that assumes the functionality fro ansible.module_utils.basic is doing the AnsibleModule setup. I managed to at least get the validate-modules test working, but that broke respawning with unsupported Python versions, so :person_shrugging: I guess for now it has to live without sanity tests


I didn’t mention that earlier, my test system was running RHEL 8 (the control node starting the playbook is running Fedora 40).

When running your latest version of the collection against my RHEL 8 node, it barfed the same error. Guess I’ll stick to using EEs with different versions of Ansible for the forseeable future. Not to downplay the experiment or your work and effort. But I feel that EEs were made for this usecase and it also is more stable.

And if some day something in my playbooks/roles is not compatible anymore with the latest-greatest Ansible as well as 2.16.X, that sounds an awful lot like a problem for future-me :wink: