从Ansible中的映射列表中提取属性列表的正确方法

从Ansible中的映射列表中提取属性列表的正确方法,ansible,Ansible,我正在寻找一种非丑陋的方法,从Ansible中的映射列表中提取特定值的列表。我可以找到一些方法,比如在这里:,但我所看到的一切都非常丑陋,而且我觉得应该有一种方法可以更清楚地告诉将来阅读它的人正在做什么。我可以写一个过滤器,但我觉得这应该是不必要的,因为这必须定期出现 我在Ansible中有这样的数据结构: interfaces: - name: eth0 subnet: 192.168.2 netmask: 255.255.255.0 static_dhcp_hos

我正在寻找一种非丑陋的方法,从Ansible中的映射列表中提取特定值的列表。我可以找到一些方法,比如在这里:,但我所看到的一切都非常丑陋,而且我觉得应该有一种方法可以更清楚地告诉将来阅读它的人正在做什么。我可以写一个过滤器,但我觉得这应该是不必要的,因为这必须定期出现

我在Ansible中有这样的数据结构:

interfaces:
  - name: eth0
    subnet: 192.168.2
    netmask: 255.255.255.0
    static_dhcp_hosts:
      - {name: "hosta", mac: "00:01:02:03:04:05", ip: "192.168.2.20"}
  - name: eth1
    subnet: 192.168.5
    netmask: 255.255.255.0
    static_dhcp_hosts:
      - {name: "hostb", mac: "00:02:03:04:05:06", ip: "192.168.5.20"}
      - {name: "hostc", mac: "00:03:04:05:06:07", ip: "192.168.5.21"}
我想得到一个以空格分隔的接口名列表,所以

eth0 eth1
显然,这只是示例数据,实际的顶级列表对于一个主机有10个元素。我知道我可以使用连接过滤器从接口列表中获取我想要的字符串,以及如何做到这一点

有人能推荐一种很好的方法来制作列表吗?这种方法对未来的维护人员来说是可读的(代码/配置应该尽可能地自文档化(而不是进一步的))

我想做一些类似的事情

{% for interface in interfaces %}{{ interface.name }} {% endfor %}

在Python中

但是,恕我直言,在角色的task/main.yml中使用这样的jinja2循环是不可能的,或者被认为是不好的做法,而且,正如我所说的,感觉不应该为此使用自定义过滤器

(这个角色不仅仅是配置一个DHCP服务器,所以请不要只是建议一个已经存在的角色来配置,这并不能解决我的问题)

任何非丑恶的方式都会得到赞赏,人们也会确认没有非丑恶的方式

我正在使用Ansible 2.3,但我仍然对答案感兴趣,即使它们只适用于更高版本

编辑:

以下是:

"{{ internal_interfaces | items2dict(key_name='name',value_name='name') | list | join(\" \") }}"

这是我能想到的最丑的。它从列表中生成一个字典,其中键和值都来自列表中字典的name属性,然后将该字典强制转换为一个列表,该列表只给出一个键列表。如果有人能想到任何东西,我还是想要一些不那么迟钝和丑陋的东西,或者如果有人认为没有更好的东西,我还是想要任何一位安斯布尔大师回答。

地图和连接是您所需要的:

- set_fact:
    interface_names: "{{ interfaces | map(attribute='name') | join(' ') }}"

嗯。我太傻了。有一个很好的方法可以做到这一点:

"{{ interfaces | map(attribute='name') | join(\" \") }}"

map的输出是一个生成器,它生成一个接口名列表,join将其转换为我想要的字符串。完美。

在剧本本身中,我需要空格分隔的字符串值。我只是在发布了我自己的答案后才看到你的答案,尽管在我需要它的地方(添加到加入过滤器中),它仍然可以正常工作。谢谢很高兴接受你的回答,但它回答了一个稍微不同的问题。如果你想编辑它,我会接受它(我不确定,这会不会给你带来某种因果报应,我不会用太多)。“{interfaces}map(attribute='name')|join(\“\”)}”是我需要的。谢谢你的评论。我在你的问题中看到了Jinja模板字符串,并假设最终的用途是在模板中。但是,正如你所说,如果你只是想在剧本中使用空格分隔的字符串,那么加入是一个不错的选择。编辑。我应该避免这样做以避免混淆,但是,是的,我需要它在剧本中。谢谢我把你的答案设为答案。我投了更高的票,但我自己的声誉太低,无法增加分数。注意:
map(attribute='name')| unique | join(“”)
如果您需要像我一样删除重复项。
"{{ interfaces | map(attribute='name') | join(\" \") }}"