If you are from a programming or scripting background then you should be familiar with the concept called "conditional statements". The conditional statements allow you to execute the code based on the result of the condition. Similarly in ansible, you can use the "when conditional statements" to execute tasks. If the condition is evaluated to true, the task will run, else the task will be skipped.
The syntax for the when
conditional statement is as follows. You will learn how to apply the conditional statement with tasks in the subsequent sections.
Play definition tasks: Task 1 when: condition Task 2 when: condition
'When
' Conditional Statements With Ansible Facts
Facts are system-related information collected by ansible using the setup module on managed nodes. There may be cases where you have to make decisions based on the facts gathered.
If you have no idea about facts, we have a brief article about facts and you can access it using the link below.
In the following playbook, I have written a task to install the epel-release repository using the dnf module. Using the fact(ansible_distribution), I have written the conditional statement to install the package only on "rocky" Linux. I have used the jinga2 case conversion filter(lower) to convert the ansible_distribution output to lower case.
--- - name: Installing packages hosts: all become: true gather_facts: true # By default it is set to true tasks: - name: Install epel-release dnf: pkg: epel-release state: present when: ansible_distribution | lower == "rocky"
When I run the playbook, the when condition will evaluate and run the task only on Rocky Linux. Task will be skipped for all other distributions.
$ ansible-playbook when_condition_test.yml PLAY [Installing packages] ******************************************************** TASK [Gathering Facts] ************************************************************ ok: [rocky.anslab.com] ok: [ubuntu.anslab.com] TASK [Install epel-release] *********************************************************************************** skipping: [ubuntu.anslab.com] ok: [rocky.anslab.com] PLAY RECAP *********************************************************************************** rocky.anslab.com : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 ubuntu.anslab.com : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Ansible 'When
' Conditional Statements With Logical AND/OR Operators
You can use the logical AND/OR operator to evaluate multiple conditions. I am using the same playbook but added one more condition based on facts. This play will be skipped since the distribution version I am running with is 8 and I am checking the condition against version 9.
- name: Logical AND Testing dnf: pkg: htop state: present when: ansible_distribution | lower == "rocky" and ansible_distribution_major_version == "9"
Sample Output:
TASK [Gathering Facts] ********************************************************************************************************************* ok: [rocky.anslab.com] ok: [ubuntu.anslab.com] TASK [Logical AND Testing] ***************************************************************************************************************** skipping: [ubuntu.anslab.com] skipping: [rocky.anslab.com]
You can also write logical AND using YAML list format.
- name: Logical AND using List syntax dnf: pkg: htop state: present when: - ansible_distribution | lower == "rocky" - ansible_distribution_major_version == "9"
When I run the same playbook against logical OR operator, the task will run fine.
TASK [Gathering Facts] ********************************************************************************************************************* ok: [ubuntu.anslab.com] ok: [rocky.anslab.com] TASK [Logical OR Testing] ****************************************************************************************************************** skipping: [ubuntu.anslab.com] ok: [rocky.anslab.com]
When you have multiple expressions to be evaluated you can put them inside parentheses. Here I am using JINJA2 syntax(int >= 8
) to evaluate if the distribution version is greater than or equal to 8.
- name: Multiple conditions dnf: pkg: epel-release state: present when: (ansible_distribution | lower == "centos" or ansible_distribution | lower == "rocky") and ansible_distribution_major_version | int >= 8
Ansible 'When
' Conditional Statement With Membership Operator
You can use the IN operator to evaluate the expression against a list of values. In the following playbook, I created a task to run on RHEL based distros.
- name: Membership Operator dnf: pkg: epel-release state: present when: ansible_distribution | lower in ["centos","rocky"]
Sample Output:
TASK [Gathering Facts] ********************************************************************************** ok: [ubuntu.anslab.com] ok: [rocky.anslab.com] TASK [Membership Operator] *********************************************************************************** skipping: [ubuntu.anslab.com] ok: [rocky.anslab.com]
'When
' Conditional Statements With Ansible Variables
You can evaluate conditions against the magic variables, host vars, group vars.
If you have no idea about ansible variables, you can take a look at our article using the link below.
In the playbook below, I have created a variable called trigger_pipeline
and set it to no. The condition is set in a way that the task will only run when trigger_pipeline
is set to execute.
--- - name: Pipeline call hosts: all gather_facts: false vars: trigger_pipeline: no tasks: - name: Trigger Pipeline debug: msg: Running pipeline when: trigger_pipeline == "execute"
When I run the playbook, this task will be skipped.
TASK [Trigger Pipeline] ********************************************************* skipping: [rocky.anslab.com]
I can override the variable trigger_pipeline
from the command line by running the following command.
$ ansible-playbook when_condition_test.yml -e trigger_pipeline=execute TASK [Trigger Pipeline] ********************************************************************************** ok: [rocky.anslab.com] => { "msg": "Running pipeline" }
Using the IS operator, you can check if a variable is declared on not in the conditional statements.
when: trigger_pipeline is defined # TRUE only when var is defined when: trigger_pipeline is undefined # TRUE only when var is not defined
'When
' Conditional Statements With Ansible Register
Register directive is used to store the output of a task. It is similar to storing the result to a variable and later using it for further processing. Based on the data stored in the register variable, you can write conditional statements.
In the tasks below, I have created two tasks where the first task will use the shell module and run /bin/true
. The output will be stored in the variable register which is used in the second task to print.
tasks: - name: set to true shell: /bin/true register: result - name: print result debug: var: result
Sample Output:
ok: [rocky.anslab.com] => { "result": { "ansible_facts": { "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": true, "cmd": "/bin/true", "delta": "0:00:00.003477", "end": "2022-05-23 17:13:15.056197", "failed": false, "msg": "", "rc": 0, "start": "2022-05-23 17:13:15.052720", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": [] } }
You can use any of these values to create conditions. Let’s say you want to run the task only when the rc is set to zero, then you can write the condition like below.
when: result.rc == 0
Similarly based on the values available, you can write as many conditions in accordance with the use case. Below are some of the conditions based on the result variable output.
when: result.stdout != "" # Checking if stdout is not empty when: result.failed == "false" # checking if failed is set to false when: changed == "true" # Checking if the status of changed is true
'When
' Conditional Statements With Loops
You can combine the conditional statement with loops. In this case, for every item in the loop conditional statement will evaluate against the given expression.
Take a look at the play below. I am creating two users named ubuntu and rocky using the user module. The loop directive will loop against the username variable. Here the condition is written in a way that the ubuntu user should be created only in ubuntu Linux host and rocky user should be created in rocky Linux host.
- name: Create Users hosts: all gather_facts: true become: true vars: username: - ubuntu - rocky tasks: - name: Create the user user: name: "{{ item }}" state: present password: "{{ item | password_hash('sha512') }}" loop: "{{ username }}" when: (item == "ubuntu" and ansible_distribution | lower == "ubuntu") or (item == "rocky" and ansible_distribution | lower == "rocky")
As you can see from the below output, the users are created in the respective distributions in accordance with the condition.
TASK [Create the user] ******************************************************************************** skipping: [rocky.anslab.com] => (item=ubuntu) changed: [ubuntu.anslab.com] => (item=ubuntu) skipping: [ubuntu.anslab.com] => (item=rocky) changed: [rocky.anslab.com] => (item=rocky)
Conclusion
In this article we have seen what a conditional statement is and how to use the when conditional statements in Ansible to evaluate conditions and run tasks based on the outcome.
When you learn advanced concepts like roles, imports, includes, you will come to know more about conditional statements and how to use them more efficiently.
Resource: