Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible variable override default in another role

Tags:

ansible

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?

like image 509
Marcus Downing Avatar asked Dec 16 '15 14:12

Marcus Downing


People also ask

What is variable precedence in Ansible?

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.

Can Ansible roles be reused by playbooks in a different directory?

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.


1 Answers

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.

like image 174
Ding-Yi Chen Avatar answered Sep 16 '22 22:09

Ding-Yi Chen