Ansible – How to loop and iteration executations in Ansible Playbook with Example (Part-8)

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 ]

    Related Posts

    Ansible Terminology

    Here are simplified one-line explanations for key Ansible terminology: Mohammad Gufran Jahangir

    Read More

    Ansible interview questions that are commonly asked in interviews

    Basic Questions Intermediate Questions How does Ansible handle authentication? What is the purpose of ansible.cfg? What are handlers in Ansible? What is Ansible Galaxy? Explain the difference…

    Read More

    Ansible Playbook for Patching & Upgrading Different Services

    Playbook for Patching & Upgrading Linux APP Servers reating an Ansible playbook for patching and upgrading Linux application servers involves several steps. Below is a detailed playbook,…

    Read More

    Ansible – Vault in Ansible (Part-11)

    What is Ansible Vault? Ansible Vault is a feature within Ansible that allows you to keep sensitive data, such as passwords, keys, and other secrets, secure. Vault…

    Read More

    Ansible – Inventory variables in Ansible (Part-11)

    What are Inventory Variables in Ansible? Inventory variables in Ansible are key-value pairs that provide additional context and configuration for hosts and groups defined in your inventory….

    Read More

    Ansible – How Default Ansible Variables Work (Part-10)

    How Default Variables Work 1.Default Variables in a Role Default variables for a role are defined in the defaults/main.yml file. These variables provide baseline values that the…

    Read More
    guest
    0 Comments
    Oldest
    Newest Most Voted
    0
    Would love your thoughts, please comment.x
    ()
    x