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

The, 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.

2 thoughts on “Make Ansible Playbook Distribution Agnostic

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.