Using inventory_hostnames in lookup()

Hi,

My infrastructure has separate “clusters” of interconnected machines. For example, several loadbalancer / backend servers combinations of the same kind. Such a host would have both a group for its cluster and a group for its role. For example:

[backend]
be[1-4].example.com

[production]
be[1-2].example.com

[staging]
be[3-4].example.com

I use group vars to make sure every cluster groups defines a “cluster” variable with the cluster name.

The load balancer would need to know which servers to configure for, so the haproxy role accepts a variable backend_servers (a list of hostnames). In my playbook, I would like to fill this variable with the intersection “backend:&{{ cluster }}”. I was trying to use something that started with lookup(‘inventory_hostnames’):

  • hosts: haproxy
  • role: haproxy
    backend_hosts: lookup(‘inventory_hostnames’, [‘backend:&{{ cluster }}’])

But the call to lookup fails with an exception, even in a simple debug task:

[…]

File “/usr/lib/python2.7/dist-packages/ansible/runner/lookup_plugins/inventory_hostnames.py”, line 37, in init
self.host_list = kwargs[‘runner’].inventory.host_list
KeyError: ‘runner’

How would I get the list of hostnames to give to the haproxy role?

Regards,
Joost

Syntax would be closer to this:

backend_hosts: “{{ lookup(‘inventory_hostnames’, ‘backend:&’ + cluster) }}”

I think you are freaking the system out a bit by the above, but should also reconsider your approach as Ansible likes things to be simple, and this is not.

Make a group called “backend_hosts” and fill it up with multiple subgroups

backend_hosts_cluster1

and then you can do, simply

groups[“backend_hosts_” + cluster]

any time you want the hosts in a particular cluster

the group “backend_hosts” would still contain all of them, for all clusters.

Syntax would be closer to this:

backend_hosts: "{{ lookup('inventory_hostnames', 'backend:&' + cluster) }}"

I think you are freaking the system out a bit by the above, ...

I dived into the code a bit, and the exception seems to be caused by
the fact that the "inventory_hostnames" lookup function requires a
"runner" parameter, which is passed when it is called as
"with_inventory_hostnames", but not when used in the "lookup"
function. I don't know whether this is a bug, but as I accept your
suggestion below I am not creating a GitHub issue (yet).

... but should also
reconsider your approach as Ansible likes things to be simple, and this is
not.

Make a group called "backend_hosts" and fill it up with multiple subgroups

backend_hosts_cluster1

and then you can do, simply

groups["backend_hosts_" + cluster]

any time you want the hosts in a particular cluster
the group "backend_hosts" would still contain all of them, for all clusters.

Alright, that sounds like a good idea. I am dividing up the inventory
into "production", "staging" and dynamic environments and I like to
create the "backend_hosts" group in a non-centralized way, which
Ansible let's me do. The resulting inventory files are a bit
repetitive, but not too much: