looping over a role, revisited

Hello,

I wondered if this previously-posted hack to loop over roles still the best option out there? (i.e. Without the need to modify the role in question to unroll the loops at a task level, as advocated as a workaround otherwise.)

   "Looping over roles ?" 5th Nov 2013
https://groups.google.com/d/topic/ansible-project/3D81SEUoNuQ/discussion

Is there any plan afoot to implement something in core to do something equivalent in a nicer (and unbounded) way?

I say this hopefully, in the belief that it would make role design easier and less error prone: you would only need to think about the simple case of one instance.

Thanks,

N

There’s no concept of looping over roles presently.

If you mean passing a list to a role, that’s fine, and you can do that.

There’s a fundamental reason this is done, in that the role must be applied in the same definition (but not the same variables) to each host in the host group.

Ergo, you can’t have different numbers of roles applied to different hosts in the same group based on some kind of inventory variance.

(So you should make a role that can take a list of input items, and then loop over it internally)

I should also add, the above is not a hack.

It’s encouraged syntax :slight_smile:

roles:

  • { role: setup_users, users: “{{ my_users }}” }

etc

I should also add, the above is not a hack.

It's encouraged syntax :slight_smile:

roles:
  - { role: setup_users, users: "{{ my_users }}" }

Possibly I didn't explain what I meant by the "hack" very well: I meant the one Jerome Wagner suggested which uses a 'loop' wrapper role with the capability to repeat another named role N times (up to some bound M), by supplying a list of N sets of parameters to pass. The role has M invocations of that role, each of which is guarded by a conditional which skips it unless there is a corresponding element in the list.

To quote:

Let's say you have you role : "ruby_install_one_version"

Now you define a new role "loop"
- { role: "loop", over: "ruby_install_one_version", iconf: [ { version: "1.9.3-p448"}, { version: "2.0.0-p247" } ] }

in meta.main.yml / dependency, you add something like (I still have a hard time with $ and {{}} in these contexts and I am not sure .length is the way to do it)

- { role: "{{ over }}", conf: $iconf[0], when: "0 < iconf.length" }
- { role: "{{ over }}", conf: $iconf[1], when: "1 < iconf.length" }
- { role: "{{ over }}", conf: $iconf[2], when: "2 < iconf.length" }
- { role: "{{ over }}", conf: $iconf[3], when: "3 < iconf.length" }
- { role: "{{ over }}", conf: $iconf[4], when: "4 < iconf.length" }

Does Jerome's work-around fall foul of the limitation you mention? i.e. That:

...the role must be applied in the same definition (but not the same variables) to each host in the host group. Ergo, you can't have different numbers of roles applied to different hosts in the same group based on some kind of inventory variance.

If so, I'm curious to know in case I need to resort to this solution. I would suspect that there would be no problem, since the parameters are supplied directly to the role and not implicitly taken from the host_vars/group_vars, but perhaps I'm not understanding something.

If not, couldn't there be an in-core Ansible solution which works essentially the same way (but without the upper bound)?

Cheers,

N

Hello

Just to clarify if Michael you have time to look at this, the “hack” that resurfaces here was used by the person to whom I answered in this playbook :

https://github.com/leucos/ansible-rbenv-playbook/tree/master/roles

you will see the “loop over roles” hack in the ruby-multi role.

I’d be interested to know what you think about it for low-volume looping.

Jerome

Ah this:

https://github.com/leucos/ansible-rbenv-playbook/blob/master/roles/ruby-multi/meta/main.yml

Can’t say I’m a fan. I still think you’d rather pass the lists of things to instantiate into the “ruby” role and loop therein.

yes, it’s going to start them all in parts, but it’s still going to achieve the final end result, and will be cleaner.