Make Ansible Playbook Distribution Agnostic
I’ve been thinking about switching to a rolling distribution on my working machine for quite some time. Because the packages in Ubuntu repositories are just too outdated for my needs and I want to save myself the headache of PPAs. And when Ubuntu announced dropping Unity in favor of Gnome, my mind was made up. I would use a rolling distro on my main computer and Ubuntu 16.04 elsewhere.
Unify package installation
In the end, I decided to go for OpenSuse. Since I use an Ansible playbook to setup my machines, it would take no time to have it up an running. Or so I thought. However, there was a little caveat. As my playbook used the apt module to install software, it would obviously not run on OpenSuse. Luckily, since the version 2.0, Ansible provides a platform-agnostic package manager module. It is called simply package
. As a result, installing packages across different distributions is as easy as running:
--- - name: Install packages become: yes package: name: git state: present
Or is it? While it may work in the case of Git, not all packages have a same name in different Linux distributions. So you have to set up variables for those: First of all, defaults in vars/default.yml
:
apache_package: apache2
Then, for Debian family vars/Debian.yml
--- apache_package: apache2
And for Redhat family vars/Redhat.yml
--- apache_package: httpd
Afterwards, just include them in your tasks:
- include_vars: "{{ item }}" with_first_found: - "{{ ansible_os_family }}.yml" - "default.yml" - name: Install Apache become: yes package: name: "{{ apache_package }}" state: present
Run different tasks on various distros
Using variables is sometimes not enough. As depending on the system, you might want to run compeletely different tasks. In such case, just create two (or more) tasks for the respective systems. A good example is upgrading packages, since it vastly differs across distributions: Firstly, for Debian family (including Ubuntu) in tasks/update-Debian.yml
:
--- - name: Update packages become: yes apt: update_cache: yes upgrade: dist
Then, for OpenSuse in tasks/update-SLES.yml
:
--- - name: Update packages zypper: name: '*' state: latest update_cache: yes
Lastly, conditionally include them in the main task (tasks/main.yml
):
--- - include: "update-{{ ansible_os_family }}.yml"
That’s it. Now you can easily make your Ansible playbook distribution agnostic, so it runs across different Linux flavors.