Search code examples
ansibleansible-inventory

How to bind configs to host groups in ansible?


Below is a "working" version, where I define the config in my inventory file: Inventory file:

all:
  children:
    grp1:
      hosts:
        host1:
    grp2:
      children:
        subgrp1:
          vars:
            config_vars:
              name1: "value1"
              name2: "value2"
          hosts:
            host11:
            host12:
        subgrp2:
          vars:
            config_vars:
              name1: "value3"
              name2: "value4"
          hosts:
            host21:
            host22:
    grp3:
      hosts:
        host31:
        host32:

My playbook looks like:

---
- name: test play
  hosts: grp2
  connection: ssh
  gather_facts: no
  remote_user: ec2-user
  tasks:
    - debug:
        msg: "inventory_hostname = {{ inventory_hostname}} and item.key = {{ item.key }} and value = {{ item.value }} "
      when: "{{ item['key'] }} == config_vars "
      loop: "{{ lookup('dict', hostvars[inventory_hostname]) }}"

Upon running ansible-playbook -i hosts.yml p1.yml I have:

ok: [host22] => (item={'key': 'config_vars', 'value': {'name1': 'value3', 'name2': 'value4'}}) => {
...
ok: [host21] => (item={'key': 'config_vars', 'value': {'name1': 'value3', 'name2': 'value4'}}) => {
...
ok: [host11] => (item={'key': 'config_vars', 'value': {'name1': 'value1', 'name2': 'value2'}}) => {
...
ok: [host12] => (item={'key': 'config_vars', 'value': {'name1': 'value1', 'name2': 'value2'}}) => {

(See how values of name1 and name2 align up according to each group's config)

The "non-working" configuration I have is where, I remove the config_vars from my inventory file, and instead have a directory structure matching the hosts.yml structure, and the config_vars dict pasted under each group's directory

> cat group_vars/grp2/subgrp2/main.yml
config_vars:
  name1: "value3"
  name2: "value4"

> cat group_vars/grp2/subgrp1/main.yml
config_vars:
  name1: "value1"
  name2: "value2"

Then I re-run the command as before and I see:

ok: [host22] => (item={'key': 'config_vars', 'value': {'name1': 'value3', 'name2': 'value4'}}) => {
ok: [host12] => (item={'key': 'config_vars', 'value': {'name1': 'value3', 'name2': 'value4'}}) => {
ok: [host21] => (item={'key': 'config_vars', 'value': {'name1': 'value3', 'name2': 'value4'}}) => {
ok: [host11] => (item={'key': 'config_vars', 'value': {'name1': 'value3', 'name2': 'value4'}}) => {

(the value1 and value2 are clobbered)

I kind of know why this happens; it is because the value3 and value4 are read later so they replace the value 1 and value2. My question is: how can I preserve the binding of the group with the config when I structure my variables organization like this. It would also be fine if I do it any other way, but have the variables taken out of the inventory file. Many thanks in advance


Solution

  • Q: "How can I preserve the binding of the group with the config?"

    A: The paths in group_vars are wrong

    group_vars/grp2/subgrp1/main.yml
    group_vars/grp2/subgrp2/main.yml
    

    In the inventory, the variables are declared in the groups subgrp1 and subgrp2 respectively. This corresponds to group_vars

    $ tree group_vars
    group_vars/
    ├── subgrp1
    │   └── main.yml
    └── subgrp2
        └── main.yml