ansibleyum

Ansible yum throwing future feature annotations is not defined


I have a highly used playbook which has a simple first task: yum, suddently, ever since I've upgraded my MacOSX the yum module stopped working

Example:

- name: Install git
  become: yes
  yum:
    name : git
    state: present

Gives:

>>> print(a['module_stderr'])
OpenSSH_9.7p1, LibreSSL 3.3.6
debug1: /etc/ssh/ssh_config line 21: include /etc/ssh/ssh_config.d/* matched no files
debug1: /etc/ssh/ssh_config line 54: Applying options for *
debug2: resolve_canonicalize: hostname x.x.x.x is address
debug1: Authenticator provider $SSH_SK_PROVIDER did not resolve; disabling
debug1: auto-mux: Trying existing master at '/tmp/ansible-ssh-x.x.x.x-22-mysql'
debug2: fd 3 setting O_NONBLOCK
debug2: mux_client_hello_exchange: master version 4
debug1: mux_client_request_session: master session id: 2
Traceback (most recent call last):
  File "<stdin>", line 12, in <module>
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load                                                                                                                                                                                      rr
Traceback (most recent call last):ap>", line 951, in _find_and_load_unlocked
  File "<stdin>", line 1, in <module>", line 894, in _find_spec
NameError: name 'false' is not defined. Did you mean: 'False'? find_spec
>>> le "<frozen importlib._bootstrap_external>", line 1131, in _get_spec
>>> le "<frozen importlib._bootstrap_external>", line 1112, in _legacy_get_spec
>>> or  File "<frozen Fimportlib._bootstrap>", line 441, in spec_from_loader                                                                                                                                                                              rn
>>> le "<frozen importlib._bootstrap_external>", line 544, in spec_from_file_location
>>> le "/tmp/ansible_ansible.legacy.dnf_payload_c428fwbu/ansible_ansible.legacy.dnf_payload.zip/ansible/module_utils/basic.py", line 5
>>> SyntaxError: future feature annotations is not defined

Anyone has a clue ?


Solution

  • This appears that it could be similar to this issue.

    In that example, the yum / dnf module in Ansible >= 2.17 is said to use a paradigm called "module respawn" which re-spawns a Python interpreter that the bindings it requires are assumed to be installed on. After Ansible connects to a remote host via SSH, it copies python modules to the remote host as zip files "Ansiballz" (a play on words like "tarball"). For the remote host, the python interpreter must meet the requirements of the python code included in the zip file, which contains such module code as yum or dnf modules, originating from the host running Ansible.

    In the example linked issue above, it is mentioned that EL8 based hosts have an older platform-python Python version1 which is not compatible with Ansible 2.17's module code.

    So, since you have not changed the remote hosts and only upgraded MacOS, it may be likely that something locally changed which is being copied over in the "Ansiballz" module code that is now incompatible with the remote host's python interpreter. Presumably changing MacOS version, you will likely have also updated Ansible version via Homebrew?

    If so, try downgrading the version of Ansible you are using on your control host. (e.g. Try Ansible 2.16 instead if using 2.17 as in the example related issue above).

    Also, the following error indicates that false (probably from YAML or JSON's lowercase "false" boolean primitive) is being evaluated in Python interpreter's context:

    NameError: name 'false' is not defined. Did you mean: 'False'? find_spec
    

    It could be that the playbook or module needs to be using False in some place instead of false.


    1Note: The platform-python version on RHEL 8 family systems is older than the other default python interpreters (3.6.8). yum / dnf use /usr/libexec/platform-python, which is that older version. The following explanation is mentioned in the example issue:

    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.

    If this is the case, you may try setting ansible_python_interpreter=/usr/libexec/platform-python just for those specific yum or dnf tasks that require this version:

    - name: Install git
      become: yes
      yum:
        name : git
        state: present
      ## RHEL8 uses separate platform-python 3.6.8 (deprecated in Ansible 2.17+)
      ## See: https://forum.ansible.com/t/ansible-playbook-ansible-core-2-17-1-fails-on-target-with-python-3-9/6700/8
      vars:
        ansible_python_interpreter: /usr/libexec/platform-python
    

    This assumes that the yum module code from your MacOS system's Ansible version is still compatible with platform-python version 3.6.8. If that's not the case, then forcing another version and/or downgrading the macOS Ansible version may help.

    In cases like this, it's best to have avoided the issue entirely by not using macOS's Ansible + Python.framework versions (This also applies to Homebrew, because brew's packages are rolling-release). This introduces change that can break things relying on Ansible's past behavior. I'd recommend creating an Ansible Docker container that is run on macOS (or any system needing to run playbooks). This way, you can ensure you version pin the master Ansible version and avoid upgrade breakage like you're currently observing. Maintaining and updating that Docker image, you'd likely run into the same issues, but you could at least solve them on your own project timeframe as hosts get upgraded.