简体   繁体   中英

Ansible variable override default in another role

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?

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. ie 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 want to wrap a role with another role then you can override the inner role's variable by specifically passing variables from the outer role.

So as per your example you would have an inner role task of:

- name: Some Task
  when: do_some_task

This inner role would have a variable set like this:

do_some_task: true

And then you can override the inner role when you are calling your outer role in a playbook like this:

- name: outer-role
  hosts: outer-role-nodes
  roles:
    -   role: outer-role
    - { role: inner role,
        do_some_task: "{{ do_some_task }}" }

This should take the do_some_task variable from the outer role and override the inner role's do_some_task .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM