Using Ansible “when” Statements

Using Ansible “when” statements allows you to set parameters for when a task should play out.  I’ve put together some examples of how to use basic when statements that I’ve come across.

Booleans (True or False)

In the example playbook below, I print “Hello world” when the”test_var” variable is true.  In the case below we use the “bool” filter to make test_var evaluated as a boolean (ie true or false), then ensure it’s true:

- hosts: localhost
  user: engonzal
  connection: local
  tasks:
    - name: test_var is "{{ test_var }}"
      debug: msg="Hello world."
      when: test_var|bool == true

As a note, instead of using “test_var|bool == true”, you can simply use “when: test_var”.  To evaluate when test_vars is false you would use “test_var|bool == false”

Defined Variables

Sometimes you’ll want to check if a variable is defined before running a task, or another when statement.  The example below has two tasks, the first runs when “test_var” is defined.  the second runs when “test_var” is not defined.  Since we’re defining “test_var” in the playbook “vars” section, the second task will show as “skipped”

- hosts: localhost
  user: engonzal
  connection: local
  vars:
    test_var: true
  tasks:
    - name: test_var is "{{ test_var }}" (when defined)
      debug: msg="test_var is defined"
      when: test_var is defined

    - name: test_var is "{{ test_var }}" (when not defined)
      debug: msg="test_var is not defined"
      when: test_var is not defined

Combing Tests

We also have the option of combining variables with “and”.

- hosts: localhost
  user: engonzal
  connection: local
  vars:
    dog: true
  tasks:
    - name: dog is defined, cat is defined
      debug: msg="Hello dog and cat."
      when: dog is defined and cat is defined

    - name: dog is defined or cat is defined
      debug: msg="Hello dog or cat."
      when: dog is defined or cat is defined

You can also format “and” statements as items of “when”

    - name: dog is defined, cat is defined
      debug: msg="Hello dog and cat."
      when:
        - dog is defined
        - cat is defined

String Tests

You can also use a when statement to verify a variable is equal to a string.  In the example below we check that “dog” is equal to “bone”.  Note that I use “dog | lower”.  This converts all the characters in the dog variable to lower case.

- hosts: localhost
  user: engonzal
  connection: local
  vars:
    dog: bone
  tasks:
    - name: dog is bone, cat is undefined
      debug: msg="dog is equal to bone"
      when: dog|lower == "bone"

Now let’s look at cat, notice that since we don’t define cat in the vars section, we want to first check if cat is defined.  This task will skip because cat is not defined and the “cat|lower ==”fish” will not get evaluated.

    - name: cat is equal to fish
      debug: msg="cat likes fish"
      when:
        - cat is defined
        - cat|lower == "fish"

Alternatively you can use the defaults filter to use a default value for “cat”

    - name: cat is equal to fish
      debug: msg="cat is equal to fish"
      when: cat | default('fish') | lower == "fish"

Verify a file exists

You can use the “stat” module to check if a file or directory exists.  All you need to do is run the stat module, and add the “register: my_new_variable”.  We can then evaluate that variable:

- hosts: localhost
  user: engonzal
  connection: local
  tasks:
    - name: Check if /tmp exists
      stat:
        path: /tmp
      register: stat_tmp

    - name: Say Hello when "/tmp" exists
      debug: msg="Hi! the directory /tmp exists"
      when:
        - stat_tmp.stat.exists|bool == true

Find Strings

You can also use the find filter to check if something exists in a variable.  In the example below, we’re checking if the variable “cat” contains any occurence of the word “plays”.

- hosts: localhost
  user: engonzal
  connection: local
  vars:
    cat: "cat plays with yarn"
  tasks:
    - name: Check if cat "plays"
      debug: msg="The cat does play"
      when:  cat.find("plays") != -1

Having the flexibility to only run tasks when they’re needed is a useful feature of Ansible.  The built in tests allow you a lot of freedom for how to structure playbooks and roles.  These were some basic example, but they can get pretty complicated.  Ansible’s docs also have some other great examples of how to use “tests”. 

I’ll be putting together some more interesting examples in the future!  Take a look at the guide to setting up ansible with virtualenv if you’re new.