【问题标题】:ansible/jinja2 get unique subelementsansible/jinja2 获取唯一的子元素
【发布时间】:2016-03-25 22:07:03
【问题描述】:

我有一个这样的列表:

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

【问题讨论】:

    标签: python ansible jinja2


    【解决方案1】:

    如果使用 Ansible 让事情变得过于复杂,并且您无法围绕它进行思维导图,则表明不应该这样做。也许在循环中使用一些 Jinja 过滤器和一些 set_fact 任务是可能的。但不要,Ansible 不是一种编程语言,不应该这样使用。 Ansible 有两个主要优势:可读性和可扩展性。不要忽略后者而破坏前者。

    with_subelements其实本身就是一个插件,只是它是一个核心插件。只需复制它并创建您自己的with_unique_subelements 插件。这是code of with_subelements。第 100 行是将元素添加到返回列表的位置。您可以在此处进行挂钩并检查该项目是否已添加。

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

    【讨论】:

      【解决方案2】:
      host_depends|map(attribute='depends')|list
      

      返回一个列表列表,就像depends 是一个列表。要将此列表扁平化/合并为一个列表,请使用内置扁平化查找:

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

      【讨论】:

      • 有趣!我在任何地方都找不到此查找记录。
      【解决方案3】:

      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
      

      【讨论】:

      • 你如何使用它?还和with_subelements:一起用吗?
      • @MaxU 不,这是一个平面列表,所以使用 with_items 来迭代它的项目。
      猜你喜欢
      • 1970-01-01
      • 2017-12-11
      • 2023-03-24
      • 2017-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      相关资源
      最近更新 更多