Bootstrap FreeKB - Ansible - Setting Python version using the interpreter_python directive in ansible.cfg
Ansible - Setting Python version using the interpreter_python directive in ansible.cfg

Updated:   |  Ansible articles

Let's say you have two systems, the Ansible controller (that's the system Ansible is installed and running on) and a target server, and let's say each system has a different version of Python. Perhaps the Python CLI on the Ansible controller is Python version 3.12.0.

[admin@controller ~]$ python --version
Python 3.12.0

 

And the Python version on a target server is Python version 3.9.18.

[john.doe@server1 ~]$ python --version
Python 3.9.18

 

Let's say you have the following playbook, which uses the ansible.builtin.file module to create and then delete the /tmp/foo.txt file on the target system on the target system.

---
- hosts: all
  tasks:
  - ansible.builtin.file:
      path: /tmp/foo.txt
      state: "{{ item }}"
    with_items:
    - touch
    - absent
...

 

Let's run the ansible-playbook command with the -vvv (very verbose) flag.

ansible-playbook example.yml --inventory server1.example.com, --user john.doe --ask-pass -vvv

 

So, underneath the hood, a directory is created on the target server, something like this.

/home/john.doe/.ansible/tmp/ansible-tmp-1713408593.1331322-16539-164674748277391

 

This can been seen in the output with the -vvv flag. The output should have something like this.

<server1.example.com> SSH: EXEC \
sshpass -d12 \
ssh -C \
-o ControlMaster=auto \
-o ControlPersist=60s \
-o 'User="john.doe"' \
-o ConnectTimeout=10 \
-o 'ControlPath="/home/john.doe/.ansible/cp/da9b18fba3"' \
server1.example.com \
'/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/john.doe/.ansible/tmp `"&& mkdir "` echo /home/john.doe/.ansible/tmp/ansible-tmp-1713408596.274309-16590-237914960550324 `" && echo ansible-tmp-1713408596.274309-16590-237914960550324="` echo /home/john.doe/.ansible/tmp/ansible-tmp-1713408596.274309-16590-237914960550324 `" ) && sleep 0'"'"''

 

It is important to recognize that the directory will be removed, so for this excercise, I would set the ANSIBLE_KEEP_REMOTE_FILES environment variable to 1 which instructs the Ansible controller to not delete the tmp files and directories that get created on the target server.

export ANSIBLE_KEEP_REMOTE_FILES=1

 

And then the AnsiballZ_file.py Python script is PUT from the Ansible controller to the target server.

<server1.example.com> PUT /home/admin/.ansible/tmp/ansible-local-1681708tty8e7/tmpclmqm36v TO /home/john.doe/.ansible/tmp/ansible-tmp-1713405726.6487887-17223-276200849623319/AnsiballZ_file.py

 

Ansible uses the sshpass command to connect to the target server and then ssh command and the /bin/sh (shell) CLI with the -c (command) flag to run a command on the target server. The command that is run on the target server is almost always /home/john.doe/.ansible/tmp/ansible-tmp/AnsiballZ_<module name>.py, a Python script. Since this command is being run on the target server, this uses the Python CLI on the target server, not Python on the Ansible controller.

<server1.example.com> SSH: EXEC \
sshpass -d12 \
ssh -C \
-o ControlMaster=auto \
-o ControlPersist=60s \
-o 'User="john.doe"' \
-o ConnectTimeout=10 \
-o 'ControlPath="/home/john.doe/.ansible/cp/da9b18fba3"' \
server1.example.com \
'/bin/sh -c '"'"'chmod u+x /home/john.doe/.ansible/tmp/ansible-tmp-1713405726.6487887-17223-276200849623319/ /home/john.doe/.ansible/tmp/ansible-tmp-1713405726.6487887-17223-276200849623319/AnsiballZ_file.py && sleep 0'"'"''

 

And if we look at line 1 in AnsiballZ_file.py, we can see it is using /usr/bin/python3.

[john.doe@server1 ~]$ head -1 /home/webproc/.ansible/tmp/ansible-tmp-1713408594.9606252-16563-253322922038816/AnsiballZ_file.py 
#!/usr/bin/python3

 

There are a few different ways to tell Ansible to run the AnsiballZ_<module>.py files on the target servers with a certain version of Python.

The interpreter_python directive in ansible.cfg will be in the [defaults] section, something like this.

[defaults]
interpreter_python = /usr/bin/python3.9

 

Let's say the playbook includes ansible_python_interpreter: /usr/bin/python3.9.

---
- hosts: all
  tasks:
  - ansible.builtin.file:
      path: /tmp/foo.txt
      state: "{{ item }}"
    with_items:
    - touch
    - absent
...

 

This will cause the AnsiballZ_file.py to have /usr/bin/python3.9.

[john.doe@server1 ~]$ head /home/john.doe/.ansible/tmp/ansible-tmp-1713410268.6565683-30050-40883123872239/AnsiballZ_file.py 
#!/usr/bin/python3.9

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter f9d12d in the box below so that we can be sure you are a human.