Looping over roles ?

Fellows,

I trying to wrap my head around a simple problem.
I have a playbook (role) that installs ruby with rbenv.
Actually, it uses ruby.version host/group variable to install the
correct ruby version :

group_vars/some_servers_that_wants_ruby.yml :

Yes, pass the array in via the role arguments and then loop over them inside the role itself. For example:

roles:

  • { role: ruby, versions: [ “1.9.3-p448”, “2.0.0-p247”]}

Then use “with_items: versions” inside the role.

Thanks James.

The problem, as explained previously, is that I can hardly use
with_items within a role's task since I use chained actions with
registered variables. It simply wouldn't work.

For instance, before installing ruby, an action checks if the requested
version is already installed (and registers a variable). I don't think
this would survive a "with_items" loop (unless it is possible to
register hash entries, but I don't think so).

M

Hello,

I am also looking for a way to loop over a set of tasks.

I used to do it with role.with_items just as you first posted but it has been deprecated.

The deprecation is for good reasons I think because the plays are unrolled before execution and even if role.with_items work in simple cases, I believe there are more complex inventory cases where it does weird things.

One option is to push the with_items down to the task level. This is what I did for my multi-versions installs but I did not need to register variables so it was simpler.

The best would be to make a role loopable with minimum modifications (pushing with_items down to the tasks level is rather painful imho)

Your question made me think about a potential new way to do it. it will look as a hack to many but may work to unroll the loop. The basis of the idea is to consider that the main use case is to loop N times over the role, N being bounded to for example 5.

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” }

The details would have to be refined but I think it could work to have the roles unroll as independent blocks of tasks rather than inside each task ; and if it works, it would look cleaner to me than obscuring the initial role with with_items and with_nested all over the place.

Tell me if you try it !

Jerome

Hello,

Hey Jerome,

I am also looking for a way to loop over a set of tasks.

[...]

One option is to push the with_items down to the task level. This is
what I did for my multi-versions installs but I did not need to register
variables so it was simpler.

The best would be to make a role loopable with minimum modifications
(pushing with_items down to the tasks level is rather painful imho)

[...]

The details would have to be refined but I think it could work to have
the roles unroll as independent blocks of tasks rather than inside each
task ; and if it works, it would look cleaner to me than obscuring the
initial role with with_items and with_nested all over the place.

Tell me if you try it !

That's hell of a hack, but it works like a charm (with few changes) !

$ cat roles/ruby/tasks/main.yml

I would like to see your full ruby role if you don't mind making it available.
-John

Hi John,

I've setup a repos with a Vagrantfile so you can try it out :
https://github.com/leucos/ansible-rbenv-playbook

Rough edges, comments & PRs welcome.

M

I am glad the looping works it means that you can go from a “single” install script to a “multi” without modification and that is interesting.

Note that in your
ruby_multi/tasks/main.yml
you can add a fail test when the versions array has a length superior to the looping cardinality of your multi. This way you will be informed if your array is not fully looped over.

note also that there might be other issues to look at and solve with notify: restart when doing a multi version of a server install. It might be necessary to restart all versions even if only one version is notified. At least until the notify: can accept parameters.

I do not use ruby that much but thanks for the script it is interesting and made me learn a few tricks.

Jerome

“since I use chained actions with
registered variables. It simply wouldn’t work.”

Not sure what a “chained variable” is.

It's registered variables. I use conditional tasks that depend on
previously registered variables (for instance, I check if the requested
ruby version is already installed and depending on the result, I install
it or not).

I'm not sure I can do that using 'with_items' for the ruby versions :
registered variables would be overriden for each item I suppose, unless
there is some facility that would put the results in a hash instead of a
simple variable.

M

I just had the same problem. But since your post is a few years old, I wondered if there might be a better solution by now. If there isn’t, I’ll try the “hack” :D.

Thanks!

I have the dilemma.
In my case the list size can vary so the above hack doesn’t work.

Does Ansible 2.0 solve this problem?

In ansible 2.0 include will be possible with with_ – so that would solve this problem, I guess.

I think a permanent solution is needed: many people is looking for that feature.
https://groups.google.com/forum/#!topic/ansible-project/B5547FiIhYA
http://phillbarber.blogspot.hu/2015/10/ansibles-for-loops.html

Is that solved in 2.0?
Or only includes + with_items (but for tasks only not for roles)
… as written here: http://stackoverflow.com/questions/30785281/one-loop-over-multiple-ansible-tasks#answer-35128533

Regards:
Bence

  1. november 27., péntek 13:04:59 UTC+1 időpontban Filias Heidt a következőt írta: