Ansible Conditionals: Using ‘when’ Statements for Conditional Task Execution

Ansible When Conditionals

The Ansible When Conditional is an important feature when you want to execute tasks only if certain conditions are met. You can use Ansible’s when conditional to control the execution of tasks based on specific conditions or facts about the target system.

It allows you to run tasks only when certain criteria are met, such as checking the operating system, verifying the status of a service, or using the output of previous tasks.

In this guide, we’ll explore how to use the when conditional in Ansible to control task execution based on specific conditions.

Basic Syntax

The basic syntax of the when conditional in Ansible is simple. You use the when keyword followed by a condition that evaluates to true or false. Here’s a simple example:

- name: Install Apache on Debian
  apt:
    name: apache2
    state: present
  when: ansible_os_family == 'Debian'

In this example, the Apache package will only be installed if the target system belongs to the Debian family.

Use Ansible When Condition with Roles

Assume you want to configure Nginx on servers that are in the production environment and have a specific role. We’ll use inventory variables and check multiple conditions.

In this example playbook, Nginx is installed, configured, and restarted only on servers in the production environment with the role web.

- hosts: web_servers
  vars:
    env: production
    role: web
  tasks:
    - name: Ensure Nginx is installed
      apt:
        name: nginx
        state: present
      when: env == 'production' and role == 'web'

    - name: Configure Nginx
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      when: env == 'production' and role == 'web'

    - name: Restart Nginx
      service:
        name: nginx
        state: restarted
      when: env == 'production' and role == 'web'

Use Ansible When Conditional with AND Operator

Sometimes, you need to check multiple conditions. You can use the and operator to combine them.

In this playbook, the web server will only restart if both service_running and config_changed are true.

- name: Restart web server if the service is running and the configuration has changed
  service:
    name: apache2
    state: restarted
  when: service_running and config_changed

Use Ansible When Conditional with NOT Operator

In a situation where you need to perform maintenance tasks only if a service is not running, you can use the NOT operator.

This playbook runs maintenance tasks only if PostgreSQL is not currently active.

- hosts: db_servers
  tasks:
    - name: Check if PostgreSQL is running
      shell: systemctl is-active postgresql
      register: postgresql_status
      failed_when: false

    - name: Perform maintenance if PostgreSQL is not running
      shell: ./maintenance_tasks.sh
      when: postgresql_status.stdout != 'active'

Use Ansible When Conditional with NOT Equal Operator

Let’s consider a scenario where you want to start a service only if the current timezone is not set to UTC. This can be useful in cases where certain services or configurations are specific to non-UTC timezones.

In this playbook, the when condition checks if the current timezone is not equal to ‘UTC’. If the condition is true (i.e., the timezone is not UTC), the task will execute.

- name: Start the ntpd service if timezone is not UTC
  ansible.builtin.systemd:
    name: ntpd
    state: started
  when: ansible_date_time.tz != 'UTC'

Use Ansible Ansible When Conditional with Register

Using the register keyword, you can capture the output of a task and use it as a condition for subsequent tasks. This is particularly useful for making decisions based on dynamic data during playbook execution.

In this playbook, disk cleanup will only be performed if the disk usage exceeds 80%.

- hosts: all
  tasks:
    - name: Check disk space
      shell: df -h / | tail -1 | awk '{print $5}' | sed 's/%//'
      register: disk_usage

    - name: Print disk usage
      debug:
        msg: "Disk usage is {{ disk_usage.stdout }}%"

    - name: Clean up disk if usage is above 80%
      shell: ./cleanup_disk.sh
      when: disk_usage.stdout | int > 80

Use Ansible When Conditional with Facts

Ansible gathers facts about the system it manages and stores them in variables. You can use these facts to make decisions in your playbooks. Let’s consider an example where you want to install packages only if the target system has a certain amount of memory.

In this playbook, high-memory-package will be installed on systems with more than 4GB of RAM, while low-memory-package will be installed on systems with 4GB or less.

- hosts: all
  tasks:
    - name: Gather facts
      setup:

    - name: Ensure high-memory package is installed
      apt:
        name: high-memory-package
        state: present
      when: ansible_memtotal_mb > 4096

    - name: Ensure low-memory package is installed
      apt:
        name: low-memory-package
        state: present
      when: ansible_memtotal_mb <= 4096

Use Ansible When Conditional with Boolean Variable

Let’s say you have a boolean variable enable_firewall that determines whether the firewall should be enabled on a server. You can use the when conditional to apply this setting.

In this example, the firewalld service will be started and enabled only if the enable_firewall variable is true.

- name: Enable and start the firewall if enable_firewall is true
  ansible.builtin.systemd:
    name: firewalld
    state: started
    enabled: true
  when: enable_firewall

Use Ansible When Conditional to Install Packages Based on the Operating System

To install packages based on the operating system using Ansible’s when conditional, you can check the OS family or distribution and then apply the appropriate package management tasks. This approach allows you to tailor package installations to different types of systems, such as RedHat-based or Debian-based distributions.

Here’s a playbook that installs httpd on RedHat-based systems and apache2 on Debian-based systems:

- name: Install web server based on OS
  hosts: all
  become: yes
  tasks:
    - name: Install httpd on RedHat-based systems
      ansible.builtin.yum:
        name: httpd
        state: present
      when: ansible_os_family == 'RedHat'

    - name: Install apache2 on Debian-based systems
      ansible.builtin.apt:
        name: apache2
        state: present
      when: ansible_os_family == 'Debian'

Use Ansible When with Multiple Conditios

You can combine multiple conditions using and and or. The following playbook installs the httpd package (which is the Apache web server) on all hosts that meet specific conditions. It runs on all target machines with elevated privileges.

The httpd package is only installed if the system is running a Red Hat-based distribution like Rocky Linux or CentOS with a major version of 8 or higher.

- name: Install httpd package based on multiple conditions
  hosts: all
  become: yes
  tasks:
    - name: Install httpd on eligible systems
      ansible.builtin.yum:
        name: httpd
        state: present
      when:
        - ansible_os_family == 'RedHat'
        - ansible_distribution in ['Rocky', 'CentOS']
        - (ansible_distribution_major_version | int >= 8) or (ansible_distribution == 'Rocky' and ansible_distribution_major_version | int >= 8)

Conclusion

In this article, we explored the various ways to use the Ansible When Conditional to control task execution based on different conditions. Use these techniques in your projects to conditionally execute tasks, making your automation scripts smarter and more reliable.

Happy automating!

FAQs

1. Can I use multiple conditions in the 'when' statement?

Yes, you can use logical operators like and, or, and not to combine multiple conditions in a single when statement.

2. What happens if the 'when' condition is false?

If the when condition is false, the task is skipped, and Ansible proceeds to the next task in the playbook without failing.

3. How do I debug the 'when' conditional if a task doesn't execute as expected?

You can use the debug module or run the playbook in verbose mode (-vvv) to inspect the value of variables and conditions to troubleshoot issues.

About Hitesh Jethva

I am Hitesh Jethva, Founder and Author at Code2DevOps.com. With over 15 years of experience in DevOps and open source technologies, I am passionate about empowering teams through automation, continuous integration, and scalable solutions.

View all posts by Hitesh Jethva