Ansible Jinja2模板在for循环中有条件

时间:2015-09-12 14:45:41

标签: ansible jinja2

我有一个jinja2模板,用于打印出ec2实例的IP地址(标记区域:au):

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

我的问题是我不能为我的生活找出如何仅包含存在于一个组而不是另一个组中的主机(但每个主机可能在两个或更多组中),例如在python中以下工作:

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

但以下情况并非如此:

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

知道我怎么只能包含一个组中存在且另一个组中不存在的主机?

2 个答案:

答案 0 :(得分:3)

在这种情况下,您可以使用内置group_names变量。 group_names变量是当前主机所属的所有组的列表。

我的hosts文件:

[tag_region_au]
host1 
host2
host3

[tag_state_live]
host2
host3
host4

我的模板文件test.j2

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

hostvars是一个dict,其键是ansible hostname,值是dict map variable name to value。 length是jinja过滤器返回列表中的项目数。

结果:

host1 - ['tag_region_au']

如果您将==更改为>,则结果为:

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

更新

要检查A组中的主机而不是B组中的主机,您可以使用difference过滤器。语法是{{ list1 | difference(list2) }}

以下是示例模板:

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

结果是:host1

答案 1 :(得分:0)

如果你不介意为模板游戏开始一个新游戏,那么一个非常干净的方法就是在游戏目标中使用一个组表达式(这正是他们所要做的)。例如:

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

然后在您的模板中,您引用play_hosts var来获取已过滤主机列表。