Hello everyone! After a long break, I'm back with part 8 of the Ansible Starter Guide. In this post, I want to show you what conditionals are and how we can use them in playbooks. I decided to split this topic into two articles because the blog post would otherwise be too long. So I'll try to show you the basic function of conditionals here, and in part 2 we'll go through practical examples together.
If you don't understand some of the points or if I didn't express myself clearly, please drop me an e-mail. I'll try to clear it up :)
What are conditionals?
Conditionals are conditions to which we can link the execution of tasks. For example, we can run a task only if the target host has a certain operating system installed. When we use conditionals, we use variables and facts to define them.
A first example
Let's start with a very simple example.
- hosts: ansible-guide-1 vars: my_number: 6 tasks: - name: task with condition ansible.builtin.debug: msg: "Variable is greater then 5!!" when: "my_number > 5"
simple-conditional.yml
Conditionals are defined in the When parameter. This is a task level parameter. The when parameter can then contain a single condition or a list of conditions. The conditions are checked before the task is executed. If they match, the task is executed; if they do not, it is skipped and given the status "skipped".
What does this mean for the example playbook above? We defined a variable "my_number" above that has a value of 6. Then we defined a task that has the following condition:
"when: my_number < 5"
So we want to run the task only if the value of the "my_number" variable is greater than 5. In this case, we want the task to run. Now let's run the playbook:
ansible-playbook -i inventory.txt simple-conditional.yml
PLAY [ansible-guide-1] ****************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ansible-guide-1]
TASK [task mit condition] ****************************************************************************
ok: [ansible-guide-1] => {
"msg": "Variable is greater than 5!!"
}
PLAY RECAP ****************************************************************************
ansible-guide-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As you can see, the task ran normally. Now let's define another task:
- hosts: ansible-guide-1 vars: my_number: 6 tasks: - name: task with condition ansible.builtin.debug: msg: "Variable is greater than 5!!" when: "my_number > 5" - name: another task with condition ansible.builtin.debug: msg: "Variable is 8!!" when: "my_number == 8"
ansible-playbook -i inventory.txt simple-conditional.yml
PLAY [ansible-guide-1] ****************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ansible-guide-1]
TASK [task mit condition] ****************************************************************************
ok: [ansible-guide-1] => {
"msg": "Variable is greater than 5!!"
}
TASK [weiterer task mit condition] ****************************************************************************
skipping: [ansible-guide-1]
PLAY RECAP ****************************************************************************
ansible-guide-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
What happened now? Ansible ran our first task because its condition is true. In the second task, it checked the condition and determined that the value of the variable "my_number" is not 8, so the condition does not apply, and skipped the task. We can see this in the "skipping" output: [ansible-guide-1]"
Operators and Jinja2
We use different operators for the two conditionals: '>' and '=='. Conditionals in Ansible are based on the Jinja2 templating language. So we can use all the operators available in that language. An overview can be found here:
https://jinja.palletsprojects.com/en/3.0.x/templates/
We will be working with Jinja2 a lot more when we get to the more advanced parts of the guide.
Multiple conditionals
As mentioned above, the "when" parameter can contain either a single condition or a list. It is important to note that conditions specified in lists are always in an "AND" relationship with each other. In short, this means that each list item under "when" must be true for the task to be executed.
Let me give you a quick example:
- hosts: ansible-guide-1 vars: my_number: 5 my_text: Hello World my_other_text: Nothing. tasks: - name: task with condition ansible.builtin.debug: msg: "This task will be executed if all conditions are true" when: - "my_number == 5" - "'Hello' in my_text" - "my_other_text == 'Nothing.'"
ansible-playbook -i inventory.txt multi-conditionals.yml
PLAY [ansible-guide-1] ****************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ansible-guide-1]
TASK [task with condition] ****************************************************************************
ok: [ansible-guide-1] => {
"msg": "This task will be executed if all conditions are true"
}
PLAY RECAP ****************************************************************************
ansible-guide-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As we can see, all three conditions are true and the task is executed. Let's take a quick look at the three conditions:
- "my_number == 5".
This is the same principle as the first two examples. The test is "if my_number is 5".
- "'Hello' in my_text"
Here we use the "in" operator to check if the substring "Hello" is in the string my_text. The "in" operator checks whether there is a subset of elements in a list. Since a string is nothing more than a list of characters, we can use this here.
- "my_other_text == 'Blubb.'"
The == operator can also be applied to strings. So we check "Is the variable my_other_text equal to 'Blubb. This is also true.
AND OPERATOR
In the example above, we define conditionals in a list, which implies an AND relationship. However, we can also define AND and OR operators in a single line. We could also define the task from "multi-conditionals.yml" this way:
- hosts: ansible-guide-1 vars: my_number: 5 my_text: Hello World my_other_text: Nothing. tasks: - name: task with condition ansible.builtin.debug: msg: "This task will be executed if all conditions are true" when: - "my_number == 5 and 'Hello' in my_text and my_other_text == 'Nothing.'"
and-onelne.yml
If we run this now, we should get the same result as above.
AND and OR combined
Things get a little more complicated when we want to combine AND and OR:
and-or.yml
- hosts: ansible-guide-1 vars: my_number: 5 my_text: Hello World my_other_text: Nothing. tasks: - name: task with condition ansible.builtin.debug: msg: "This task will be executed if all conditions are true" when: - "my_text == 'Hello World'" - "my_number == 5 or my_number > 3"
So we have defined two conditionals in a list. As we have learned, both list items must be true at the end for the task to be performed. The above example can be rewritten as follows:
If my_text is 'Hello world' AND my_number is 5 or greater than 3.
If we now run the playbook, the task will be executed:
ansible-playbook -i inventory.txt and-or.yml
PLAY [ansible-guide-1] ****************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ansbible-guide-1]
TASK [task mit condition] ****************************************************************************
ok: [ansible-guide-1] => {
"msg": "This task will be executed if all conditions are true"
}
PLAY RECAP ****************************************************************************
ansible-guide-1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As expected, the task runs. Now let's verify this by setting the value of my_number to 2:
- hosts: ansible-guide-1 vars: my_number: 2 my_text: Hello World my_other_text: Nothing. tasks: - name: task mit condition ansible.builtin.debug: msg: "This task will be executed if all conditions are true" when: - "my_text == 'Hello World" - "my_number == 5 or my_number > 3"
ansible-playbook -i inventory.txt and-or.yml
PLAY [ansible-guide-1] ****************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ansible-guide-1]
TASK [task with condition] ****************************************************************************
skipping: [ansible-guide-1]
PLAY RECAP ****************************************************************************
ansible-guide-1 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Try it out!
The best thing to do is to try it out for yourself and vary the variable values as you wish.
Now that we've looked at how conditionals work in this part, I'd like to go through some practical use cases with you in the next part.
I hope you enjoyed it again and look forward to your feedback!
Regards.
Mow