I’m having a bit of trouble figuring out the best structure for declaring a default variable value per inventory group that would be used by a role, that is over rideable per inventory.
I’m aware that versions of this question have been asked many, many times before but I haven’t yet seen a suitable answer.
I’ve structured my project similar to this:
├── ansible.cfg
├── inventories/ # Parent directory for our environment-specific directories
│ │
│ ├── dev/ # Contains all files specific to the dev environment
│ │ ├── group_vars/ # dev specific group_vars files
│ │ │ ├── all.yml
│ │ │ ├── billing.yml
│ │ │ └── policy.yml
│ │ └── hosts # Contains only the hosts in the dev environment
│ │
│ ├── prod/ # As above but for the prod environment
│ │
│ └── stage/ # As above but for the stage environment
│
├── playbook.yml
├── group_vars/ # Play specific group_vars files
│ ├── all.yml
│ ├── billing.yml
│ └── policy.yml
│
├── roles/
│ ├── deploy-tomcat-war/
│
└── . . .
I keep all common variables in playbook/group_vars/.yml because there is no other place to declare them that all inventories have access to (that I am aware of).
I keep all environment specific overrides in inventory/group_vars/.yml.
For any of you familiar with my problem you’ll already know the fatal flaw in my approach. Ansible’s order of precedence means that the playbook/group_vars override inventory/group_vars. The “recommended” solution for this is to place the default variable declaration in playbook/group_vars/all as inventory/group_vars will override this, but playbook/group_vars/all does not support declaring the same variable with a different value per group.
https://github.com/ansible/ansible/issues/9877 has a very good write up of the issue but fails to come up with a good solution.
My understanding of the purpose of each Ansible component is:
-
Inventories: define where a play is run (and organize servers by groups)
-
Playbooks: define what roles are applied to a group (the link between inventory and role)
-
Roles: define how the components are applied to the group
Given that understanding it should follow that variables define in roles are overridden by those defined in playbook/group_vars which in turn should be overridden by those defined in inventories/group_vars. However I keep coming across the statement that “playbook/group_vars are meant to override the inventory as plays are more specific than inventory”. I don’t understand how the Ansible developers have come to that conclusion, sure playbooks control what is run but I would argue that inventories are more specific because they control the where.
All the proposed solutions I’ve seen fall into the following groups:
- Use customs variable loader.
a. Seems a lot of work for something that should be in built
- Put all override-able variables into playbook/group_vars/all.yml and which will allow you to use inventories/group_vars/.yml to override them.
a. You lose the ability to define variables per group which is vital in my playbook / role combinations
- Use environment specific groups in inventory your files.
a. I can’t even be bothered explaining how bad a solution that strikes me as
- Keep fingers crossed that developers provide a mechanism to do this, e.g.
allow override of the precedence order
support groups in playbooks/group_vars/all//yml
a. Based on the age of some of the threads I’ve seen people have been waiting a long, long time so I’m not expecting this any time soon
So all you Ansible dev’s out there, where do you suggest I put default variable declarations for each group where it can be overridden by an inventory if required?