Hi!
I stumbled onto the following.
While this works:
`
roles:
- { role: foo, data: ‘bar’ }
- { role: foo, data: ‘zab’ }
`
this will fail right away with “value of ‘roles:’ must be a list”:
`
- hosts: all
vars:
my_data:
- { role: foo, data: ‘bar’ }
- { role: foo, data: ‘zab’ }
roles: my_data
`
So it makes a difference if the list of roles is provided verbatim or assigned to a variable first. This is especially surprising as this pattern works well with e.g. “with_items” where the list being looped can be either verbatim or a variable.
Is this an intended limitation or a bug?
Why do I need this? I want to load the variable from another file using “include_vars”.
Cheers,
Henning
Hi Henning, this will not work due to the fact that “include_vars” is a task, and roles are evaluated and loaded before any tasks are executed - meaning the variable will not be available at that time. We could make your given example work, however I don’t think it’s very useful this way, since you’d have to specify the variable in vars, which doesn’t buy you much. Additionally, some users may try to use variables from inventory (host/group vars) to do this, which would also not work and could cause confusion.
Hi James,
thank you for the quick and good explanation. That makes a lot of sense, it’s basically compile-time vs. run-time values. I wonder if I missed that in the docs or if it could be pointed out more clearly.
So, what would be the correct solution? I am trying to configure multiple multi-tier “virtual hosts” on a fixed set of servers. It’s not just configuring apache, it includes setting up a separate db instance, home directory, background processes and the actual app server. So there are a quite a few tasks involved.
I started out by creating a playbook that configures one such server thinking that I could later easily reuse that in a loop of sort. Trying that, though, I first hit the “include-with_items” wall and read that parameterized roles would be the better solution. Then I stumbled onto the limitation described here.
I am currently converting my playbooks to include “with_items: vhosts_data” with each task, which seems to be the only working solution. This is tedious and cumbersome, though, and makes ansible lose some of its power and beauty:
- Tasks that already used a with_items: need to be split up into separate tasks. None of the other with_* constructs would work.
- The “item.” has to trickle all the way down into templates.
- I cannot define per-vhost variables (e.g. “home_dir”) and re-use them across several tasks. I solved this by pre-generating all these values in the python script that generates the vhosts_data list in the first place, thus moving part of the configuration out of the playbooks into code. Not nice.
Parameterized roles would solve all of these because each has its own namespace. If only I could feed them with data that the playbook collects at run-time. Putting the virtual hosts configuration data into the playbook itself so it can be evaluated at compile-time is not an option because these will get updated frequently as vhosts are added, removed or reconfigured.
How could this use case, which I believe is rather common, be addressed in future versions of ansible? Or am I missing something that would make this work with the current version?
Thanks again for explaining. Hopefully this reply did not get too long.
Henning