Ansible Dry Run: Running Playbook in Check Mode

Ansible's dry run, also known as check mode, is a powerful tool that lets you simulate playbook execution without making any actual changes to your systems. This is incredibly useful for testing and debugging playbooks before unleashing them on your production environment.

Imagine you have a complex Ansible playbook that updates configurations across multiple servers. Before hitting that "run" button, you'd ideally want to test it to ensure everything works as planned.

A dry run allows you to do exactly that. It walks through your playbook, checks for errors, and displays what changes would be made on the target hosts, all without actually applying them.

Let's dive into how to perform a dry run in under 5 minutes, with examples ranging from super simple to a more practical scenario.

Prerequisites

To proceed with this tutorial, you will need the following:

  • An Ansible management node with Ansible installed and configured.
  • SSH key-based authentication between the management node and target nodes.

How to dry run

There are two main ways to perform a dry run with Ansible:

1. Command Line Flag

This is the quickest way. Run your playbook with the --check flag like this:

ansible-playbook my_playbook.yml --check

2. Playbook Option

You can also define the check_mode: True option within your playbook itself:

- hosts: all
  become: true
  tasks:
    - name: Update package lists
      apt: update_cache=yes
      check_mode: True 

Example 1: Super simple dry run

Let's say you have a simple task that updates the /etc/hostname file on your target machine. Here's the playbook:

- hosts: all
  become: true
  tasks:
    - name: Update system hostname
      lineinfile:
        path: /etc/hostname
        create: yes
        line: "newlinuxhost"

Now, run the playbook with the --check flag:

ansible-playbook update_hostname.yml --check

This confirms that the playbook would add the line newlinuxhost to the /etc/hostname file, but since it's a dry run, no changes are actually made.

Example 2: Practical dry run with package installation

Now, let's look at a more practical scenario. Imagine you have a playbook that installs the apache2 web server package on your web servers:

- hosts: webservers
  become: true
  tasks:
    - name: Install Apache web server
      apt:
        name: apache2
        state: present
      check_mode: True 

Before unleashing this on your production servers, it's wise to do a dry run:

ansible-playbook install_apache.yml

The output will show you details about which packages would be installed and their versions. This allows you to verify if the playbook targets the correct packages and avoids any surprises during actual execution.

Example 3: Conditional task execution with check mode

Imagine a playbook that updates a system based on specific conditions. Here's an example:

- hosts: web1
  become: true
  tasks:
  - name: Check if Python 3 is installed
    command: python3 --version
    register: python3_check
  - name: Install Python 3 if not found (would only run in actual execution)
    apt:
      name: python3
      state: present
    when: python3_check.rc != 0  # Only run if Python 3 is not found
  - name: Update system message for Python 3 users (dry run will show intended message)
    lineinfile:
      path: /etc/motd
      line: "Welcome! Python 3 is now available."
    when: python3_check.rc == 0  # Only run if Python 3 is found

Now, let's do a dry run:

ansible-playbook install_python3.yml --check

Running this with --check won't actually install Python 3, but it will show the intended line that would be added to the /etc/motd file if Python 3 is detected. This helps verify the conditional logic works as expected.

Example 4: Testing Jinja2 templating with check mode

Ansible uses Jinja2 templating for dynamic content. Dry runs can help test how variables are used within templates. Here's an example:

- hosts: webservers
  become: true
  tasks:
  - name: Configure Apache with server name
    template:
      src: apache.conf.j2
      dest: /etc/apache2/sites-available/{{ server_name }}.conf
      owner: www-data
      group: www-data
    vars:
      server_name: "mysite.com"

Now, try to run the above playbook with dry run:

ansible-playbook configure_apache.yml --check

Example 5: Testing with loops and conditionals

Ansible allows looping through lists and running tasks conditionally. Dry runs can help validate these constructs before actual execution. Here's an example:

---
- hosts: all
  become: true
  tasks:
    - name: Loop through list of packages to install
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - php
        - php-fpm
        - mariadb-server
      when: ansible_os_family == "Debian"  # Run only on Debian-based systems

    - name: Loop through list of systemd services to enable (dry run shows intended service states)
      systemd:
        name: "{{ item }}"
        state: enabled
      loop:
        - apache2.service
        - php8.1-fpm.service
      when: ansible_os_family == "Ubuntu"  # Run only on Ubuntu systems

Now, run the above playbook using dry run:

ansible-playbook loop.yml --check

This playbook loops through package lists and systemd services based on the operating system. A dry run will iterate through the loops and show the intended actions for each item, even though no actual installation or enabling occurs.

Conclusion

Ansible's dry run functionality is a valuable asset for any Ansible user. By incorporating dry runs into your workflow, you can ensure your playbooks are error-free and make well-informed decisions before applying changes to your systems. So, next time you write a playbook, remember to take it for a spin in check mode first!

If you are new to Ansible and want to learn it from scratch, our Ansible tutorial series will be of great help. It's written for RHCE exam but it helps you the same whether you are preparing for the exam or not.

RHCE Ansible EX294 Exam Preparation Course
Learn all the essentials of Ansible with this hands-on tutorial series. It is ideal for RHCE Ansible EX294 exam preparation.
✍️
Author: Hitesh Jethwa has more than 15+ years of experience with Linux system administration and DevOps. He likes to explain complicated topics in easy to understand way.