Ansible check if variable exists in attribute list

18,513

Solution 1

There are presumably more elegant ways of doing it, but something like this works for me:

If your inventory file looks like this

host1
host2
host3
host4

Then a playbook with the following content, would only be run against host4 because it isn't matched in the hostlist var:
$ cat test.yml

- hosts: all
  vars:
    hostlist:
      - { name: 'host1', ip_addr: '192.168.2.31', hostgrp: 'physical_workstation' }
      - { name: 'host2', ip_addr: '192.168.2.32', hostgrp: 'physical_workstation' }
      - { name: 'host3', ip_addr: '192.168.2.33', hostgrp: 'virtual_machine' }
  tasks:

    - name: Conditional test
      debug:
        msg: "ansible_hostname not found in hostlist."
      when: hostlist|selectattr("name", "equalto", ansible_hostname)|list|length == 0

when called like this:

ansible-playbook test.yml

means that only host4 runs the block of tasks....

PLAY [all] *************************************************

TASK [Gathering Facts] *************************************
ok: [host1]
ok: [host2]
ok: [host3]
ok: [host4]

TASK [debug] ***********************************************
ok: [host4] => {
    "msg": "hostname not in hostlist name list"
}
skipping: [host1]
skipping: [host2]
skipping: [host3]

Solution 2

Optionally, this condition is cleaner

    when: inventory_hostname not in hostlist|map(attribute="name")|list

Use inventory_hostname instead of ansible_hostname if you want to compare to the list of inventory's aliases. See What's the difference between inventory_hostname and ansible_hostname.

Share:
18,513
Mike Williams
Author by

Mike Williams

Updated on September 18, 2022

Comments

  • Mike Williams
    Mike Williams over 1 year

    I have a variable containing details of host machines on my network (called 'hostlist' - I believe you call this a dictionary, but I'm not sure of the terminology. The variable is defined in a file in group_vars/all, so it's available in all playbooks (not sure if this is important).

    I have a play which I would like to run only if ansible_hostname is not found in the list of host names in hostlist. The host names in hostlist are one of the attributes of the variable, but again I'm not sure if "attribute" is the right term...

    Hostlist is defined as:

    hostlist:
      - { name: 'host1', ip_addr: '192.168.2.31', hostgrp: 'physical_workstation' }
      - { name: 'host2', ip_addr: '192.168.2.32', hostgrp: 'physical_workstation' }
      - { name: 'host3', ip_addr: '192.168.2.33', hostgrp: 'virtual_machine' }
    

    The play I'm using to try to get this working is:

    - name: Conditional test
      debug:
        msg: "ansible_hostname not found in hostlist."
      when: ansible_hostname not in hostlist.name
    

    I'm not sure of the syntax required in the condition, or if what I'm wanting is achieveable in this manner?

    • Michael Hampton
      Michael Hampton over 3 years
      This would be a lot easier if your "hostlist" was actually part of your inventory. Why isn't it?
    • Mike Williams
      Mike Williams over 3 years
      I tried doing that earlier on, but I am wanting to be able to run my playbook on new machines where there is no ansible hosts file present (I use a template doc to deploy an /etc/ansible/hosts file based on hostlist contents)
    • Michael Hampton
      Michael Hampton over 3 years
      It sounds like you should just be creating an inventory file instead of this "hostlist".
    • Mike Williams
      Mike Williams over 3 years
      Potentially - I'll look into this also
  • Mike Williams
    Mike Williams over 3 years
    Thanks for the response. This looks like it's what I'm after, but when I try to create your example playbook and run as per your command, I get: [WARNING]: Could not match supplied host pattern, ignoring: host3 [WARNING]: Could not match supplied host pattern, ignoring: host4 ERROR! Specified hosts and/or --limit does not match any hosts ...Not sure how I can get the same output?
  • gokva
    gokva over 3 years
    so you can remove the -l host3:host4, that was just so that it didn't run against every other host in my inventory. let me update with the full inventory example...
  • Mike Williams
    Mike Williams over 3 years
    Thanks for this also. The key thing for me is that I'm wanting to use my playbook when running ansible-pull on new machines which aren't in the known hosts list, and I'm wanting to do a single line ansible-pull command without needing to first deploy a hosts file with the current machine ip included. I think I had trouble testing your earlier answer because I tried it without adding the test hosts to the hosts file on my test machine. I've tried your "when" condition in my actual playbook and it works exactly as I was wanting. So I'll accept your first answer. Thanks again!