yzftnt
yzftnt

Reputation: 103

search a host in ansible inventory

I have below ansible inventory structure:

[app1]
labhost1 ansible_host=1.1.1.1 tag=master
labhost2 ansible_host=1.1.1.2 tag=slave
labhost3 ansible_host=1.1.1.3 tag=slave
labhost4 ansible_host=1.1.1.4 tag=master
labhost5 ansible_host=1.1.1.5 tag=slave
labhost6 ansible_host=1.1.1.6 tag=slave

[DC1]
dc1_app1

[DC2]
dc2_app1

[dc1_app1]
labhost1 ansible_host=1.1.1.1 tag=master
labhost2 ansible_host=1.1.1.2 tag=slave
labhost3 ansible_host=1.1.1.3 tag=slave

[dc2_app1]
labhost4 ansible_host=1.1.1.4 tag=master
labhost5 ansible_host=1.1.1.5 tag=slave
labhost6 ansible_host=1.1.1.6 tag=slave

and group_vars file below: DC1.yml

---
location: country1

DC2.yml

---
location: country2

When running a playbook on labhost2, I like to extract the IP address of the master device in the same datacenter in which the host labhost2 is located.

I tried below expression

- set_fact:
    masterIP: "{{ groups['app1'] | map('extract', hostvars) | selectattr('location', 'eq', location) | selectattr('tag', 'eq', 'master') | map(attribute='ansible_host') }}"

It should return 1.1.1.1 as value of the variable masterIP but it shows:

VARIABLE IS UNDEFINED

Upvotes: 0

Views: 256

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68189

From the logic of the question, I can only assume that you run the playbook for the group app1

- hosts: app1

Iterate the 'dc*' groups that belong to the group of applications and create the dictionary of masters, e.g.

    - set_fact:
        dc_masters: "{{ dc_masters|d({})|combine({item: _dict.master}) }}"
      loop: "{{ groups|select('match', 'dc[\\d+]_app1') }}"
      vars:
        _hosts: "{{ groups[item] }}"
        _tags: "{{ _hosts|map('extract', hostvars, 'tag') }}"
        _dict: "{{ dict(_tags|zip(_hosts)) }}"
      run_once: true

gives

  dc_masters:
    dc1_app1: labhost1
    dc2_app1: labhost4

Then you can use this dictionary and find the masters for the slaves, e.g.

    - debug:
        msg: "slave: {{ inventory_hostname }} master: {{ dc_masters[dc] }}"
      vars:
        dc: "{{ group_names|difference(['app1'])|first }}"
      when: tag == 'slave'

gives

TASK [debug] **************************************************************
skipping: [labhost1]
skipping: [labhost4]
ok: [labhost2] => 
  msg: 'slave: labhost2 master: labhost1'
ok: [labhost3] => 
  msg: 'slave: labhost3 master: labhost1'
ok: [labhost6] => 
  msg: 'slave: labhost6 master: labhost4'
ok: [labhost5] => 
  msg: 'slave: labhost5 master: labhost4'

Fit the expression dc: ... to your needs if there are more groups a slave belongs to.

Upvotes: 1

Related Questions