Accessing Variables within Inventory Vars using Jinja2

I have been having a really tough time trying to use variables that are defined within an Inventory file.

For Example:

Inventory File:

[WebApp_Login]
server1
server2
server3

[WebApp_Login:vars]
route=login

[WebApp_Sweetness]
server2

[WebApp_Sweetness:vars]
route=sweetness

[WebApp_ReallyAwesomeSweetness]
server3

[WebApp_ReallyAwesomeSweetness:vars]
route=reallyawesomesweetness

J2 Template:

{% for service_name in groups|sort %} {% for host in groups[service_name]|sort %} {{ host }} {% endfor %} {% endfor %}

I need to fill in the part that is bolded in the J2 Template. Any help would be greatly appreciated. I feel like there should be something called “groupvars” to be able to access, but there doesn’t appear to be.

Thank You!

groupvars are applied directly to the hosts that reside within that group.

So you should just be able to use {{route}} as long as the server resides within a group that contains the “route” variable.

the problem is that group_vars are not 'by group' when you access them,
they are collapsed into host. This should give you what you want.

route={{hostvars[groups[service_name][0]].route}}

^ might need to ensure all {} and match

I should explain what the monster in my previous answer does:

hostvars[ ]. <= gives you access to the variable (varname) for a ‘non current host’ (hostname), otherwise you could just use .

groups[service_name][0] <== this retrieves the first hostname from the current groupname in the service_name variable.

compose both and your template ‘should’ work

Thanks a lot for the explanation. I will give it a try!

I changed my template to:

{% for service_name in groups|sort %} {% if service_name not in ['all', 'ungrouped'] %} {% if hostvars[groups[service_name][0]].route %} {% else %} {% endif %} {% for host in groups[service_name]|sort %} {{ host }} {% endfor %} {% endif %} {% endfor %}

The idea is to have a route next to id in the xml it’s generating if it has a route, otherwise, do not add a route to the xml.

I get an odd error back stating:

[localhost] => {‘msg’: 'host not found: ', ‘failed’: True}

Keep in mind, my hosts I am running this against is localhost. The idea behind this playbook is to just generate an xml file via the services inventory file.

Adding [0] after the groups[service_name] command is what is causing it to blow up.

I figured out what was wrong. Some of my groups did not have servers.

It now runs, but everything in the generated xml has the same route. I will continue working on this, but the help so far was huge. Much further than I was before.

removing the [0] should return a list, not a single host, see if this is a bit cleaner

{% for service_name in groups|sort|difference([‘all’, ‘ungrouped’]) %}
{% set first_host = groups[service_name][0] %}
{% if ‘route’ in hostvars[first_host] %}

this also assumes that the first host in the group has the correct route var (it can be overridden by individual hosts)

Understood. The issue is all of the groups have the same host. What seems to be happening is the last route I assign to that host is what is used for all three. I will have to make the routevariables unique for each and call them all separately. Maybe something like this:

Inventory:

[WebApp_Login:vars]
WebApp_Login_route=login

[WebApp_number2]
KSQ-B-WEB-D01

[WebApp_number2:vars]
WebApp_number2_route=exposureindexbuilder

[WebApp_number3]
KSQ-B-WEB-D01

[WebApp_number3:vars]
WebApp_number3_route=marketdataadministration

{% for service_name in groups|sort|difference([‘all’, ‘ungrouped’]) %}
{% set first_host = groups[service_name][0] %}
{% if ‘service_name_route’ in hostvars[first_host] %}

This is what I am working on now. Thanks again for all of your help.

I realize I am doing something out of the ordinary here. (Not using this inventory file as a typical inventory file.)

This is what I came up with and it’s now working great! Thanks a lot for the help!

{% set route = service_name + “_route” %}
{% if hostvars[groups[service_name][0]][route] %}

{% else %}

{% endif %}

Good deal!

FYI – It looks like for each group of hosts in the list “groups” the OP wants to do print some things. If so, this first outer loop should just be

{% for service_name in group_names|sort %}

Versus “groups” above. Else service_name isn’t a string, it’s a list of hosts if you had “groups” instead.