How to Loop Over a Dictionary in Ansible (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: database-automation
How to loop over dictionaries in Ansible using dict2items, with_dict, and loop. Iterate over key-value pairs in playbooks with practical examples.
How to Loop Over a Dictionary in Ansible (Complete Guide)
Looping over dictionaries (key-value pairs) is essential for dynamic Ansible playbooks. Here are all the methods, from modern to legacy.
See also: Ansible combine Filter: Merge Dictionaries & Override Defaults (Guide)
Method 1: dict2items Filter (Recommended)
vars:
users:
alice:
role: admin
shell: /bin/bash
bob:
role: developer
shell: /bin/zsh
tasks:
- name: Create users from dictionary
ansible.builtin.user:
name: "{{ item.key }}"
shell: "{{ item.value.shell }}"
groups: "{{ item.value.role }}"
loop: "{{ users | dict2items }}"
Each item has .key and .value.
Method 2: loop with dict2items and Filters
vars:
packages:
nginx: present
vim: present
cups: absent
tasks:
- name: Manage packages
ansible.builtin.apt:
name: "{{ item.key }}"
state: "{{ item.value }}"
loop: "{{ packages | dict2items }}"
See also: Ansible no_log: Hide Sensitive Data in Playbook Output (Guide)
Method 3: Nested Dictionary
vars:
app_config:
database:
host: db.example.com
port: 5432
cache:
host: redis.example.com
port: 6379
tasks:
- name: Show all config sections
ansible.builtin.debug:
msg: "{{ item.key }}: {{ item.value.host }}:{{ item.value.port }}"
loop: "{{ app_config | dict2items }}"
Method 4: with_dict (Legacy)
# Still works but dict2items is preferred
- name: Create directories
ansible.builtin.file:
path: "{{ item.value.path }}"
owner: "{{ item.value.owner }}"
state: directory
with_dict: "{{ directories }}"
See also: How to Check if a File Exists in Ansible (4 Methods)
Filter Dictionary Before Looping
vars:
services:
nginx: { enabled: true, port: 80 }
debug_server: { enabled: false, port: 9999 }
api: { enabled: true, port: 8080 }
tasks:
- name: Start only enabled services
ansible.builtin.debug:
msg: "Starting {{ item.key }} on port {{ item.value.port }}"
loop: "{{ services | dict2items | selectattr('value.enabled') | list }}"
Convert Between Dict and List
# Dict to list of items
"{{ my_dict | dict2items }}"
# Result: [{"key": "a", "value": 1}, {"key": "b", "value": 2}]
# List of items back to dict
"{{ my_list | items2dict }}"
# Custom key/value names
"{{ my_list | items2dict(key_name='name', value_name='config') }}"
FAQ
How do I loop over a dictionary in Ansible?
Use the dict2items filter: loop: "{{ my_dict | dict2items }}". Each item provides .key and .value for the dictionary entry.
What is the difference between dict2items and with_dict?
dict2items is the modern approach used with loop. with_dict is the legacy syntax. Both produce the same result, but dict2items is more flexible and composable with other filters.
Can I filter a dictionary before looping?
Yes. Chain filters: loop: "{{ my_dict | dict2items | selectattr('value.enabled') | list }}" loops only over entries where enabled is true.
Related Articles
• Ansible Variables: Complete Guide • Ansible Jinja2 Filters Reference • Ansible Playbook GuideAdvanced Dictionary Looping
Nested Dictionary with dict2items
- name: Manage users from dictionary
hosts: all
become: true
vars:
users:
alice:
uid: 1001
shell: /bin/bash
groups: ["wheel", "developers"]
bob:
uid: 1002
shell: /bin/zsh
groups: ["developers"]
tasks:
- name: Create users from dictionary
ansible.builtin.user:
name: "{{ item.key }}"
uid: "{{ item.value.uid }}"
shell: "{{ item.value.shell }}"
groups: "{{ item.value.groups }}"
state: present
loop: "{{ users | dict2items }}"
- name: Show user details
ansible.builtin.debug:
msg: "{{ item.key }}: UID={{ item.value.uid }}, Shell={{ item.value.shell }}"
loop: "{{ users | dict2items }}"
Filter Dictionary Items
- name: Process only users with bash shell
ansible.builtin.debug:
msg: "Bash user: {{ item.key }}"
loop: "{{ users | dict2items | selectattr('value.shell', 'equalto', '/bin/bash') }}"
Combine Dictionaries
- name: Merge default and custom settings
ansible.builtin.set_fact:
final_config: "{{ default_config | combine(custom_config, recursive=True) }}"
vars:
default_config:
timeout: 30
retries: 3
custom_config:
timeout: 60
FAQ
What is the difference between dict2items and with_dict?
dict2items is a Jinja2 filter used with loop:. with_dict is the older lookup-based syntax. Both produce item.key and item.value. The loop: + dict2items approach is recommended for new playbooks.
Can I loop over a dictionary and a list at the same time?
Use ansible.builtin.subelements or nested loops with loop: "{{ dict | dict2items | subelements('value.list_field') }}".
How do I convert a list to a dictionary?
Use the items2dict filter: {{ list_of_dicts | items2dict(key_name='name', value_name='value') }}.
Category: database-automation