I am using ansible to connect with server. But I am getting errors for certain pip packages because of older version of python. How can I install a specific version of python ( 2.7.10
) using ansible. Current python version on the server is 2.7.6
For now I have compiled and installed the python version manually but would prefer to have a way to do it via ansible.
Additionally to @Simon Fraser's answer, the following playbook is what I use in Ansible to prepare a server with some specific Python 3 version:
# python_version is a given variable, eg. `3.5`
- name: Check if python is already latest
command: python3 --version
register: python_version_result
failed_when: "{{ python_version_result.stdout | replace('Python ', '') | version_compare(python_version, '>=') }}"
- name: Install prerequisites
apt: name=python-software-properties state=present
become: true
- name: Add deadsnakes repo
apt_repository: repo="ppa:deadsnakes/ppa"
become: true
- name: Install python
apt: name="python{{ python_version }}-dev" state=present
become: true
I have the above in a role too, called ansible-python-latest ( github link ) in case you are interested.
The first thing to consider is that you probably don't want to replace or upgrade the system version of Python. This is because it's used by the system itself for things like package management, and so replacing it may cause other important things to break.
Installing an extra copy of Python that someone else made
To get an extra version of Python installed, the easiest option is to use a ppa , such as https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes-python2.7 so that someone else has done the work of turning Python into a package for you.
A PPA can be added with Ansible's apt repository module using a directive like the one below, which will then allow you to install packages from it the normal ansible way:
apt_repository: repo='ppa:fkrull/deadsnakes-python2.7'
Building a package yourself
If there is no ppa
that has the version of Python you require, then you may need to build a .deb
package yourself. The simplest way of doing this is a tool like checkinstall . There's also fpm , which can take lots of different sources and make deb
, rpm
and so on with them. It can also take a Python module only available with pip install
and turn it into a system package for you, which is very useful.
Once you have a deb
package you can install it with Ansible's apt module
apt: deb=/tmp/mypackage.deb
I want to point out that there are potentially 2 or 3 different Pythons involved in an Ansible build and that's it's useful not to mix them up.
1️⃣ The system/Ansible Python. On my VirtualBox guest Ubuntu 20.04, that's 3.8.x right now.
2️⃣ Your application/production Python, and that includes what pip/venv
are tasked with doing, via Ansible. In my case, my own application code uses 3.10.
3️⃣ The development , not system, Python you use on your host machine, which is again a separate concern. (macos, Python 3.10, in my case).
You want to keep your application's development 3️⃣ and production 2️⃣ Pythons at an equivalent level.
Ansible does not need to use 3.10 however, so I will leave Ansible and system Python alone.
For what it's worth, my host Macbook is running Python 3.10 too, but that does not interfere with the guest's being on 3.8
The following details some of what I did. I don't claim it is best practices, but it does show how I chose to separate those concerns:
#dont start out with 3.10, because it may not exist yet
# ansible_python_interpreter=/usr/bin/python3.10
ansible_python_interpreter=/usr/bin/python3 #1️⃣
I did not adjust ansible_python_interpreter
throughout my playbook, ie Ansible was left with 20.04's delivered Python.
Track the application Python version in different variables.
# application, not system/Ansible, python
py_appver: "3.10" #2️⃣
py_app_bin: "/usr/bin/python{{py_appver}}"
I very rarely used py_appver
in the playbook.
(ssha)vagrant bin$pwd
/usr/bin
(ssha)vagrant bin$ls -l python3*
lrwxrwxrwx 1 root root 9 Mar 13 2020 python3 -> python3.8
(ssha)vagrant bin$/usr/bin/python3 --version #1️⃣
Python 3.8.10
apt
to get 3.10 from: - name: add Python dead snakes repo for 3.10
ansible.builtin.apt_repository:
repo: 'ppa:deadsnakes/ppa'
##############################################
# These utilities may be used by any of the tasks
# so might as well put them in early
##############################################
- name: install system-level components
package: "name={{ item }} state=present"
with_items:
- monit
- runit
....
# needed by ANXS.postgresql
- python3-psycopg2
# not sure I needed but..
- python3-pip
#Application Python
- python{{py_appver}} #2️⃣
- python{{py_appver}}-venv #2️⃣
# DONT DO THIS
# - name: symlink python executables
# file:
# src: "/usr/bin/{{item.from_}}{{pyver}}"
# dest: "/usr/bin/{{item.to_}}"
# state: link
# force: true
# with_items:
# - {from_: "python", to_: "python3"}
# - {from_: "pyvenv-", to_: "pyvenv"}
# when: false
Again, this may not necessarily be best practice, but it worked.
The result is to have /srv/venv
4️⃣ virtualenv using Python 3.10
- name: create virtualenv manually
command: "{{py_app_bin}} -m venv ./venv" #2️⃣
args:
chdir: "/srv"
become: yes
become_user: builder
when: not venv_exists.stat.exists
And now, I ask pip
to self-update and install stuff:
- name: pip self-update to 20.x
pip:
name: pip
state: latest
virtualenv: "/srv/venv" # 4️⃣
- name: pip requirements 1st pass
pip:
requirements: "{{ dir_app }}/requirements.txt"
virtualenv: "/srv/venv" # 4️⃣
virtualenv_python: "python{{py_appver}}" #2️⃣
And that was it. My pip/venv stuff gets its 3.10 to play with and everything else, including ansible, uses 3.8.
/usr/bin
on the VM at the end:(ssha)vagrant bin$pwd
/usr/bin
(ssha)vagrant bin$ls -l python3*
lrwxrwxrwx 1 root root 9 Mar 13 2020 python3 -> python3.8
-rwxr-xr-x 1 root root 5454104 Dec 21 09:46 python3.10
-rwxr-xr-x 1 root root 5490488 Nov 26 12:14 python3.8
lrwxrwxrwx 1 root root 33 Nov 26 12:14 python3.8-config -> x86_64-linux-gnu-python3.8-config
lrwxrwxrwx 1 root root 16 Mar 13 2020 python3-config -> python3.8-config
(ssha)vagrant bin$python3 --version # 1️⃣
Python 3.8.10
(ssha)vagrant bin$source /srv/venv/bin/activate # 4️⃣
(venv) (ssha)vagrant bin$python --version # 2️⃣
Python 3.10.1
$ansible --version
ansible [core 2.12.1]
config file = /Users/myuser/.ansible.cfg
configured module search path = ['/Users/myuser/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /Users/myuser/kds2/venvs/bme/lib/python3.10/site-packages/ansible
ansible collection location = /Users/myuser/.ansible/collections:/usr/share/ansible/collections
executable location = /Users/myuser/kds2/venvs/bme/bin/ansible
python version = 3.10.1 (main, Dec 10 2021, 12:10:01) [Clang 12.0.5 (clang-1205.0.22.11)]
Not sure how relevant guest-side ansible is but I'll add it anyway:
$apt list | egrep -i ^ansible
ansible-doc/focal 2.9.6+dfsg-1 all
ansible-lint/focal 4.2.0-1 all
ansible-tower-cli-doc/focal 3.3.0-1.1 all
ansible-tower-cli/focal 3.3.0-1.1 all
ansible/focal 2.9.6+dfsg-1 all
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.