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:
- Disable automatic fact checking
- Create
pre_tasks
using raw commands in order to detect the OS version - Set the
ansible_python_interpreter
variable according to the OS version - Run fact checking
- 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
vars_files:
- group-vars/all_groups
roles:
- common
- server
pre_tasks:
- 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
setup:
# step 5