I have an Ansible playbook (using ansible 1.9.3) that sets up and updates a bunch of servers. One of those steps is to install packages (using the 'apt' plugin). Until recently all of my servers have been uniform (same version of Ubuntu server). I'm introducing a newer Ubuntu server and some of package names have changed.
Here's what my tasks file looks like:
- name: install needed packages
apt: name={{ item }} state=present update_cache=yes
with_items: packages
(and I have a list of packages in a vars file).
I could define a variable in my inventory file for the hosts with a different Ubuntu version.
How do I change this task to use one list of packages for my current hosts, and another list of packages for my newer hosts?
Use a when
clause. Here's an example that will only run on ubuntu 12.04
when: "'{{ ansible_distribution}}' == 'Ubuntu' and '{{ ansible_distribution_release }}' == 'precise'"
You could alternatively use:
when: "'{{ ansible_distribution }}' == 'Ubuntu' and '{{ ansible_distribution_version }}': '12.04'"
Edit:
Later versions of Ansible (e.g. 2.7.1) would print a warning for this statement:
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: '{{ansible_distribution}}' == 'Ubuntu' and '{{ ansible_distribution_release }}' == 'bionic'
Ansible now expects another syntax for conditional statements, as stated in the docs.
For Ansible 2.5 you could try this:
when: "ansible_distribution|string == 'Ubuntu' and ansible_distribution_release|string == 'bionic'"
or even:
when:
- ansible_distribution|string == 'Ubuntu'
- ansible_distribution_release|string == 'bionic'
The latest version of the docs suggests to use access the ansible_facts like this:
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"
To keep your playbooks cleaner, you could do this within the roles, for example, you could have a single tasks/main.yml
the one based on the OS it will include the tasks matching the condition used with when
, for example, if using ansible_os_family
the contents of main.yml
could be something like:
---
- include_tasks: freebsd.yml
when: ansible_os_family == "FreeBSD"
tags:
- unbound
- include_tasks: debian.yml
when: ansible_os_family == "Debian"
tags:
- unbound
- include_tasks: redhat.yml
when: ansible_os_family == "RedHat"
tags:
- unbound
The advantage of this approach is that besides only having a set of task per OS, you can also tag the full tasks.