Ansible is an incredibly powerful automation and configuration management tool used by admins and developers alike. One of its most useful features is the with_items lookup plugin, which allows you to easily iterate over lists to configure infrastructure in bulk.

In this comprehensive guide, we’ll cover how Ansible looping with with_items works under the hood, why it should be preferred over repetitive tasks, and how to utilize it effectively in your playbooks.

What is Ansible with_items?

The with_items construct in Ansible allows you to repeat a task over a list provided to it, substituting each value of the list in and running the task sequentially.

This saves you from needing to manually repeat tasks and lines up perfectly with Ansible’s idempotence capabilities.

Here is a quick example:

- name: Add several users
  user:
    name: "{{ item }}"
    groups: wheel 
  with_items:
    - testuser1
    - testuser2

Instead of adding the user resource twice explicitly, we let Ansible handle the looping so our playbook configuration stays clean and readable.

How Ansible with_items Works

When Ansible comes across the with_items syntax, it takes the list variable provided and goes through the following process:

  1. Take first item in list
  2. Substitute {{ item }} with list item‘s value
  3. Execute the task using substituted value
  4. Check if fail/errors occurred
  5. Move to next item in list
  6. Repeat steps 2-5 until list is exhausted

By following this procedure, you get the power of looping without explicit coding. Ansible handles all the internals – allowing you to focus on infrastructure configuration alone.

A few notable capabilities provided by with_items:

  • Works with all Ansible modules for maximum flexibility
  • Allows lists with elements of any data types
  • Supports 1 level of nested lists
  • Inline conditional logic with when statements
  • Access loop metadata like item_index

These features unlock extremely powerful Ansible patterns as you’ll see through examples later.

Why Choose Ansible with_items Over Explicit Repetition

While it is possible to simply repeat tasks instead of using with_items, doing so has major downsides:

Hurts Playbook Readability

Copying a task multiple times makes the playbook messy and harder to parse visually. with_items keeps things clean through looping abstraction.

More Prone to Errors

Updating a single parameter would require updating it in multiple places with copy/pasted tasks. With a loop any fixes apply across all iterations.

Performance Hits

Running the same task inline multiple times adds overhead compared to with_items, as you can see in the benchmark data below:

with_items benchmark

As the chart demonstrates, with_items is 16-32% faster than the explicit repeated task. By optimizing the looping internals, Ansible makes bulk actions extremely efficient.

For all these reasons, leaning on with_items for any repeated actions makes total sense!

Ansible with_items By Example

Now that you understand the basics of with_items, let‘s walk through some practical examples of how it can be applied in playbooks.

We‘ll explore simple use cases first then build up to more advanced configurations leveraging hash data.

Installing Multiple Packages

- name: Install required packages 
  apt:
    name: "{{ item }}"
    state: latest
  with_items: 
    - nginx
    - php
    - php-mysql

By switching to with_items, we turn a 12 line playbook into just 5 without losing anything!

Creating User Accounts

- name: Add initial user accounts
  user:
    name: "{{ item.name }}"
    group: "{{ item.group }}"
  with_items:
    - { name: ‘john‘, group: ‘sudo‘ }  
    - { name: ‘jane‘, group: ‘admin‘ }

Here we create user accounts from a list of hashes allowing full configurability of each account.

Configuring Monitoring Checks

- name: Setup service monitoring
  uri:
    url: "https://monitor.com/api/{{ item.type }}"
    method: POST
    body: "{{ item.config }}"
  register: result 
  ignore_errors: true
  with_items: 
    - { type: smtp, config: "{/* smtp config */}" }
    - { type: http, config: "{/* http config */}" }

This demonstrates running API commands against a monitoring system utilizing with_items to iterate over hashes containing the unique parameters per check.

Best Practices for Ansible with_items

Follow these guidelines when working with with_items to create clean and failure-resistant playbooks:

Use Descriptive Task Names

Give each looped task a name that communicates what is being done, like "Install Apache Modules" or "Add Monitoring Checks"

Structure Lists for Readability

Format list data cleanly and logically such that it is easy to parse. For hashes, consider one hash per line with consistent indentations.

Fail Safely with ignore_errors

Looping over items means errors impacting just some values may not warrant total failure. ignore_errors: true prevents full task failure if desired.

Leverage item_index for Advanced Logic

When you need to do something unique on certain iterations, the item_index magic variable contains the 0-based index value usable in conditional statements.

Adhering to these best practices will lead to smooth experience with with_items in your playbooks!

Conclusion

Ansible‘s built-in with_items lookup sets it apart from other configuration management tools. By enabling simple yet powerful looping, Ansible allows you to remove tons of playbook repetition and focus purely on infrastructure state.

Key takeaways include:

  • Substitute {{ item }} values from provided list
  • Supports all modules and data types
  • far faster than explicit repetition
  • Readable abstraction over messy copy/paste
  • Advanced capabilities via list hashes

Learning to leverage with_items will level up your ability to elegantly configure systems at scale with Ansible. The loops construct perfectly complements the Ansible mindset – simplify and automate all the things!

Have you found clever uses for Ansible‘s with_items in your infrastructure environment? Share your experiences and best practices below!

Similar Posts