使用 Ansible 重新格式化 JSON 的最佳方法是什么?

使用 Ansible 重新格式化 JSON 的最佳方法是什么?

我在变量中有一个 JSON:

{
"device_vlans": {
    "1": {
        "name": "default",
        "interfaces": [
            "GigabitEthernet1/1",
            "GigabitEthernet1/2",
            "GigabitEthernet1/3"
        ]
    },
    "20": {
        "name": "VLAN20",
        "interfaces": [
            "GigabitEthernet1/2"
        ]
    },
    "30": {
        "name": "VLAN30",
        "interfaces": [
            "GigabitEthernet1/3"
        ]
    }
}

但我需要它看起来更像这样:

{
"device_vlans": {
    "GigabitEthernet1/1": {
        "vlans": [
            "1"
        ]
    },
    "GigabitEthernet1/2": {
        "vlans": [
            "1",
            "20"
        ]
    },
    "GigabitEthernet1/3": {
        "vlans": [
            "1",
            "30"
        ]
    }
}

目前,我正在循环遍历设备的所有接口,并且在循环中,我正在使用 循环遍历 device_vlans 变量中的所有项目when: item == interface。它真的很慢,并给我带来了问题。

有没有更好的方法可以用 ansible 来实现这个效果?

我想到自定义过滤器可以解决这个问题吗?

答案1

创建设备和接口列表

    - set_fact:
        dev_ifc: "{{ dev_ifc|d([]) + [{'dev': item.1, 'ifc': item.0.key}] }}"
      with_subelements:
        - "{{ device_vlans|dict2items }}"
        - value.interfaces

给出

  dev_ifc:
    - {dev: GigabitEthernet1/1, ifc: '1'}
    - {dev: GigabitEthernet1/2, ifc: '1'}
    - {dev: GigabitEthernet1/3, ifc: '1'}
    - {dev: GigabitEthernet1/2, ifc: '20'}
    - {dev: GigabitEthernet1/3, ifc: '30'}

然后,按设备对列表进行分组并创建字典

    - set_fact:
        device_vlans: "{{ dict(key|zip(val)) }}"
      vars:
        arr: "{{ dev_ifc|groupby('dev') }}"
        key: "{{ arr|map('first')|list }}"
        val: "{{ arr|map('last')|
                     map('json_query', '[].ifc')|
                     map('community.general.dict_kv', 'interfaces')|
                     list }}"

给出

  device_vlans:
    GigabitEthernet1/1:
      interfaces: ['1']
    GigabitEthernet1/2:
      interfaces: ['1', '20']
    GigabitEthernet1/3:
      interfaces: ['1', '30']

可以避免在任务中进行迭代。相反,将迭代放入 Jinja2 中。例如,将以下声明放入合适的

    dev_ifc_str: |-
      {% for ifc in device_vlans.keys() %}
      {% for dev in device_vlans[ifc]['interfaces'] %}
      - {dev: {{ dev }}, ifc: {{ ifc }}}
      {% endfor %}
      {% endfor %}
    dev_ifc: "{{ dev_ifc_str|from_yaml }}"
    device_vlans2: "{{ dict(_key|zip(_val)) }}"
    _arr: "{{ dev_ifc|groupby('dev') }}"
    _key: "{{ _arr|map('first')|list }}"
    _val: "{{ _arr|map('last')|
                   map('json_query', '[].ifc')|
                   map('community.general.dict_kv', 'interfaces')|
                   list }}"

相关内容