在ansible列表中展平和过滤复杂结构 - dict列表

时间:2018-01-29 04:56:23

标签: scripting ansible jinja2 devops

我有以这种方式表示的数据:

 {
    "key1": [{
      "name": "some name1",
      "index": "some idx1"
    },
    {
      "name": "some name2",
      "index": "some idx2"
    },
    {
      "name": "some name3",
      "index": "some idx3"
    }],
    "key2": [{
      "name": "some name4",
      "index": "some idx4"
    },
    {
      "name": "some name5",
      "index": "some idx5"
    },
    {
      "name": "some name6",
      "index": "some idx6"
    }]
}    

我想将上面的内容转换为此内容,这基本上是一个字典,其中包含索引列表的现有键。

{ 
      "key1": [some idx1, some idx2, some idx3],
      "key2": [some idx4, some idx5, some idx6]
}

我已经看过几个使用map,extract和combine的例子,但还不能让它工作。然而,我能够使用jinja,代码如下。 我的问题是,实现上述目标的最佳方法是什么。对于这类事情,建议的最佳做法是什么 - 有没有理由不使用jinja2进行更复杂的操作(鉴于我所看到的一个衬里过于复杂,其他人可能难以想象out - 因此使脚本难以维护。)

这里有代码可以解决问题,但同样,不确定是否有最好的方法来实现这一目标:

- hosts: local
  tags: test1
  gather_facts: False
  vars:
    dict1:
      key1:
        - { name: some name1, index: some idx1 }
        - { name: some name2, index: some idx2 }
        - { name: some name3, index: some idx3 }
      key2:
        - { name: some name4, index: some idx4 }
        - { name: some name5, index: some idx5 }
        - { name: some name6, index: some idx6 }
  tasks:      
  - name: "dict of list of dict"
    set_fact:
      index_map: |
        {% set map = dict() %}
        {% for k,v in dict1.iteritems() %}
          {% set x=map.__setitem__(k, []) %}
          {% for item in v %}
            {% set x= map[k].append(item.name) %}
          {% endfor %}
        {% endfor %}
        {{ map }}
  - debug: 
      msg: "{{ index_map }}"

要扩展问题我试图解决更多:给定'索引',我想找到它与之关联的密钥。目标结构可以让我更容易地想到这一点。所以要么是索引列表的键的dict,要么是key的索引dict就足够了。

感谢您的任何建议..

1 个答案:

答案 0 :(得分:3)

Ansible在词典中使用键的工具相当有限(参见this answer)。

dictsort过滤器有时也很方便,就像你的情况一样 它将dict转换为列表,您可以使用json_query来处理它。

这是一个按索引名称获取根密钥的任务:

- debug:
    msg: "key is '{{ list_with_keys | json_query(qry) }}' for index {{ item }}"
  vars:
    list_with_keys: "{{ dict1 | dictsort | to_json | from_json }}"
    qry: "[?contains(([1] | [].index),`{{ item }}`)][] | [0]"
  with_items:
    - some idx5
    - some idx3

其中dict1取自您的示例。