I'm unsure how to override variables between roles in Ansible.
To simplify the setup a little, I have two roles applied to the same host. The first role defines a variable in its default/main.yml
:
do_some_task: yes
And looks for that variable in its tasks:
- name: Some Task
when: do_some_task
The second role overrides that in its vars/main.yml
, which is supposed to take precedence over the defaults:
do_some_task: no
However, the task is still being run, indicating that the variable wasn't overridden. It seems that the override is scoped to the tasks of the second role. I tested that by adding a debug task to both roles:
- name: Test some task
debug: "msg='do_some_task = {{ do_some_task }}'"
This confirms that the first role sees a different value of the variable than the second.
TASK: [role1 | Test some task]
ok: [myhost] => {
"msg": "do_some_task = True"
}
...
TASK: [role2 | Test some task]
ok: [myhost] => {
"msg": "do_some_task = False"
}
The common answer to this appears to be to set the variables in the inventory or the host vars. However this isn't particularly DRY: if you have many hosts in different inventories, you'd have to set the same variables in lots of places.
So is there some way of overriding a variable from another role?
In general, Ansible gives precedence to variables that were defined more recently, more actively, and with more explicit scope. Variables in the defaults folder inside a role are easily overridden. Anything in the vars directory of the role overrides previous versions of that variable in the namespace.
You can re-use tightly focused playbooks, but you can only re-use them statically, not dynamically. A role contains a set of related tasks, variables, defaults, handlers, and even modules or other plugins in a defined file-tree.
If you use Ansible >= 2.2, you maybe able to use include_roles
:
- name: Pass variables to role
include_role:
name: role1
vars:
do_some_task: "{{ role2_do_some_task }}"
You can also use dependencies of roles for Anslbie >= 1.3. Write the role2/meta/main.yml
like:
---
dependencies:
- { role: role1, do_some_task: yes }
If you want neither, given that you don't want to put the variable definition in playbook, the only sensible place to define them is in inventory.
You can define the ones that need to overwrite the role1 default in the same group:
[overwrite_do_some_task]
host1
host3
[overwrite_do_some_task:vars]
do_some_task=yes
If you don't give the variable value before running role1, then the expected behavior is, use the role default, which is what OP observed.
Note: It is more readable to prefix role variables. i.e. use role1_do_some_task
instead of do_some_task
. Doing so, you are less likely to confuse yourself. See Ansible Best Practices: The Essentials.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With