Suppose I have a parameter (ansible variable) which I want to keep the same for several inventories except for one.
By using the playbook level group_vars and inventory level group_vars, according to the docs, I could define a group for all inventories and still be able to override variables in the inventory by targeting the children because the children have precedence over the parents.
inventories/testervm/hosts
[central:children]
testervm
[testervm]
127.0.0.1 ansible_connection=local
group_vars/central.yaml
parameter: "I want to be overridden"
inventories/testervm/group_vars/central.yaml
parameter: "This override shouldn't work."
inventories/testervm/group_vars/testervm.yaml
parameter: "This override should work"
playbook.yaml
- hosts: all
roles:
- the_role
roles/the_role/tasks/main.yaml
- name: printing the parameter
debug:
msg: "{{ parameter }}"
When I run
$ ansible --version
ansible 2.9.7
[...]
$ ansible-playbook -i inventories/testervm playbook.yaml
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [127.0.0.1]
TASK [the_role : printing the parameter] ***************************************************************************
ok: [127.0.0.1] => {
"msg": "I want to be overridden"
}
PLAY RECAP *********************************************************************************************************
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Needless to say I would have expected to see "msg": "This override should work"
.
What am I getting wrong ?
[EDIT] fixed wrong paths in file paths
[EDIT] PS: Thanks to Vladimir I ended up doing this trick, maybe somebody can find it useful. In the playbook I added this task:
- name: include variable overrides
include_vars:
file: "{{ item }}"
when: item is file
with_items: "{{ [inventory_dir ~ '/group_vars/_overrides/'] | product(groups.keys()) | map('join') | product(['.yaml']) | map('join') | list }}"
tags: always
Example: inventories/testervm/group_vars/_overrides/testervm.yaml
This makes possible to have this precedence order in the group vars:
Your assumption is wrong. playbook group_vars/* (7.) is a higher precedence than inventory group_vars/* (6.). See Understanding variable precedence.
The result of the test is correct
shell> cat playbook.yaml
- hosts: all
roles:
- the_role
shell> cat roles/the_role/tasks/main.yaml
- name: printing the parameter
debug:
msg: "{{ parameter }}"
shell> cat inventories/testervm/hosts
[central:children]
testervm
[testervm]
127.0.0.1 ansible_connection=local
shell> cat inventories/testervm/group_vars/central.yaml
parameter: "Inventory group_vars/central.yaml"
shell> cat inventories/testervm/group_vars/testervm.yaml
parameter: "Inventory group_vars/testervm.yaml"
shell> cat group_vars/central.yaml
parameter: "Playbook group_vars/central.yaml"
gives (abridged)
shell> ansible-playbook -i inventories/testervm playbook.yaml
"msg": "Playbook group_vars/central.yaml"
Q: "Override a variable only in one specific inventory ... 12 options (above 10.) how to override host_vars and group_vars none of which applies to groups."
A: All of the 12 options apply, of course. This is the consequence of higher precedence. For example, the playbook below shows how to override parameter by include_vars (precedence 18.) if the host is a member of the group testervm
- hosts: all
roles:
- the_role
tasks:
- include_vars: files/testervm.yaml
when: inventory_hostname in groups.testervm
- debug:
msg: "{{ parameter }}"
shell> cat files/testervm.yaml
parameter: "Include_vars files/testervm.yaml"
gives (abridged)
shell> ansible-playbook -i inventories/testervm playbook.yaml
"msg": "Playbook group_vars/central.yaml"
"msg": "Include_vars files/testervm.yaml"