3

I have a jinja2 template designed to print out the IP addresses of ec2 instances (tagged region: au) :

{% for host in groups['tag_region_au'] %}

My problem is I can't for the life of me work out how to include only hosts that exist in one group and NOT another (however each host may be in two or more groups), for example in python the following works:

( (a in list) and ( a not in list2) )

However the following does not:

{% for (host in groups['tag_region_au']) and (host not in groups['tag_state_live']) %}

Any idea how I can include only hosts that exist in one group and that do not exist in the another group?

Hilton D
  • 31
  • 1
  • 4

2 Answers2

3

You can use built-in group_names variable in this case. group_names variable is a list of all groups that the current host is a member of.

My hosts file:

[tag_region_au]
host1 
host2
host3

[tag_state_live]
host2
host3
host4

My template file test.j2:

{% for host in groups['tag_region_au'] %}
{% if hostvars[host]['group_names']|length == 1 %}
{{ host }} - {{ hostvars[host]['group_names'] }}
{% endif %}
{% endfor %}

hostvars is a dict whose keys are ansible hostname and values are dict map variable name to value. length is jinja filter return number of items in list.

Result:

host1 - ['tag_region_au']

If you change == to >, the result is:

host2 - ['tag_region_au', 'tag_state_live']
host3 - ['tag_region_au', 'tag_state_live']

Update:

To check host in group A and not in group B, you can use difference filter. Syntax is {{ list1 | difference(list2) }}.

Here is example template:

{% for host in groups['tag_region_au']|difference(groups['tag_state_live']) %}
{{ host }}
{% endfor %}

Result is: host1

nghnam
  • 661
  • 7
  • 10
  • While this technically answers the question it fails if there is a third or more groups that the host is in that the OP doesn't mind having the host be part of. It would be interesting to see a way to do this where you can explicitly say that the host should be in one specific group and not in another specific group. – ydaetskcoR Sep 12 '15 at 17:16
  • I don't know what you are talking about. Can you explain it? You can use `{% if %}` to check anything you want. – nghnam Sep 13 '15 at 00:44
  • Thanks for your answer @nghnam however each host is in two or more groups at any one time. I really need a statement that says "in group a and not in group b" – Hilton D Sep 13 '15 at 01:19
1

A really clean way to do it if you don't mind starting a new play for the templating stuff is to use a group expression in the play target (which is exactly what they're for). For example:

- hosts: tag_region_au:!tag_state_live
  tasks:
 - template: (bla)

Then in your template, you'd reference the play_hosts var to get at the list of filtered hosts.

nitzmahone
  • 13,720
  • 2
  • 36
  • 39