ansible/jinja2获取唯一的子元素



我得到了这样的列表:

host_depends:
  - host: abc
    depends:
      - name: item1
      - name: item4
        type: asdf
      - name: item6
  - host: def
    depends:
      - name: item2
      - name: item4
      - name: item6

我需要在depends元素的唯一名称上循环,所以在这个例子中,我想在上循环

- item1 
- item2
- item4
- item6

基本上什么

debug: var=item.1.name
with_subelements:
  - "{{ host_depends }}"
  - depends

确实如此,但仅使用独特元素。

如何获取所有host_depends项的depends,以便对它们运行unique筛选器并将它们与with_items一起使用?

编辑:

我设法得到了所有depends项目的列表,如下所示:

host_depends|map(attribute='depends')|list

但从那以后,我无法将此列表缩减为name项。

如果Ansible让事情变得太复杂,而你无法将你的想法映射到它周围,这表明不应该这样做。也许在循环中使用一些Jinja过滤器和一些set_fact任务是可能的。但是不要这样做,Ansible不是一种编程语言,不应该这样使用。Ansible有两个主要优势:可读性和可扩展性。不要忽略后一个而打断第一个。

with_subelements实际上本身就是一个插件,只是它是一个核心插件。只需复制它并创建自己的with_unique_subelements插件。这是with_subelements的代码。第100行是元素添加到返回列表中的位置。这就是您可以挂接并实现检查该项是否已添加的地方。

将您相对于剧本的修改版本保存为lookup_plugins/unique_subelements.py,或者如果您使用Ansible 2,您也可以在任何角色中使用相同的路径存储它。

host_depends|map(attribute='depends')|list

返回一个列表列表,dependent是一个列表。要将此列表展开/组合为一个列表,请使用内置的展开查找:

lookup('flattened', host_depends|map(attribute='depends')) |map(attribute='name')|unique|list

host_depends|map(attribute='depends')|list返回一个列表列表,因为depends是一个列表。要将此列表展平/合并为一个列表:

将其添加为roles/<rolename>/filter_plugins/filter.py:

from ansible import errors
# This converts a list of lists into a single list
def flattenlist(l):
    try:
        return [item for sublist in l for item in sublist]
    except Exception, e:
        raise errors.AnsibleFilterError('split plugin error: %s' % str(e) )
class FilterModule(object):
    ''' A filter to split a string into a list. '''
    def filters(self):
        return {
            'flattenlist' : flattenlist
        }

并使用

host_depends|map(attribute='depends')|flattenlist|map(attribute='name')|unique|list

最新更新