Skip to main content

Using Loops and Items

· loading · loading ·
Table of Contents

Using Loops and Items
#

  • Some modules enable you to provide a list that needs to be processed.
  • Many modules don’t, and in these cases, it makes sense to use a loop mechanism to iterate over a list of items.
  • Take, for instance, the yum module. While specifying the names of packages, you can use a list of packages.
  • If, however, you want to do something similar for the service module, you find out that this is not possible.
  • That is where loops come in.

Working with Loops
#

Install software packages using the yum module and then ensures that services installed from these packages are started using the service module:

    ---
    - name: install and start services
      hosts: ansible1
      tasks:
      - name: install packages
        yum:
          name:
          - vsftpd
          - httpd
          - samba
          state: latest
      - name: start the services
        service:
          name: "{{ item }}"
          state: started
          enabled: yes
        loop:
        - vsftpd
        - httpd
        - smb
  • A loop is defined at the same level as the service module.

  • The loop has a list of services in a list (array) statement

  • Items in the loop can be accessed by using the system internal variable item.

  • At no place in the playbook is there a definition of the variable item; the loop takes care of this.

  • When considering whether to use a loop, you should first investigate whether a module offers support for providing lists as values to the keys that are used.

  • If this is the case, just provide a list, as all items in the list can be considered in one run of the module.

  • If not, define the list using loop and provide "{{ item }}" as the value to the key.

  • When using loop, the module is activated again on each iteration.

Using Loops on Variables
#

  • Although it’s possible to define a loop within a task, it’s not the most elegant way.
  • To create a flexible environment where static code is separated from dynamic site-specific parameters, it’s a much better idea to define loops outside the static code, in variables.
  • When you define loops within a variable, all the normal rules for working with variables apply: The variables can be defined in the play header, using an include file, or as host/hostgroup variables.

Include the loop from a variable:

    ---
    - name: install and start services
      hosts: ansible1
      vars:
        services:
        - vsftpd
        - httpd
        - smb
      tasks:
      - name: install packages
        yum:
          name:
          - vsftpd
          - httpd
          - samba
          state: latest
      - name: start the services
        service:
          name: "{{ item }}"
          state: started
          enabled: yes
        loop: "{{ services }}"

Using Loops on Multivalued Variables
#

An item can be a simple list, but it can also be presented as a multivalued variable, as long as the multivalued variable is presented as a list.

Use variables that are imported from the file vars/users-list:

users:
  - username: linda
    homedir: /home/linda
    shell: /bin/bash
    groups: wheel
  - username: lisa
    homedir: /home/lisa
    shell: /bin/bash
    groups: users
  - username: anna
    homedir: /home/anna
    shell: /bin/bash
    groups: users

Use the list in a playbook:

    ---
    - name: create users using a loop from a list
      hosts: ansible1
      vars_files: vars/users-list
      tasks:
      - name: create users
        user:
          name: "{{ item.username }}"
          state: present
          groups: "{{ item.groups }}"
          shell: "{{ item.shell }}"
        loop: "{{ users }}"
  • Working with multivalued variables is possible, but the variables in that case must be presented as a list; using dictionaries is not supported.
  • The only way to loop over dictionaries is to use the dict2items filter.
  • Use of filters is not included in the RHCE topics and for that reason is not explained further here.
  • You can look up “Iterating over a dictionary” in the Ansible documentation for more information.

Understanding with_items
#

  • Since Ansible 2.5, using loop has been the command way to iterate over the values in a list.
  • In earlier versions of Ansible, the with_keyword statement was used instead.
  • In this approach, the keyword is replaced with the name of an Ansible look-up plug-in, but the rest of the syntax is very common.
  • Will be deprecated in a future version of Ansible.

With_keyword Options Overview with_items

  • Used like loop to iterate over values in a list with_file
  • Used to iterate over a list of filenames on the control node with_sequence
  • Used to generate a list of values based on a numeric sequence

Loop over a list using with_keyword:

    ---
    - name: install and start services
      hosts: ansible1
      vars:
        services:
        - vsftpd
        - httpd
        - smb
      tasks:
      - name: install packages
        yum:
          name:
          - vsftpd
          - httpd
          - samba
          state: latest
      - name: start the services
        service:
          name: "{{ item }}"
          state: started
          enabled: yes
        with_items: "{{ services }}"

Lab: Working with loop
#

1. Use your editor to define a variables file with the name vars/packages and the following contents:

packages:
- name: httpd
  state: absent
- name: vsftpd
  state: installed
- name: mysql-server
  state: latest

2. Use your editor to define a playbook with the name exercise71.yaml and create the play header:

- name: manage packages using a loop from a list
  hosts: ansible1
  vars_files: vars/packages
  tasks:

3. Continue the playbook by adding the yum task that will manage the packages, using the packages variable as defined in the vars/packages variable include file:

- name: manage packages using a loop from a list
  hosts: ansible1
  vars_files: vars/packages
  tasks:
  - name: install packages
    yum:
      name: "{{ item.name }}"
      state: "{{ item.state }}"
    loop: "{{ packages }}"

4. Run the playbook using ansible-playbook exercise71.yaml, and observe the results. In the results you should see which packages it is trying to manage and in which state it is trying to get the packages.