Looping Over List of Dictionaries
A loop’s items don’t have to be plain values like "apple". In practice, they’re very often dictionaries — each iteration carrying several related pieces of data at once, not just one.
Looping Over A List Of Dictionaries
loop:
- name: alice
role: admin
- name: bob
role: viewerEach item in this loop is now a small dictionary, with two fields instead of one plain value.
Accessing Fields With item['key']
Bracket notation, consistent with every other dictionary access in this course:
- name: Dict Loop Demo
hosts: servers
tasks:
- name: Print user info
ansible.builtin.debug:
msg: "{{ item['name'] }} has role {{ item['role'] }}"
loop:
- name: alice
role: admin
- name: bob
role: viewerok: [ubuntu] => (item={'name': 'alice', 'role': 'admin'}) => {
"msg": "alice has role admin"
}
ok: [ubuntu] => (item={'name': 'bob', 'role': 'viewer'}) => {
"msg": "bob has role viewer"
}A Realistic Example: Creating Multiple Users
Real playbooks loop over a variable, not an inline list written directly into the task — exactly the same separation-of-data-from-logic principle from the variables section, now applied to loop data:
- name: Create Users
hosts: servers
vars:
users:
- name: alice
role: admin
- name: bob
role: viewer
- name: carol
role: editor
tasks:
- name: "Report user creation:"
ansible.builtin.debug:
msg: "Would create user '{{ item['name'] }}' with role '{{ item['role'] }}'"
loop: "{{ users }}"In a real deployment, that debug task would be ansible.builtin.user, actually creating each account — the loop mechanics controlling which users get processed are identical either way.
A Gotcha: Missing Keys Across Items
Real data isn’t always perfectly consistent. What happens when one entry is missing a key another one has?
loop:
- name: alice
role: admin
- name: bobmsg: "{{ item['name'] }} has role {{ item['role'] }}"alice’s iteration succeeds fine. bob’s fails — there’s no role key on that dictionary at all, and accessing a genuinely missing dictionary key with item['role'] raises an error rather than quietly returning something empty. Ansible runs every item in the loop regardless — a failure on one iteration doesn’t stop the rest from being attempted — but the task as a whole is still reported failed once any single iteration fails.
The fix is exactly the filter you’d expect from the manipulating-data section:
msg: "{{ item['name'] }} has role {{ item['role'] | default('unknown') }}"alice has role admin
bob has role unknown| default(...) handles a missing key here exactly the way it handled a missing variable back in that chapter — the mechanism is identical, just applied to a dictionary key inside a loop instead of a standalone variable.
Best Practices
- Use bracket notation (
item['key']) consistently, exactly as recommended for facts and every other dictionary access in this course. - Loop over a variable, not an inline list, in anything beyond a quick throwaway example — keep the data separate from the task logic, the same way
vars_filesandhost_varskept configuration separate from playbook structure. - Pair
item['field']with| default(...)whenever the entries in a loop’s list might not all share exactly the same keys — a single missing key shouldn’t have to fail an entire task’s worth of otherwise-fine iterations.