使用map()函数在Jinja2 / Ansible中基于唯一键加入两个dicts列表

时间:2017-03-27 16:44:44

标签: templates dictionary ansible jinja2

如果有些人有更好的想法,我会陈述最终目标。我正在尝试使用ansible在nagios中设置主机监控。我想使用变量集合来定义某些服务的默认值,并让这些变量能够被更具体的变量覆盖。

所以我最终得到两个dicts列表,并希望将第一个列表作为默认值,并将其与第二个列表中的第二个列表合并,并使用匹配的键名称优先。

list1: [
{u'type': u'local-service', u'command': u'something', u'name': 
u'AUTODISCOVER'},
{u'type': u'pager-service', u'command': u'something', 
u'name': u'RPC'},
{u'type': u'local-service', u'command': u'something', u'name': u'PING''} ]

list2: [
{u'type': u'local-service', u'command': u'different', u'name': u'AUTODISCOVER'} ]

结果列表为:

list: [
{u'type': u'local-service', u'command': u'different', u'name': u'AUTODISCOVER'},
{u'type': u'pager-service', u'command': u'something', u'name': u'RPC'},
{u'type': u'local-service', u'command': u'something', u'name': u'PING''} ]

在我的jinja2模板中,我有这个:

{% set services = item.services | union( server_types[item.type].services ) %}
{% for service in services | sort(attribute='name') %}
{{ service.name }}
{% endfor %}

上面是一些调试输出 这样可以正常工作并列出已排序的服务名称属性。

{% for service in services | map(attribute='name') | list | unique %}
define  service{
    use                   {{ service.type | default('local-service') }}
    host_name             {{ item.host }}
    service_description   {{ service.name }}
    check_command         {{ service.command }}
}
{% endfor %}

这会导致此错误

AnsibleUndefinedVariable: 'unicode object' has no attribute 'name'

所以很明显它正在将dict对象转换为字符串并尝试映射它导致错误。但是看一下这些文档,我的语法似乎是正确的,它在第一个循环的sort()过滤器中作为一个dict对象。那么为什么地图功能在第二次循环中失败了呢?

1 个答案:

答案 0 :(得分:0)

评论回答:

  

services | map(attribute='name') | list仅从name列表中的每个元素获取services个属性并形成新列表