How to Use When Conditionals Statement in Ansible Playbook
Oftentimes, Ansible plays contain various sets of variables. The tasks to be carried out using these variables vary according to the nature of these variables. And this is where Conditional statements come in. Conditional statements are mostly used in Ansible playbooks where there is a mix of different variables, each representing different entities such as software packages, servers, networking devices and so on. In this guide, we will demonstrate how to use various when conditional statements in a setup with servers running different operating systems.
Using ‘when’ conditional statement
Traditional programming language usually uses the if-else statement when more than one outcome is expected. In Ansible, ‘when’ statement is used instead to determine the outcome of a variable. So instead of using the if-else statement, you define what you want to happen. The syntax is as shown below:
tasks . . .
Let’s take an example of a setup with an Ansible control node and two servers as shown below:
- CentOS 7 server IP: 188.8.131.52
- Ubuntu 18.04 server IP: 184.108.40.206
- Ansible control node IP: 220.127.116.11
Using the Ansible Control node which has already been set up and configured to communicate with the two servers.
The task at hand will be to install the Apache web server on both web servers using a single playbook.
But here’s the catch,
Installation of Apache on CentOS, which is a Red Hat flavor, differs from Ubuntu, which is a Debian flavor. Both use different package managers and the Apache package also differs in both cases. In such a scenario, where we have different variables at play, a conditional statement is crucial.
Given the differences mentioned, we are going to use the ‘when’ conditional statement to install Apache web server as shown in the playbook as shown:
--- - name: install Apache Web-Server hosts: all tasks: - name: Install Apache on CentOS Server yum: name=httpd state=present become: yes when: ansible_os_family == "RedHat" - name: Install Apache on Ubuntu Server apt:name=apache2 state=present become: yes when: ansible_os_family == "Debian"
When you run the playbook, you’ll get the output below
Let’s break this down:
The first task or play executes the installation of the httpd package, colloquially known as the Apache web-server, on the remote CentOS host using the yum package manager which is the package manager for RHEL distros. Because we have defined all the host systems in our inventory, the installation of the httpd package alongside other dependencies will only take place for servers belonging to the Red Hat family. This has been defined by the built-in variable ansible_os_family. In effect skips the installation on Ubuntu server, which is evidenced by the line “skipping [18.104.22.168]”
Because the Ubuntu server has been omitted in the first play, another play needs to be defined. The second play executes the installation of the Apache2 package using the apt package manager which is the native package manager for the Debian OS family. This implies that the apache2 package will be installed in all systems that fall under the Debian family, for which Ubuntu is a part.
Ultimately, the Apache Web Server will be installed on both Red Hat and Debian based servers.
Using ‘when’ with the logical AND operator
You can further refine your playbook and narrow it down to the specifics. Suppose you only want Ansible to install apache web server on Ubuntu servers whose version is 18.04, how would you go about it?
In this case, you will define another variable which will restrict the installation of Apache to Ubuntu servers on version 18.04. Here’s how they play would look like.
--- - name: install Apache webserver hosts: all tasks: - name: Install Apache on Ubuntu Server apt: name=apache2 state=present become: yes when: ansible_os_family == "Debian" and ansible_distribution_version == "18.04"
As you have seen, we have used the AND logical operator followed by another built-in Ansible variable known as ansible_distribution_version which has been assigned the value “18.04”
For this play to be executed, both conditions have to be TRUE, i.e, the host system has to fall under the Debian category of OS, and the version has to be 18.04. As we know, only Ubuntu fits the description i.e Ubuntu 18.04. If either of the conditions is not met, then the play fails and the installation of Apache will fail.
Using ‘when’ with the logical OR Operator
With OR logical operator, the play is executed when either or all of the conditions are satisfied.
Let’s consider another playbook:
--- - name: Check disk space usage hosts: all tasks: - name: Check disk space usage on servers shell: df -Th register: result - debug: var: result.stdout_lines when: ansible_os_family == "Debian" or ansible_os_family == "RedHat"
The above playbook displays disk usage metrics on servers in the setup that fall either under Debian or Red Hat distributions or both. Since both servers in our setup fall under the above-mentioned OS families, the playbook will display disk usage for both servers.
Conditional statements are essential in a multi-OS setup where variations exist in package management and server configuration. We hope you can now comfortably use the when conditional statement to perform various tasks according to the distribution of your server.