I have just merged in patches that enable role default variables (thanks to @smoothify for a large portion of the work), and also tweak the way variables are processed by roles. This will be included in Ansible 1.3, but if you’re running from a git clone you can take advantage of this today.
Role defaults are created by adding a defaults/main.yml file (formatted the same way as any other vars file) in your role directory. Any variables you define there have the lowest priority of any variables available in Ansible, and can be overridden by inventory variables like host and group vars.
This is really great - I was about to ask for such a feature and it came in unexpectedly. Excellent.
Played with it and found a behaviour I’m not sure about whether that’s what you want.
Playbook:
name: Test role defaults
hosts: myhost
connection: local
roles:
test1
test2
roles/test1/defaults/main.yml:
testvar: ‘test1’
roles/test2/defaults/main.yml:
testvar: ‘test2’
roles/test1/tasks/main.yml:
name: Group test 1
debug: msg=“{{ testvar }}”
roles/test2/tasks/main.yml:
name: Group test 2
debug: msg=“{{ testvar }}”
The output is in both cases “test2” which is a surprise to me. It looks as if all defaults get read before the tasks of each role are performed and secondly, default variables of roles are overwriting each other. OK, a variable scope which is limited by role is probably asking for too much.
This is a behavior we did not want to change, as it was how role variables acted before and we did not want to break backwards compatibility. All variables are read into the global scope, so if two roles set the same variable, which ever is imported/depended last will “win”. This is expected, and the usual recommendation is to prepend the role name to your variables if you want to be sure nothing else tramples on them accidentally.
Remember that we fixed this in 1.3 for roles/x/vars/foo.yml so that the roles active vars always won by making it as if they were passed into parameters for the role.
I would agree that it would be logical to expect that same behavior out of role default variables.
PLAY RECAP ********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
I’ve also merged in one other tweak mdehaan and I discussed, which is to base the role duplicate checking on the role dependency definition rather than just the role name. For example, the following would be included twice without having to specify “allow_duplicates: true”:
This is now working but I guess something else got broken: if the same variable is defined in host_vars/host then this does no longer overwrite the role default.
Yes, I’ve commented on the commit. The above fix needs to be reverted.
It’s better to have role defaults doing what they were meant to do and have to be aware they are global, in the event we can’t tweak the above behavior – because that was the whole purpose of role defaults
Ok, I’ve reworked this, but won’t merge it in quite yet until I get a bit more testing in on it (my previous mistake was in not testing it against every permutation of variables possible). I’ve done some testing with setting variables at the different levels of priority and it seems to be working well, so here’s the diff if anyone else would like to do some testing on their own plays: