pythonansible

ansible_python_interpreter_fallback is not working


I have a playbook with a mix of connection: local tasks and remote tasks that use an AWS dynamic inventory. The Python interpreter has different paths on local and remote systems.

Through another question python3 venv - how to sync ansible_python_interpreter for playbooks that mix connection:local and target system, I have determined I should use ansible_python_interpreter_fallback to configure two Python interpreter paths to try. But I cannot get them working.

I have tried:

Defining it in my playbook:

---

- hosts: tag_group_web_servers
  vars_files:
    - group_vars/au
  roles:
    - autodeploy
  vars:
    ansible_python_interpreter_fallback:
      - /Users/jd/projects/mgr2/ansible/bin/python3
      - /usr/bin/python3

, which is ignored

And defining it in the dynamic inventory:

plugin: aws_ec2
regions:
  - ap-southeast-2
  - us-east-1
hostnames:
  - ip-address
keyed_groups:
  - prefix: "tag"
    key: tags
  - prefix: "group"
    key: tags
  - prefix: "security_groups"
    key: 'security_groups|json_query("[].group_name")'
all:
  hosts:
    127.0.0.1:
      ansible_connection: local
      ansible_python_interpreter: "/Users/jd/projects/mgr2/ansible/bin/python3"
    remote:
      ansible_host: remote.host.ip
      ansible_python_interpreter: /usr/bin/python3
ansible_python_interpreter_fallback:
  - /Users/jd/projects/mgr2/ansible/bin/python3
  - /usr/bin/python3

, which is also ignored.

I'm confused where else this can go or why it doesn't work.

Here is my Ansible version:

ansible [core 2.17.4]
  config file = /Users/jd/projects/mgr2/ansible/ansible.cfg
  configured module search path = ['/Users/jd/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/homebrew/lib/python3.11/site-packages/ansible
  ansible collection location = /Users/jd/.ansible/collections:/usr/share/ansible/collections
  executable location = /opt/homebrew/bin/ansible
  python version = 3.11.10 (main, Sep  7 2024, 01:03:31) [Clang 15.0.0 (clang-1500.3.9.4)] (/opt/homebrew/opt/python@3.11/bin/python3.11)
  jinja version = 3.1.4
  libyaml = True

Solution

  • You cannot mix and match a dynamic inventory and a "regular" (YAML) inventory in the same file like that, you will have to create two different inventory files.

    The reason being the inventory is inferred by Ansible when it loads the inventory files.
    You can actually realise this if you run Ansible in verbose mode (using the option -vvv)

    $ ansible-playbook play.yml -vvv
    
    (... some lines not relevant for the issue at hand)
    
    Using inventory plugin
        'ansible_collections.amazon.aws.plugins.inventory.aws_ec2' 
        to process inventory source
        '/usr/local/ansible/inventories/inventory.aws_ec2.yml'
    
    Parsed /usr/local/ansible/inventories/inventory.yml 
        inventory source with yaml plugin
    
    (...)
    

    The good thing is that you can configure Ansible inventory(ies) either as a list of files or as a folder of inventories in your configuration file.

    For example, my ansible.cfg reads

    inventory =
        /usr/local/ansible/inventories/
    

    But you could also do something like

    inventory =
        /usr/local/ansible/inventories/inventory.yml, # YAML inventory
        /usr/local/ansible/inventories/inventory.aws_ec2.yml # AWS inventory
    

    But, in your case, I would probably use a default on all hosts and redefine it only for the local machine, all of this happening in the YAML inventory (i.e.: in /usr/local/ansible/inventories/inventory.yml, in the example above):

    all:
      vars:
        ansible_python_interpreter: /usr/bin/python3
      hosts:
        127.0.0.1:
          ansible_connection: local
          ansible_python_interpreter: >-
            /Users/jd/projects/mgr2/ansible/bin/python3
    

    Another solution would be to use the compose parameter to set the variable in the dynamic inventory:

    plugin: aws_ec2
    regions:
      - ap-southeast-2
      - us-east-1
    hostnames:
      - ip-address
    
    # You can define variable(s) for the dynamic hosts here, 
    #     and it can even be applied with Jinja templating, making those dynamic
    # Mind that the usage of both double and single quote here **is** important
    #     as it will indicate to the Jinja templating that it is a literal string
    compose:
      ansible_python_interpreter: "'/usr/bin/python3'"
    
    keyed_groups:
      - prefix: "tag"
        key: tags
      - prefix: "group"
        key: tags
      - prefix: "security_groups"
        key: 'security_groups|json_query("[].group_name")'
    

    Then in the YAML inventory:

    all:
      hosts:
        127.0.0.1:
          ansible_connection: local
          ansible_python_interpreter: >-
            /Users/jd/projects/mgr2/ansible/bin/python3