I’m a bit confused about the usage of defaults. At first sight it seems like it’s a good place to put default values of parameterized roles. But when I looked deeper onto how the vars in defaults work, I see that defaults aren’t exactly vars. They are placeholders that are being rendered at runtime.
Here is something that will show what I mean.
Let’s say we have a role “test” with a “testvar” as parameter:
The bit about simply being a placeholder is not correct, they’re just held in a different variable dictionary that is later merged in with all of the others. The behavior you’re seeing is related to this, as the defaults are not yet merged in, so they’re not being injected into the template engine when the name of the task is read/saved. As others have noted on this ML, inventory variables suffer from the same problem.
In the case of defaults though, they should be able to be included in that data, so please open a github issue for this and we’ll look into it.
I was thinking about the whole thing… I was fighting with this nginx/sites and php5-fpm/pools roles for sometime.
Maybe the right why to go here would be to develop a “module” for a single site and a module for a single php/pool.
And then the role would use those modules. It looks cleaner for me. Would it be a better way to approach it?
Another thing I’ve noticed in regards of defaults… When I define a list in defaults/main.yml, it won’t be parsed inside a “with_items” call.
When I move this var to the main playbook var decleration, it works. Is that on purpose?
Thanks a lot,
and sorry if I ask too many questions It’s just I’m really passionate about Ansible and would like to know a lot about it
When in doubt, consult the docs, and we’ll show the right way.
(B)
Include + with_items isn’t supported. Hasn’t been documented for a long time.
Should have never been implemented.
Eats kittens for breakfast.
The solution is to always loop inside the role/item, or when including more than one thing it’s ok to load the role more than once with different parameters if need be.
(C)
“Another thing I’ve noticed in regards of defaults… When I define a list in defaults/main.yml, it won’t be parsed inside a “with_items” call.”
Now, I have another misconception. This time it’s about naming vars.
Let’s say I have 2 roles. nginx_site and php_pool.
Both of them should take “user” as a parameter. Now, they both have a default “user” defined in defaults.
However, if a var called “user” that is used for different purposes is configured in a higher scope, the defaults are overridden, and it can cause some mess.
This led me to a point that it would be better that each role would depend on a dictionary and not on several single parameters. The other option is to prefix all the vars in each role.
So roles are already implemented such that when using them variables set in one role won’t be applied inside another, you are guaranteed to have those active roles “in scope”.
Defaults however occur at a level lower than inventory and can’t as easily do this, but it sounds like something we should explore if possible, such that it has the same behavior.
I’ll talk to James about this as he did the magic features for regular role variables.
I’d prefer to not bring up implementation here and just get it doing what it should be
This is actually normal and expected, because defaults have the lowest priority so they are easily overridden. Best practices for default variables would be to namespace them with the role name to help prevent unexpected collisions.
If you have a role default for “x”, the whole point of role defaults was to have something inventory could override.
If you want something that’s easily namespaced in the role, you can stick that in role/x/vars instead, and that is automatically guaranteed to be used in that role.
If you added that protection to defaults, there would be no way to specify which one in inventory.
If you are going to set the variable in defaults and/or inventory you would not have to pass it along to the role as a parameter, it would be redundant, and cleaner to leave off.
Just do:
{ role: foo }
And the values from inventory and defaults will get used, no need to pass them along forcibly.
You did ask about something else though…
Right now {{ foo }} means “I want a string” and can’t really be used to pass references.
However, if you want to pass references, currently this is the only valid use for old style vars
{ role: foo, params: $params }
This is something I’m working on cleaning up right now, so we can permanently encourage only the one standard.