This question has probably been asked before but I’m having trouble wrapping my head around it. It was recently asked again on freenode so I’m bring it up here.
Lets say I have a role definition for an nginx setup and one of the variables in the roles vars is nginx_version.
If this role is included by different playbooks targetting different host groups, I find it logical to specify an override version in the group vars. However, unless I remove the variable definition in the roles vars I can’t achieve this. Having required variable definitions for certain roles makes sense - i.e. a contract, however, I’m not sure how to enforce that (thus the need for a default value in the roles vars)
Here is what we do for variable definitions, lowest to highest precedence:
group_vars/all <— var definitions that apply to all roles
/vars/main.yml <— default definitions for the roles
“var_files:” ← any environment specific overrides, so different overrides for different plays
Having the same variable defined under group_vars/ and in your /vars/main.yml is something we avoid altogether.
We also prefix all of our role vars with the name of the role to avoid namespace collisions though there has been talk about making var definitions in the role take higher precedence which would be nice.
I also believe 1.3 will abort if a variable is referenced that is not defined which is a nice feature.
For ansible 1.2 you can always do this:
- fail: my_var required for role
when: my_var is not defined
In general the ansible maintainers refuse to break backwards compatibility so I doubt the precedence rules will change.
If somebody can send me a nice patch and it might get in sooner
However, our primary feature we are working on right now for 1.3 is role dependencies, so that is currently taking a backseat
There is also a nice proposal to inject role variables even in YAML into the “role parameter” space which avoids the need for jarv to use prefixes, which we plan to include in 1.3.
I agree that the variable precedence causes some confusing and I’ve seen plenty of explanations as to what the precedence is but not why it’s that way. In my head, the inventory should be the highest priority - it’s were have individual servers configured - ansible CMDB, if you will The roles and so on are the how to get there, so putting the variable in there results in vars tightly coupled to the actions of the process, rather than being easily overridden on a host by host or group by group basis in the inventory.
It seems that ansible tightly couples the data to the plays, making generic playbooks with a moderate amount of variable data hard and counter intuitive.
The obvious fix for this has been mentioned before: use different names. This project has grown organically and Michael (as well as the other contributors) has rightly been trying not to break backward compatibility without having a really really good reason, and then when necessary to do so not turning on a dime and leaving people hanging.
While there are different ways of handling this kind of disagreement in Open Source Software (and even hardware) projects, preserving compatibility is in general the right thing to do. Changes that break with such preservation should be announced well ahead of time, with many projects choosing to emit “nag messages” to be 10000% sure that the notification of a pending change has gotten out.
(Even if I disagree on any particular design decision I would not advocate just dropping everything and changing with the next tagged release to an entirely different model, unless it was some sort of security problem.)