AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Error 'Use loop or with_': Fix Deprecated with_items Syntax

By Luca Berton · Published 2024-01-01 · Category: installation

Fix Ansible deprecation error about loop vs with_items. Migrate from with_items, with_dict, with_nested to modern loop syntax with practical before/after.

Ansible Error 'Use loop or with_': Fix Deprecated with_items Syntax

Introduction

Ansible, a powerful IT automation tool, continually evolves to improve the efficiency and readability of playbooks. One such evolution is the introduction of the use-loop rule in Ansible Lint, aiming to discourage the use of with_xxx as a looping mechanism in favor of the more versatile loop.

The Rule in Action

The use-loop rule emphasizes the preference for the loop construct over the older with_xxx syntax. While the latter is not deprecated, adopting the loop syntax is encouraged for a future-proof playbook.

When applied, the rule generates messages highlighting instances where with_xxx is used for looping, nudging developers towards the more modern and flexible loop alternative. For example, it may produce warnings such as: • use-loop[play]: The play uses strategy: free. • use-loop[task]: Using run_once may behave differently if the strategy is set to free.

Understanding the Motivation

The use-loop rule aligns with Ansible's commitment to staying current and streamlining syntax for better code maintenance. By discouraging the use of with_xxx in favor of loop, the rule prompts users to embrace a more uniform and expressive approach to looping in playbooks.

Community Dialogue

The introduction of this rule sparked discussions within the Ansible community. Some contributors expressed concerns about the rule being controversial, as the preference between with_xxx and loop can be subjective and dependent on individual taste and style. The rule's default inclusion in the production profile was also debated, with suggestions to make it optional to accommodate diverse preferences.

Real-World Considerations

In the discussions, real-world examples were raised to illustrate scenarios where the with_xxx syntax might be more readable or efficient than its loop counterpart. The community emphasized the need for a comprehensive list of examples to guide the implementation of this rule effectively.

Future Implications

While the use-loop rule is currently an opt-in feature, its potential inclusion in default profiles and the ongoing discussions within the Ansible community highlight the importance of staying informed about evolving best practices in playbook development.

Links

• https://github.com/ansible/ansible-lint/issues/2204

Conclusion

As Ansible evolves, so do its best practices. The use-loop rule in Ansible Lint is a testament to the community's commitment to enhancing playbook readability and maintainability. Users are encouraged to engage in discussions, share real-world examples, and adapt to emerging conventions to create efficient and future-proof Ansible playbooks.

See also: Publishing Ansible Collections to Ansible Galaxy and Automation Hub

The Fix

Replace deprecated with_* syntax with modern loop:

# OLD (deprecated)
- name: Install packages
  apt:
    name: "{{ item }}"
  with_items:
    - nginx
    - curl

# NEW (modern) - name: Install packages apt: name: "{{ item }}" loop: - nginx - curl

Migration Examples

with_items → loop

# Before
- debug: msg="{{ item }}"
  with_items: "{{ my_list }}"

# After - debug: msg="{{ item }}" loop: "{{ my_list }}"

with_dict → loop + dict2items

# Before
- debug: msg="{{ item.key }}={{ item.value }}"
  with_dict: "{{ my_dict }}"

# After - debug: msg="{{ item.key }}={{ item.value }}" loop: "{{ my_dict | dict2items }}"

with_nested → loop + product

# Before
- debug: msg="{{ item.0 }}-{{ item.1 }}"
  with_nested:
    - [a, b]
    - [1, 2]

# After - debug: msg="{{ item.0 }}-{{ item.1 }}" loop: "{{ ['a','b'] | product([1,2]) | list }}"

with_fileglob → loop + fileglob lookup

# Before
- copy: src="{{ item }}" dest=/etc/configs/
  with_fileglob: "files/*.conf"

# After - copy: src="{{ item }}" dest=/etc/configs/ loop: "{{ lookup('fileglob', 'files/*.conf', wantlist=True) }}"

with_sequence → loop + range

# Before
- debug: msg="user{{ item }}"
  with_sequence: start=1 end=5

# After - debug: msg="user{{ item }}" loop: "{{ range(1, 6) | list }}"

with_subelements → loop + subelements

# Before
- debug: msg="{{ item.0.name }}-{{ item.1 }}"
  with_subelements:
    - "{{ users }}"
    - groups

# After - debug: msg="{{ item.0.name }}-{{ item.1 }}" loop: "{{ users | subelements('groups') }}"

See also: Ansible troubleshooting - Error parser-error

loop_control

- name: Process with custom variable
  debug:
    msg: "{{ server.name }}"
  loop: "{{ servers }}"
  loop_control:
    loop_var: server       # Custom variable name
    label: "{{ server.name }}"  # Shorter output
    index_var: idx         # Loop counter
    pause: 1               # Delay between iterations

Quick Reference

| Old Syntax | New Syntax | |-----------|------------| | with_items | loop | | with_list | loop | | with_dict | loop: dict2items | | with_nested | loop: product() | | with_sequence | loop: range() | | with_fileglob | loop: fileglob lookup | | with_subelements | loop: subelements() | | with_together | loop: zip() | | with_indexed_items | loop + loop_control.index_var |

See also: ARA Records Ansible: Playbook Reporting & History (Complete Guide)

FAQ

Is with_items completely removed?

Not yet — it's deprecated and will show warnings. It still works but should be migrated to loop for forward compatibility.

Can I pass a list directly to modules?

Many modules accept lists natively (faster than looping):

# Better than loop — single transaction
- apt:
    name:
      - nginx
      - curl
      - git
    state: present

Related Articles

with_items vs loop in Ansible

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home