Loop over roles with a list

Hi, I want to loop over a role with a var like that, but the loop below does not work, because it cannot find a definition for item.

array:
 - name: "a name"
   path: "/path/"

- name: "Do Role"
  roles:
    - role: my_role
      vars:
        - name: {{ item.name }}
        - path: {{ item.path }}
      loop: "{{ array }}"
  

I could not find any example in the official docs and other sources still use with_items which is deprciated. If anyone could point me to the correct documentation or reply with a possible solution, that would be wonderful.

1 Like

I have tried the following, which is working for me now. Is this good practice?

1 Like
  • with_items is not deprecated … its just that those writing the docs do not like to show more than one way to do things so they moved everything to use loop, which is the equivalent of with_list, with_ also has ‘magic’ which is sometimes hard to debug so the loop syntax is more explicit.

  • roles and import_role are run at ‘parse/compile time’ so they cannot support loops, that is what include_role is for, so it’s not ‘good practice’ but ‘only way to do it’.

5 Likes

Hey,

You can’t use loops on imported roles (as in static reuse), and using roles: keyword at play level means static imports:

When you use the roles option at the play level, Ansible treats the roles as static imports and processes them during playbook parsing.

(from Roles — Ansible Documentation)

And is the same as using import_role at task level:

  tasks:
    - name: some task
      import_role:
        name: some_role

I’m not sure why you can’t loop over items with static imports; something something pre-processed infos. TBH, I often forget about these limitation and switch conveniently between the two as needed.
Hope someone will clarify this point.

Long answer short, use include_role at task level, as you seem to have figured out already.

2 Likes

I’m using this a lot, combined with GitHub - leapfrogonline/ansible-merge-vars: An Ansible action plugin to explicitly merge inventory variables to dynamically create the list of host/group-specific roles I want to throw against my fleet :slight_smile:

Looks a bit like this:

- name: 'Main configuration run - all systems'
  hosts: 'all'
  tasks:
    - name: 'Prepare host specific role list'
      merge_vars:
        suffix_to_merge: '_roles__to_merge'
        merged_var_name: 'host_roles'
        expected_type: 'list'

    - name: 'Host specific roles'
      ansible.builtin.include_role:
        name: "{{ host_role }}"
      loop: "{{ host_roles | default([]) }}"
      loop_control:
        loop_var: 'host_role'

Hi @poinck! It looks like the post might be solved - could you check to see if any of the responses above worked for you?

If so, it would be super helpful if you could click the :heavy_check_mark: on their post to accept the solution - it recognises the input of others, helps our volunteers find new issues to answer, and keeps the forum nice and tidy.

Thanks!
(this is template reply, do feel free to reply if I’ve misunderstood the situation!)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.