How to Work with Ansible When and Other Conditionals

Published:14 October 2021 - 8 min. read

If you need to execute Ansible tasks based on different conditions, then you’re in for a treat. Ansible when and other conditionals lets you evaluate conditions, such as based on OS, or if one task is dependent on the previous task.

In this tutorial, you’re going to learn how to work with Ansible when and other conditionals so you can execute tasks without messing things up.

Let’s get into it!

Prerequisites

This tutorial comprises hands-on examples. If you’d like to follow along, be sure you have the following in place:

  • A remote computer to run commands.
  • You’ll need an inventory file set up and one or more hosts already configured to run Ansible command and playbooks. The tutorial will use an inventory group called web.

Working with Ansible when with Multiples Tasks in Playbook

Having multiple tasks in a playbook can be a drag if they all execute without specific conditions. Let’s begin this tutorial by defining Ansible when conditions in the Ansible playbook with multiple tasks.

1. Open a terminal on the Ansible controller host.

2. Run the commands below to create a directory and name it anything you prefer in your home directory, and navigate to that directory.

For this example, the directory is named ansible_when_condition_demo. This directory will contain the playbook you’ll use to invoke the when condition within the Ansible task.

# Create a directory named ~/ansible_when_condition_demo
mkdir ~/ansible_when_condition_demo
# Change working directory to ~/ansible_when_condition_demo
cd ~/ansible_when_condition_demo

3. In your preferred code editor, create a YAML file in the ~/ansible_when_condition_demo directory. In this example, the file is called my_playbook.yml. Copy and paste the YAML playbook contents below to the my_playbook.yml file.

In both tasks below (Task-1 and Task-2), the when conditions check which operating system every remote host is on. The result is then passed to the ansible_os_family placeholder variable on each task.

If the ansible_os_family placeholders’ value equals either RedHat or Debian, then Ansible executes either of the tasks to install Apache.

---
- name: Ansible tasks to work on Ansible When
# Defining the remote server where Ansible will run
  hosts: web
  remote_user: ubuntu # Using Remote host as ubuntu
  become: true # Run the tasks as an elevated user (sudo)
  tasks:

# (Task-1) Checks if ansible_os_family == "RedHat" and then Installs Apache on Remote Node
    - name: Install Apache on CentOS  Server
      yum: name=httpd  state=present
      become: yes
      when: ansible_os_family == "RedHat"

# (Task-2) Checks if ansible_os_family == "Debian" and then Installs Apache on Remote Node
    - name: Install Apache on Ubuntu Server
      apt:name=apache2 state=present
      become: yes
      when: ansible_os_family == "Debian"

4. Now run the ansible-playbook command below to execute the tasks defined in the playbook (my_playbook.yml) on the remote host, defined in your existing inventory file.

ansible-playbook my_playbook.yml 

In the screenshot below, you can see that:

  • The first TASK returned an OK status, which shows the task doesn’t require any changes.
  • The second TASK returned the skipping status. When the condition is not met, the task will be skipped.
  • The third TASK returned a changed status, which indicates the remote host wasn’t in the proper state (i.e., Apache is not present) and was modified to install Apache.
Invoking the ansible-playbook using ansible-playbook command
Invoking the ansible-playbook using ansible-playbook command

5. Open a SSH session to the remote host, that was the target of the Ansible playbook, using your favorite SSH client to verify that Apache is installed and running.

6. Finally, run the service command below to verify if Apache is installed (status apache2) on the remote host.

service status apache2

As you can see below, you’ve installed Apache service on the remote machine.

Verifying the Apache service on the remote node
Verifying the Apache service on the remote node

Working with Ansible when and loops

You previously executed Ansible tasks according to an Ansible when for a particular parameter such as ansible_os_family. But perhaps you need to check a condition with multiple parameters defined in a list. If so, then try adding a loop in a task.

Open the my_playbook.yml file you previously created (step three under the “Working with Ansible when with Multiples Tasks in Playbook”). Replace the content of the my_playbook.yml file with the code below.

The task in the code below (Task-1) runs a loop where the when condition checks if the item value is greater than five and returns the result.

---
- name: Ansible tasks to work on Ansible When
# Defining the remote server where Ansible will run
  hosts: web
  remote_user: ubuntu   # Using Remote host as ubuntu
  become: true
  tasks:
  # (Task -1) Checking if item value is greater than 5
    - name: Run with items greater than 5
      ansible.builtin.command: echo {{ item }}
      loop: [ 0, 2, 4, 6, 8, 10 ]
      when: item > 5*

Now run the command below to execute the playbook as you did previously.

 ansible-playbook my_playbook.yml

Below, you can see the task returned skipping status for when the condition is false and changed status for when the condition is true.

Checking the when condition for multiple parameters
Checking the when condition for multiple parameters

Working with Ansible when and Ansible facts

Perhaps you want to add multiple conditions to execute a task. If so, learn how to utilize Ansible facts within when condition. Ansible facts allow you to add a conditional statement to execute tasks based on collected facts, such as your OS, IP addresses, attached file systems, and more.

Replace the content of the my_playbook.yml file with the below code.

In the code below, both tasks (Task-1 and Task-2) only execute (system shutdown) when either of the conditions below is true:

  • Both the distribution and distribtion_major_version returned a true value.
  • The os_family value is equal to CentOS.
---
- name: Ansible When Single task example
  hosts: web
  remote_user: ubuntu
  become: true
  tasks:
# (Task-1): To shutdown the remote node if distribution is CentOS with a major Version 6 
    - name: Shut down CentOS 6 systems
      ansible.builtin.command: /sbin/shutdown -t now
      when:
        - ansible_facts['distribution'] == "CentOS"
        - ansible_facts['distribution_major_version'] == "6"
# (Task-2): To shutdown the remote node if os_family is CentOS. 
    - name: Shut down CentOS flavored systems
      ansible.builtin.command: /sbin/shutdown -t now
      when: ansible_facts['os_family'] == "CentOS"

Execute the playbook as you previously did with the command below.

ansible-playbook my_playbook.yml

Notice below that both tasks show the skipping status since you’re in Ubuntu. The task only executes if you’re in CentOS.

Executing the ansible-playbook with Ansible facts in Ansible when
Executing the ansible-playbook with Ansible facts in Ansible when

Working with Ansible when Based on Registered Values

At times you want to execute or skip a task based on the outcome of an earlier task in a playbook. For instance, you might want to configure a service after a previous task upgrade. In that case, use a registered variable. A registered variable allows you to register the outcome of the earlier task as a variable and use it for the next task as an input.

1. Create an empty directory named /home/ubuntu/hello.

2. Replace my_playbook.yml file’s content with the below code, which performs the following:

The first task (Task-1) lists the contents (files and sub-directories) of the /etc/hosts directory in memory and saves that result to the contents1 variable via the register command.

The second task (Task-2) lists the contents (currently empty) of the /home/ubuntu/hello directory in memory and saves that list to the contents2 variable.

The third task (Task-3) checks and prints a “Directory is empty” message if either registered result for the contents1 or contents2 variable is empty.

The stdout property of the contents1 and contents2 variable is the saved shell output from the result of running the task commands.

---
- name: Ansible When Single task example
  hosts: web
  remote_user: ubuntu
  become: true
  tasks:
# (Task-1): To list the directory content in /etc/hosts directory
      - name: List contents of directory and Store in content1
        ansible.builtin.command: ls /etc/hosts
        register: contents1
# (Task-2): To list the directory content in /home/ubuntu/hello
      - name: List contents of directory and Store in content2
        ansible.builtin.command: ls /home/ubuntu/hello
        register: contents2
# (Task-3): Display Directory is empty if any of the directory 
# /etc/hosts or /home/ubuntu/hello is empty directory
      - name: Check contents for emptiness for content1 or content2
        ansible.builtin.debug:
          msg: "Directory is empty"
        when: contents1.stdout == "" or contents2.stdout == ""

3. Finally, execute the playbook with the ansible-playbook command below.

ansible-playbook my_playbook.yml

As shown below, since the registered result for the contents2 variable is empty, the third task returns the Directory is empty message.

Running the Ansible playbook for Ansible when based on registered values
Running the Ansible playbook for Ansible when based on registered values

Working with Ansible when in Ansible Roles

In this final example, you will learn how Ansible when works within Ansible roles. Ansible roles allow you to re-use standard configurations and make a quicker deployment. Read on to learn how a task invokes Ansible roles only if the Ansible when condition is true.

1. Run the commands below to create a directory named ~/ansible_role_when_demo in your home directory and change to that folder as the working directory. The ~/ansible_role_when_demo directory will hold this example’s demo files.

# Create a directory named ~/ansible_role_when_demo in your home directory
mkdir ~/ansible_role_when_demo
# Change to the ~/ansible_role_when_demo directory
cd ~/ansible_role_when_demo

2. Next, run the commands below to create a ~/ansible_role_when_demo/roles and ~/ansible_role_when_demo/roles/java/tasks directory.

Below is what each directory will contain:

  • The ~/ansible_role_when_demo/roles directory will contain the role that you need to deploy.

By default, Ansible looks for roles in two locations in a directory called roles/ within the directory where playbook resides or in the /etc/ansible/roles. If you wish to store roles at different paths, declare the paths using the - role: parameter in the playbook.

  • The ~/ansible_role_when_demo/roles/java/tasks folder will contain a main.yml file you’ll need to deploy a role.
# Create a directory named roles inside the ~/ansible_role_when_demo directory
mkdir -p roles
# Change working directory to ~/ansible_role_when_demo/roles directory
cd roles 
# Create the parent (-p) directory named java and a subdirectory named tasks
mkdir -p java/tasks

Now, create a file named main.yml in the ~/ansible_role_when_demo/roles/java/tasks directory, then copy and paste the playbook code below to the main.yml file.

The playbook below installs Java on the remote node it’s run on with the apt module.

---
# Installing the Java (Open Jdk) 
- name: Install Java 1.8
  apt: name=openjdk-8-jdk

4. Create another YAML file with a name you prefer, and copy/paste the below code. For this example, the file is named ~/ansible_role_when_demo/java-setup.yml.

The code below deploys the Ansible role (java) to the remote user (ubuntu) that has admin access only when the remote user is on Debian OS.

- name: Java Installation playbook
# Defining the remote server where the package will be deployed 
  hosts: myserver
  remote_user: ubuntu   # Using Remote user as ubuntu
  become: true
  tasks:  
  roles:
     - role: java
       # Execute the task only if the remote_user is on a Debian OS.
       when: ansible_facts['os_family'] == 'Debian'

5. Run the tree command to verify all required folders and files exist in the ~/ansible_role_when_demo directory.

Verifying all of the required folders in the ~/ansible_role_when_demo directory
Verifying all of the required folders in the ~/ansible_role_when_demo directory

6. Finally, execute the playbook with the ansible-playbook command below. ansible-playbook java-setup.yml

ansible-playbook java-setup.yml

Below, the task returned a changed status, indicating Java has been installed successfully as the remote node is on a Debian OS. Untitled Running the Ansible playbook using Ansible when with Ansible roles

Running the Ansible playbook using Ansible when with Ansible roles
Running the Ansible playbook using Ansible when with Ansible roles

Conclusion

In this tutorial, you learned different ways of using Ansible when and other conditionals. You’ve also learned how to apply Ansible when conditions, from basic tasks leveraging Ansible facts and deploying Ansible roles.

Now how would you build upon this newfound knowledge? Perhaps save time configuring multiple servers with Ansible templates while applying Ansible when conditions?

Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.

Explore ATA Guidebooks

Looks like you're offline!