Hello everyone! After a long break, I finally got back to blogging. As promised, here is the next part of the Ansible Starter Guide, which will give you more information about using loops.
Dictionaries
But before we return to our loops, I would like to introduce you to dictionaries, which were only briefly mentioned in Part 5. Simply put, dictionaries are lists whose elements can have multiple fields. A simple example:
people:
- firstName: Ronald
surName: Weasley
age: 21
- firstName: Gilderoy
surName: Lockhart
age: 40
- firstName: Albus
surName: Dumbledore
age: 99
As in a simple "list", the hyphen marks the beginning of a new item. In this example, each of the two items has the fields "name", "last name", and "age".
We can also use dictionaries in loops. For example, if we wanted to print the information defined in our example, the playbook would look like this:
- hosts: localhost
vars:
people:
- firstName: Gilderoy
surName: Lockhard
age: 43
- firstName: Minerva
surName: McGonnagal
age: 67
- firstName: Albus
surName: Dumbledore
age: 99
tasks:
- name: list people
ansible.builtin.debug:
msg: "First Name: {{ item.firstName }}, Surname: {{ item.surName }}, Age: {{ item.age }}"
loop: "{{ people }}"
PLAY [localhost] ***********************************************************************************
TASK [Gathering Facts] ***********************************************************************************
ok: [localhost]
TASK [list people] ***********************************************************************************
ok: [localhost] => (item={'firstName': 'Gilderoy', 'surName': 'Lockhard', 'age': 43}) => {
"msg": "First Name: Gilderoy, surName: Lockhard, Age: 43"
}
ok: [localhost] => (item={'firstName': 'Minerva', 'surName': 'McGonnagal', 'age': 67}) => {
"msg": "First Name: Minerva, surName: McGonnagal, Age: 67"
}
ok: [localhost] => (item={'firstName': 'Albus', 'surName': 'Dumbledore', 'age': 99}) => {
"msg": "First Name: Albus, surName: Dumbledore, Age: 99"
}
PLAY RECAP ***********************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
If we use a dictionary as a loop variable, we can access the individual fields within the task with "{{ item.FIELDNAME }}}".
Loops and conditionals
If we use a loop and a condition in the same task, the condition will be validated for each loop item.
- hosts: localhost
vars:
people:
- firstName: Gilderoy
surName: Lockhard
age: 43
- firstName: Minerva
surName: McGonnagal
age: 67
- firstName: Albus
surName: Dumbledore
age: 99
tasks:
- name: list people oder than 90
ansible.builtin.debug:
msg: "{{ item.firstName }} is older than 90"
loop: "{{ people }}"
when: "item.age > 90"
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]
TASK [list people oder than 90] ***********************************************************************************************************************************************************************************
skipping: [localhost] => (item={'firstName': 'Gilderoy', 'surName': 'Lockhard', 'age': 43})
skipping: [localhost] => (item={'firstName': 'Minerva', 'surName': 'McGonnagal', 'age': 67})
ok: [localhost] => (item={'firstName': 'Albus', 'surName': 'Dumbledore', 'age': 99}) => {
"msg": "Albus: is older than 90"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As you can see, two characters (Gilderoy, Minerva) have been skipped because they do not meet the condition (age > 90). Only good old Albus is over 90 :)
Loop control
In some cases it is necessary to control the behavior of loops. For example, you can set the name of the index variable (default is "item"). This is interesting, for example, if we want to use a loop inside another loop.
Changing the name of the index variable
A loop inside another loop? Huh? Who would do that? In some cases, it may even make sense. For example, here we have a playbook that integrates a task file for multiple elements:
- hosts: all
tasks:
- name: include tasks for every list item
include: my-tasks.yml
loop:
- "A"
- "B"
- "C"
For example, the my-tasks.yml file might look like this in its simplest form:
- name: print item
ansible.builtin.debug:
msg: "{{ item }}"
During execution, the my-tasks file is included for each item listed in the loop in the playbook. The content of the loop variable is output to the my-tasks.yml file.
However, if we now want to use another task with a loop in my-tasks.yml, we have a small problem: the "item" variable is already used by the "outer" loop. This can be solved with loop_control:
- name: print item
ansible.builtin.debug:
msg: "{{ item }}"
- name: another loop
ansible.builtin.debug:
msg: "{{ item_2 }}"
loop:
- "D"
- "E"
- "F"
loop_control:
index_var: item_2
Pause between items
We can alos use the loop control to specify, for example how long ansible should pause between processing each element:
- hosts: localhost
tasks:
- name: include tasks for every list item
ansible.builtin.debug:
msg: "{{ item }}"
loop:
- "A"
- "B"
- "C"
loop_control:
pause: 5
So that's it for now. See you then!
Mow