0

I need some help with matching inventory_hostname with item.host (from vars_file). What is the best way to do that? I couldn't figure out this as i am a newbie.

My requirement is:

  • I must call all hosts from inventory file.

  • I must match item.host from ansible_inventory, if it's exist then run a shell command on hosts which matches with all item.hosts then exit.

  • filelist.yml is a dynamic file which is changing on daily basis, all hosts exist in inventory but I only want to leverage those which is in file.

I have list.yml file which contains hostname, disk and version info

$ cat list.yml
---
list:
  - host: host1
    diskn: disk0
    os: 7

  - host: host2
    diskn: disk4
    os: 7

  - host: lhost6
    diskn: hdisk7
    os: 7
---

In playbook i tried to match the value but had no luck.

---
- name: My playbook   
  hosts: all   
  vars_file: 
    - list.yml   
  tasks:
   - name: Remove file from client
     shell: "rm -f /tmp/me"
     when:
       - "('item.host' in inventory_hostname) and (ansible_distribution_version == 'item.os')"
     loop: "{{ list }}"
     register: fileopt
   - debug: var=fileopt
----

Please propose a solution which can resolve this issue.

Atif
  • 11
  • 1

1 Answers1

2

For example, given the inventory

shell> cat hosts
host01
host02
host03

and the list

list:
  - host: host01
    diskn: disk0
    os: 13.0
  - host: host02
    diskn: disk4
    os: 13.0
  - host: host06
    diskn: hdisk7
    os: 13.0

Create the list of the allowed hosts

my_hosts: "{{ list|map(attribute='host')|list }}"

gives

my_hosts:
  - host01
  - host02
  - host06

Next, create a dictionary of the allowed hosts and OS versions

my_os: "{{ list|items2dict(key_name='host', value_name='os') }}"

gives

  my_os:
    host01: 13.0
    host02: 13.0
    host06: 13.0

Now, the tasks below remove the file conditionally and display the registered results

    - name: Remove file from client
      file:
        state: absent
        path: /tmp/me
      when:
        - inventory_hostname in my_hosts
        - ansible_distribution_version ==
          my_os[inventory_hostname]|default('None')|string
      register: fileopt
    - debug:
        var: fileopt

gives

TASK [Remove file from client] *********************************************
skipping: [host03]
ok: [host02]
ok: [host01]

TASK [debug] ***************************************************************
ok: [host01] => 
  fileopt:
    changed: false
    failed: false
    path: /tmp/me
    state: absent
ok: [host02] => 
  fileopt:
    changed: false
    failed: false
    path: /tmp/me
    state: absent
ok: [host03] => 
  fileopt:
    changed: false
    skip_reason: Conditional result was False
    skipped: true

As expected, host03 which is missing from the list was skipped.


Optionally, creating a dynamic group might be more efficient if the list of the allowed hosts is much smaller compared to all hosts. For example, create a group of allowed hosts in the first play and use it in the second play

- name: Create group my_hosts
  hosts: all
  gather_facts: true
  vars:
    list:
      - host: host01
        diskn: disk0
        os: 13.0
      - host: host02
        diskn: disk4
        os: 13.0
      - host: host06
        diskn: hdisk7
        os: 13.0
    my_hosts: "{{ list|map(attribute='host')|list }}"
    my_os: "{{ list|items2dict(key_name='host', value_name='os') }}"
  tasks:
    - set_fact:
        _my_os: "{{ ansible_distribution_version ==
                    my_os[inventory_hostname]|default('None')|string }}"
    - name: Create group my_hosts
      add_host:
        name: "{{ item }}"
        groups: my_hosts
      loop: "{{ hostvars|dict2items|
                selectattr('key', 'in', my_hosts)|
                selectattr('value._my_os')|
                map(attribute='key')|
                list }}"
      run_once: true

- name: Remove file from my_hosts
  hosts: my_hosts
  gather_facts: false
  tasks:
    - name: Remove file from client
      file:
        state: absent
        path: /tmp/me
      register: fileopt
    - debug:
        var: fileopt

gives

PLAY [Create group my_hosts] ***************************************

TASK [Gathering Facts] *********************************************
ok: [host03]
ok: [host01]
ok: [host02]

TASK [set_fact] ****************************************************
ok: [host03]
ok: [host02]
ok: [host01]

TASK [Create group my_hosts] ***************************************
ok: [host01] => (item=host01)
ok: [host01] => (item=host02)

PLAY [Remove file from my_hosts] ***********************************

TASK [Remove file from client] *************************************
ok: [host01]
ok: [host02]

TASK [debug] *******************************************************
ok: [host01] => 
  fileopt:
    changed: false
    failed: false
    path: /tmp/me
    state: absent
ok: [host02] => 
  fileopt:
    changed: false
    failed: false
    path: /tmp/me
    state: absent
Vladimir Botka
  • 5,138
  • 8
  • 20