Playbook inventory group targeting

Hi

Need some help on how inventory works.
Having this structure:
inventory/groupA.yaml

groupA:
  children:
    masters:
      hosts:
        master1ofA: {}
    slaves:
      hosts:
        slave1ofA: {}

inventory/groupB.yaml

groupB:
  children:
    masters:
      hosts:
        master1ofB: {}
    slaves:
      hosts:
        slave1ofB: {}

playbooks/playbook.yaml

---
- name: Print hostname on all hosts
  hosts: groupA
  become: false
  tasks:
    - name: Display hostname
      command: hostname

why:
ansible-playbook -i inventory playbooks/playbook.yaml --list-hosts

playbook: playbooks/playbook.yaml

  play #1 (groupA): Print hostname        TAGS: []
    pattern: ['groupA']
    hosts (4):
      slave1ofB
      master1ofB
      slave1ofA
      master1ofA

why does it appears the hosts of groupB?

If I change to -i inventory/groupA.yaml it target the correct hosts. So why it needs the hosts: groupA instruction in playbook?

Thanks in advance

Even in the playbook:
hosts: groupA:&masters

ansible-playbook -i inventory playbook/playbook.yaml --list-hosts

playbook: playbook/playbook.yaml

  play #1 (groupA:&masters): Print hostname     TAGS: []
    pattern: ['groupA:&masters']
    hosts (2):
      master1ofA
      master1ofB

It still target boths masters.
If hosts are from groupA AND masters, why it target a master from groupB?

Welcome to The Forum, @zeitler !

There’s your misunderstanding. There is only one masters group. Or any other group. Groups don’t nest. You have two inventory files, both of which add hosts to the single masters group.

If you want that sort of hierarchy, you can fake it with group naming, like shown below:

a:
  children:
    a_masters:
      hosts:
        master1ofa: {}
    a_slaves:
      hosts:
        slave1ofa: {}
# No need for separate files, unless you find it convenient. Which is fine.
b:
  children:
    b_masters:
      hosts:
        master1ofb: {}
    b_slaves:
      hosts:
        slave1ofb: {}

thank you

So, in you example, what happens to “a”? It’s still a group? Ansible don’t make a difference about that? But it’s that its used in hosts on playbook. That’s why I’m not getting it.

Im my cases, I have some roles. In them, I have something like:

- name: Get cluster token
  ansible.builtin.include_tasks:
    apply:
      become: true
    file: get_cluster_token.yaml
  when: inventory_hostname in groups['masters'][0]

Doing how you suggest, how can I accomplish this role to other clusters?

The idea was having some roles, that I can reuse to all of our clusters. But everytime I start the playbook, I act on all hosts.
If I do ansible-playbook -i inventory/groupa.yaml .... it works. But, If I’m defining the hosts on playbook… I feel that I’m repeating myself :slight_smile:

Yes, it’s still a group. Behold:

utoddl@tango:~/ansible/zeitler$ ansible -i inventory.yml --list-hosts all
  hosts (4):
    master1ofb
    slave1ofb
    master1ofa
    slave1ofa
utoddl@tango:~/ansible/zeitler$ ansible -i inventory.yml --list-hosts a
  hosts (2):
    master1ofa
    slave1ofa
utoddl@tango:~/ansible/zeitler$ ansible -i inventory.yml --list-hosts b
  hosts (2):
    master1ofb
    slave1ofb
utoddl@tango:~/ansible/zeitler$ ansible-inventory -i inventory.yml --list
{
    "_meta": {
        "hostvars": {}
    },
    "a": {
        "children": [
            "a_masters",
            "a_slaves"
        ]
    },
    "a_masters": {
        "hosts": [
            "master1ofa"
        ]
    },
    "a_slaves": {
        "hosts": [
            "slave1ofa"
        ]
    },
    "all": {
        "children": [
            "ungrouped",
            "a",
            "b"
        ]
    },
    "b": {
        "children": [
            "b_masters",
            "b_slaves"
        ]
    },
    "b_masters": {
        "hosts": [
            "master1ofb"
        ]
    },
    "b_slaves": {
        "hosts": [
            "slave1ofb"
        ]
    }
}

I’ve harped on about this before. It’s what I call “fully articulated” inventory groups. In our shop, we group things by service line, and within that by environment (dev, tst, prd, …). We also prepend our work group’s initials to all our host group names to keep them from colliding with those of other work groups. We’re called the “Middleware” group, hence the leading “mw_”. So all our host group names look like this:

mw_<service>[_<env>[_<hostclass>[_<subclass>]]]

Whenever we need it, we’ll also define a literal “all” group at any of those placeholder levels. Then we can say:

 when: inventory_hostname in groups['mw_xkcd_all_head']

Or the equivalent for your inventory if it were “fully articulated”:

when: inventory_hostname in groups['all_masters']

That lets us avoid contortions in our when: clauses like the following – which works, but who wants to read it, much less write it.:

---
# /home/utoddl/ansible/zeitler/test.yml
- name: Play group name games
  hosts: all
  gather_facts: false
  tasks:
    - name: Are we in a *_master group
      ansible.builtin.debug:
        msg:
         - 'group_names: {{ group_names }}'
         - '{{ inventory_hostname }} is in a *_master group.'
      when: group_names | map("regex_search", "_master") | reject("==", None) | length

which produces

TASK [Are we in a *_master group] ***********************************************************
task path: /home/utoddl/ansible/zeitler/test.yml:7
ok: [master1ofb] => 
  msg:
  - 'group_names: [''b'', ''b_masters'']'
  - master1ofb is in a *_master group.
skipping: [slave1ofb] => 
  false_condition: group_names | map("regex_search", "_master") | reject("==", None) | length
skipping: [slave1ofa] => 
  false_condition: group_names | map("regex_search", "_master") | reject("==", None) | length
ok: [master1ofa] => 
  msg:
  - 'group_names: [''a'', ''a_masters'']'
  - master1ofa is in a *_master group.

I’m going to quote myself in case someone didn’t follow the link above, because I think it’s worth repeating.

1 Like

Thank you very much for your explanation.
Understood now quite well how to accomplish what I wanted. Even better that I first thought

Thank you