Ansible group_vars variable precedence (group_vars override other group_vars)

ansible

On Ansible 2.2,

I have an Ansible hosts file:

[webserver]
aegir.dev

[hostmaster]
aegir.dev

I have two group_vars/ files:

# group_vars/webserver.yml
my_var:
  - vagrant

and

# group_vars/hostmaster.yml
my_var:
  - vagrant
  - aegir

and the playbook:

- hosts: webserver
  tasks:
    - debug: var=my_var

- hosts: hostmaster
  tasks:
    - debug: var=my_var

Output:

PLAY [webserver] ***************************************************************

TASK [setup] *******************************************************************
ok: [aegir.dev]

TASK [debug] *******************************************************************
ok: [aegir.dev] => {
    "my_var": [
        "vagrant",
        "aegir"
    ]
}

PLAY [hostmaster] **************************************************************

TASK [setup] *******************************************************************
ok: [aegir.dev]

TASK [debug] *******************************************************************
ok: [aegir.dev] => {
    "my_var": [
        "vagrant",
        "aegir"
    ]
}

Why both webserver and hostmaster use the variables from hostmaster.yml?

Probably I'm not using the group_vars correctly but how I can fix that?

EDIT

The real case scenario is that I have the same role running on two groups, one is webserver that actually contains 4 generic servers and the hostmaster group that is a webserver + extra configuration on the same role (the user aegir exists only on aegir.dev and not on the other 3 web-servers)

Best Answer

This question is a bit old but the mentioned issue already exists, so I wrote my answer to one who needs the answer.

Actually, based on the documentation, Ansible focused on the Host and Task, so groups don’t really survive outside of inventory and host matching. To solve this problem, we need to add a prefix to variables of groups (like using namespacing to avoid conflicts).

# inventory/hosts.yml
webservers:
  hosts:
    host1:
    host2:
  vars:
    webserver_my_var: ...

hostmaster:
  hosts:
    host1:
  vars:
    hostmaster_my_var: ...

And in the playbook, you can use the variable safely.

# playbooks/main.yml
- hosts: webserver
  tasks:
    - debug: var=webserver_my_var | mandatory

- hosts: hostmaster
  tasks:
    - debug: var=hostmaster_my_var | mandatory

This way you will eliminate the problem safely.

Using the same variable name inside multiple groups has another problem. It's hard to guess the value of a variable by just looking at the inventory, you need to know the relation between groups and the order/precedence of one group to another and it is hard work and error-prone.