4

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?

3 Answers3

5

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]

Tom
  • 11,611
3

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.

0

an alternative solution is (as suggested in the comment on the question) is to refactor the hostlist into the inventory like so:

[physical_workstation]
host1 ansible_host=192.168.2.31
host2 ansible_host=192.168.2.32

[virtual_machine] host3 ansible_host=192.168.2.33

[all] host4 ansible_host=192.168.2.34

Then you can simplify the playbook to run plays against hosts that are in no groups, using the special ungrouped group, which selects hosts from all that are not in any other group:

- hosts: ungrouped
  tasks:
    - name: only ungrouped
      debug:
        msg: "host not found in any other group."

or run things against those specific hosts in groups...

- hosts: physical_workstation:virtual_machine
  tasks:
    - name: only in specified groups
      debug:
        msg: |
          This will run on machines that are in groups:
          physical_workstation or virtual_machine

outputs

PLAY [ungrouped] ***********************************************

TASK [only ungrouped] ****************************************** ok: [host4] => { "msg": "host not found in any other group." }

PLAY [physical_workstation:virtual_machine] ********************

TASK [only in specified groups] ******************************** ok: [host1] => { "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine" } ok: [host2] => { "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine" } ok: [host3] => { "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine" }

Tom
  • 11,611