2016-03-25 37 views
2

我有像这样的列表: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 elemnents的唯一名称,所以在这个例子中,我要循环

- 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项目。

回答

2

如果事情与Ansible过于复杂,而且无法映射出你的想法,那么这是一个不应该做的指示。也许可以用一些Jinja过滤器和一些循环中的set_fact任务。但是不要,Ansible不是一种编程语言,不应该这样使用。 Ansible有两个主要优势:可读性和可扩展性。不要忽视第一种。

with_subelements实际上是一个插件本身,只是它是一个核心插件。只需复制它并创建您自己的with_unique_subelements插件。这里是code of with_subelements。第100行是将元素添加到返回列表的位置。这就是你可以挂钩并执行检查,如果该项目已被添加。

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

1

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 
+0

您如何使用它?你还会用'with_subelements:'一起使用它吗? – MaxU

+1

@MaxU不,这是一个平面列表,所以使用'with_items'来迭代它的项目。 – Zulakis

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

返回一个列表的列表,如所依赖一个列表。要将列表列表整合成一个列表,请使用内置平坦查找:

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

有趣!我无法在任何地方找到这种查找。使用_....处理程序的所有 – Zulakis

+0

都是查找 –