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

Posted by

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 ]
    guest
    0 Comments
    Inline Feedbacks
    View all comments
    0
    Would love your thoughts, please comment.x
    ()
    x