Looping in Ansible allows you to repeat a task multiple times with different inputs. This feature is particularly useful for managing lists of items, such as packages to install, users to create, or files to copy. Ansible provides several ways to implement loops, each suitable for different scenarios.
Basic Looping with loop
The most straightforward way to perform a loop in Ansible is by using the loop
keyword.
Example: Installing Multiple Packages
- name: Install multiple packages
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- apache2
- php
- mysql-server
Looping with with_items
Before the introduction of the loop
keyword, with_items
was commonly used. It’s still supported for backward compatibility.
Example: Creating Multiple Users
- name: Create multiple users
ansible.builtin.user:
name: "{{ item }}"
state: present
with_items:
- user1
- user2
- user3
Looping with Dictionaries
You can loop over dictionaries (hashes) to perform tasks with key-value pairs.
Example: Adding Multiple Users with Attributes
- name: Add multiple users with attributes
ansible.builtin.user:
name: "{{ item.name }}"
state: present
shell: "{{ item.shell }}"
loop:
- { name: 'user1', shell: '/bin/bash' }
- { name: 'user2', shell: '/bin/zsh' }
Nested Loops
Ansible supports nested loops, allowing you to iterate over multiple lists simultaneously.
Example: Assigning Users to Groups
- name: Assign users to groups
ansible.builtin.user:
name: "{{ item.0 }}"
groups: "{{ item.1 }}"
loop: "{{ query('nested', users, groups) }}"
vars:
users:
- user1
- user2
groups:
- group1
- group2
Loop Control with loop_control
You can control the loop behavior using the loop_control
keyword. This is useful for customizing the display of loop output.
Example: Customizing Loop Output
- name: Install multiple packages
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- apache2
- php
- mysql-server
loop_control:
label: "{{ item }}"
Looping with with_*
Lookup Plugins
Ansible provides several with_*
lookup plugins for more advanced looping scenarios.
with_fileglob
:Loops over files matching a pattern.Example: Copying Multiple Files
- name: Copy files matching a pattern
ansible.builtin.copy:
src: "{{ item }}"
dest: /destination/path/
with_fileglob:
- /source/path/*.conf
with_lines
:
Loops over the lines of a command’s output.
Example: Looping Over Command Output
- name: Add users from command output
ansible.builtin.user:
name: "{{ item }}"
state: present
with_lines: "cat /path/to/userlist.txt"
with_items
:
Loops over a list of items.
Example: Creating Directories
- name: Create directories
ansible.builtin.file:
path: "/var/www/{{ item }}"
state: directory
with_items:
- site1
- site2
- site3
Looping with include_tasks
You can use loops with include_tasks
to include and execute another task file multiple times with different inputs.
Example: Including a Task File with Loop Variables
Main Playbook:
- name: Include task file with loop
include_tasks: create_users.yml
loop:
- { name: 'user1', uid: 1001 }
- { name: 'user2', uid: 1002 }
Task File (create_users.yml
):
- name: Create user
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
Example Playbook Code
---
- name: Update web servers
hosts: web
vars:
listvar1:
- 'a'
- 'b'
- 'c'
tasks:
- name: Install Apache in centos7
ansible.builtin.yum:
name: "{{ item }}"
state: latest
with_items:
- git
- httpd
- ntp
- name: Copy index.html
ansible.builtin.copy:
src: index.html
dest: /var/www/html/index.html
- name: Starting a Apache Server
ansible.builtin.service:
name: httpd
state: started
- command: echo {{ item }}
loop: [ 0, 2, 4, 6, 8, 10 ]
- command: echo {{ item }}
loop: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
- name: Remove users Chuck and Craig from the system.
user:
name: "{{ item }}"
state: absent
remove: yes
with_items:
- chuck
- craig
- shell: echo "nested test a={{ item[0] }} b={{ item[1] }} c={{ item[2] }}"
with_nested:
- [ 'red', 'blue', 'green' ]
- [ 1, 2, 3 ]
- [ 'up', 'down', 'strange']
- shell: echo "nested test a={{ item[0] }} b={{ item[1] }}"
with_nested:
- listvar1
- [ 1, 2, 3 ]
# EXAMPLE
- name: Install common software requirements
apt: pkg={{ item }} state=installed
with_items:
- git
- htop
- vim
# EXAMPLE
tasks:
- command: echo {{ item }}
loop: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
# EXAMPLE
- command: echo {{ item }}
loop: "{{ mylist|default([]) }}"
when: item > 5
# EXAMPLE
- command: echo {{ item.key }}
loop: "{{ query('dict', mydict|default({})) }}"
when: item.value > 5
# EXAMPLE
- name: Remove users �Chuck� and �Craig� from the system.
user:
name: "{{ item }}"
state: absent
remove: yes
with_items:
- chuck
- craig
# EXAMPLE
---
# this is a trivial example of how to do a nested loop.
- hosts: all
tasks:
- shell: echo "nested test a={{ item[0] }} b={{ item[1] }} c={{ item[2] }}"
with_nested:
- [ 'red', 'blue', 'green' ]
- [ 1, 2, 3 ]
- [ 'up', 'down', 'strange']
# EXAMPLE
# you can reference a raw variable name without putting it in {{ brackets }}
- hosts: all
vars:
listvar1:
- 'a'
- 'b'
- 'c'
tasks:
- shell: echo "nested test a={{ item[0] }} b={{ item[1] }}"
with_nested:
- listvar1
- [ 1, 2, 3 ]