Loops
Often you’ll want to do many things in one task, such as create a lot of users, install a lot of packages, or repeat a polling step until a certain result is reached.
This chapter is all about how to use loops in playbooks.
- name: add several users
user:
name: "{{ item }}"
state: present
groups: "wheel"
with_items:
- testuser1
- testuser2
If you have defined a YAML list in a variables file, or the ‘vars’ section, you can also do:
with_items: "{{ somelist }}"
The above would be the equivalent of:
- name: add user testuser1
user:
name: "testuser1"
state: present
groups: "wheel"
- name: add user testuser2
user:
name: "testuser2"
state: present
groups: "wheel"
The yum and apt modules use with_items to execute fewer package manager transactions.
Note that the types of items you iterate over with ‘with_items’ do not have to be simple lists of strings. If you have a list of hashes, you can reference subkeys using things like:
- name: add several users
user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups }}"
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
Also be aware that when combining when with with_items (or any other loop statement), the when statement is processed separately for each item. See The When Statement for an example.
Loops are actually a combination of things with_ + lookup(), so any lookup plugin can be used as a source for a loop, ‘items’ is lookup.
Please note that with_items flattens the first depth of the list it is provided and can yield unexpected results if you pass a list which is composed of lists. You can work around this by wrapping your nested list inside a list:
# This will run debug three times since the list is flattened
- debug:
msg: "{{ item }}"
vars:
nested_list:
- - one
- two
- three
with_items: "{{ nested_list }}"
# This will run debug once with the three items
- debug:
msg: "{{ item }}"
vars:
nested_list:
- - one
- two
- three
with_items:
- "{{ nested_list }}"
Nested Loops
Loops can be nested as well:
- name: give users access to multiple databases
mysql_user:
name: "{{ item[0] }}"
priv: "{{ item[1] }}.*:ALL"
append_privs: yes
password: "foo"
with_nested:
- [ 'alice', 'bob' ]
- [ 'clientdb', 'employeedb', 'providerdb' ]
As with the case of ‘with_items’ above, you can use previously defined variables.:
- name: here, 'users' contains the above list of employees
mysql_user:
name: "{{ item[0] }}"
priv: "{{ item[1] }}.*:ALL"
append_privs: yes
password: "foo"
with_nested:
- "{{ users }}"
- [ 'clientdb', 'employeedb', 'providerdb' ]