Functionality - For Each

Minimum PPA Version: 2.10.0

Summary

The for_each loop allows you to:

  • Repeat a step or action for each item in a list
  • Give the current loop item a friendly variable name
  • Skip to the next item early if a certain condition is met (optional)

You can use for_each loops to repeat both steps & actions.

It's possible to have repeated actions inside repeated steps.

Configuration

Items

Either a list of values to loop over, or a variable whose value is a list.

for_each:
  items: groups
  name: current_group

Name

Variable name to assign to the current loop item.

This cannot be the same as anything previously saved or set.

for_each:
  items: groups
  name: current_group

This variable is removed once the loop has completed

Skip [optional]

Optional variable name to use as a skip flag.

When supplied this variable will be created with a default value of false.

If an action inside the step sets the flag to true:

  • No further actions in the step will be run for the current loop item
  • The step will immediately skip to the next loop item & start at the top
for_each:
  items: groups
  name: current_group
  skip: keep_group

This cannot be the same as anything previously saved or set.

The skip key is only valid in step loops

This variable is removed once the loop has completed

Loop Counters

PPA makes counter & index variables available inside a loop.

The index variables start at 0, & the counter variables start at 1.

They are both incremented by 1 each time through the loop.

These can be used to:

  • Display how many times a loop has run
  • Compare the current loop counter with the total number of items
  • Cross-reference the current loop item with another item from a different list

Step Counters

  • step_index
  • step_counter

Action Counters

  • action_index
  • action_counter

Counter variables are removed once their respective loop has completed

Examples

1 - Looped Step

This example uses for_each to delete each Active Directory group in a list.

The list is stored in a variable called groups which was saved by a previous action.

- name: Delete Groups
  for_each:
    items: groups
    name: current_group
  actions:

    - active_directory.groups.delete:
      load:
        distinguishedName: current_group.distinguishedName
        domain_controller: domain_controller

2 - Looped Step With Skip

This example uses for_each to:

  • Loop over each Active Directory group in a list
  • Ask the user whether the group should exist
  • Either delete the group or skip to the next one

The step_counter variable is used to show the user how many groups they have reviewed.

As with the previous example, the groups variable has been saved by a previous action.

If the user selects Yes the keep_group variable is set to true, & the loop will skip.

- name: Delete/Skip Groups
  for_each:
    items: groups
    name: current_group
    skip: keep_group
  actions:

    - ppa.ui.input_confirm:
        text: "{{ step_counter }} - should group {{ current_group.cn }} exist?"
      save: keep_group

    - active_directory.groups.delete:
      load:
        distinguishedName: current_group.distinguishedName
        domain_controller: domain_controller

    - ppa.ui.output_info:
        text: Group {{ current_group.cn }} has been deleted.

3 - Looped Action

This example does the same as example 1, but with a looped action rather than a looped step.

- name: Delete Groups
  actions:

    - active_directory.groups.delete:
      load:
        distinguishedName: current_group.distinguishedName
        domain_controller: domain_controller
      for_each:
        items: groups
        name: current_group

4 - Looped Step & Action

This example uses for_each in both a step & an action to remove many users from many groups.

The step loops over a list of users, & the action loops over a list of groups.

Both were saved by previous actions.

- name: Remove Users From Groups
  for_each:
    items: users
    name: current_user
  actions:

    - ppa.ui.output_progress:
        text: Removing {{ current_user.cn }} from {{ groups | length }} groups...
        percent: null
        element_id: removing

    - active_directory.users.remove_from_group:
      load:
        user_distinguishedName: current_user.distinguishedName
        group_distinguishedName: current_group.distinguishedName
        domain_controller: domain_controller
      for_each:
        items: groups
        name: current_group

    - ppa.ui.output_progress:
        text: Removed {{ current_user.cn }} from {{ groups | length }} groups
        percent: 100
        element_id: removing

Action Output

Saving dynamic variables works differently for actions with a for_each loop.

Standard

Actions without a loop run once & output a single piece of data.

Regardless of the type (list, dictionary, string, etc), there will only be one output.

Looped

Actions with a for_each loop will nearly always run more than once.

Each time the action is run its output is added to a list.

The contents of a saved variable in this scenario will be a list of all the outputs.