Ansible support of Python 3.x is crucial and works out-of-the-box:

“Ansible 2.5 and above have support for Python 3.” (Ansible docs)

However, the combination of Ansible and Fedora 27 (and maybe also Fedora 28?) causes a chicken-and-egg problem under certain circumstances.

The problem

Fedora ships only Python 3.x and recently removed Python 2.x from the base install.

As part of a transition phase of moving from Python 2.x to Python 3.x, /usr/bin/python has been temporarily removed (source). This will result in an error when running Ansible, because it expects the Python interpreter to be found at /usr/bin/python.

As recommended by the Ansible docs, the Python interpreter path needs to be configured (e.g. ansible_python_interpreter=/usr/bin/python3). However, in order to detect the state of a system and set the ansible_python_interpreter variable accordingly, Ansible needs to gather facts about the system by executing the setup module (Ansible docs). The setup module requires Python, which results in the chicken-and-egg problem.

The solution

Actually, there are multiple approaches to solve the problem. The simplest approach might be to define the previously mentioned variable in the Ansible inventory file per host known to run Python 2.x or 3.x.

I prefer to automate the solution, which I did this way:

  1. Disable automatic fact checking
  2. Create pre_tasks using raw commands in order to detect the OS version
  3. Set the ansible_python_interpreter variable according to the OS version
  4. Run fact checking
  5. Continue with your playbooks and execute them against hosts running Python 2 AND Python 3 without the need of any additional config. 😄.

Example “code”-snippet:

- hosts: server
  gather_facts: False # step 1
  become: true
    - group-vars/all_groups
    - common
    - server
    - name: Detect distribution 1/2 # step 2
      raw: bash -c "[ '$(. /etc/os-release && echo $NAME)' = 'Fedora' ] && [ '$(. /etc/os-release && echo $VERSION_ID)' -ge 27 ]" # Fedora release >= version 27
      register: fedora_ver
      failed_when: fedora_ver.rc >= 2
    - name: Load vars for Fedora Linux >= 27 # step 3
      include_vars: group-vars/distribution/fedora/main.yml
      when: fedora_ver.rc == 0
    - name: Detect distribution 2/2 # step 2
      raw: bash -c "[ '$(. /etc/os-release && echo $NAME)' = 'CentOS Linux' ] && [ '$(. /etc/os-release && echo $VERSION_ID)' -ge 7 ]" # CentOS release >= version 7
      register: centos_ver
      failed_when: centos_ver.rc >= 2
    - name: Load vars for CentOS Linux >= version 7 # step 3
      include_vars: group-vars/distribution/centos/main.yml
      when: centos_ver.rc == 0
    - name: Gathering Facts # step 4
    # step 5