如何根据匹配的键/值详细信息将字典中的项目组合到字典列表中

问题描述 投票:0回答:1

我有一个字典列表

    "tor_vlans": [
        {
            "switch-ls01": {
                "Vlan1": {
                    "id": "1",
                    "ip": "unassigned",
                    "ok": "NO",
                    "protocol": "down",
                    "status": "up"
                },
                "Vlan10": {
                    "id": "10",
                    "ip": "10.10.10.2/24",
                    "ok": "YES",
                    "protocol": "up",
                    "status": "up"
                },
                "Vlan20": {
                    "id": "20",
                    "ip": "10.10.20.2/24",
                    "ok": "YES",
                    "protocol": "up",
                    "status": "up"
                }
            }
        }
    ]

使用 ansible.utils.ipaddr 模块,我从上面提取了 ip 值,并创建了一个新字典,其中包含每个子网的其他详细信息

    "subnet_details": {
        "10.10.10.2/24": {
            "dhcp_scope": "10.10.10.4-10.10.10.254",
            "tor_1_ip": "10.10.10.2/24",
            "tor_2_ip": "10.10.10.3/24",
            "vrrp": "10.10.10.1/24"
        },
        "10.10.20.2/24": {
            "dhcp_scope": "10.10.20.4-10.10.20.254",
            "tor_1_ip": "10.10.20.2/24",
            "tor_2_ip": "10.10.20.3/24",
            "vrrp": "10.10.20.1/24"
        }
    }

我正在尝试通过将 tor_vlans 列表中的 ip 值与 subnet_details 中的 keys

进行匹配,将两组字典组合成一个新的字典列表。

使用下面的 Jinja2 模板

    - name: Combine both based on matching ips and keys
      ansible.builtin.set_fact:
        my_new_dict: |
          {% for tor in tor_vlans %}
          {% for key,value in tor.items() %}
          {% for vlan,facts in value.items() %}
          {% for cidr,param in subnet_details.items() %}
          {% if cidr in facts %}
          {{ key }}:
            {{ vlan }}:
              {{ facts }}
              {{ param }}
          {% else %}
          {{ key }}:
            {{ vlan }}:
              {{ facts }}
          {% endif %}
          {% endfor %}
          {% endfor %}
          {% endfor %}
          {% endfor %}

预期输出为

    "my_new_dict": [
        {
            "switch-ls01": {
                "Vlan1": {
                    "id": "1",
                    "ip": "unassigned",
                    "ok": "NO",
                    "protocol": "down",
                    "status": "up"
                },
                "Vlan10": {
                    "id": "10",
                    "ip": "10.10.10.2/24",
                    "ok": "YES",
                    "protocol": "up",
                    "status": "up",
                    "dhcp_scope": "10.10.10.4-10.10.10.254",
                    "tor_1_tep_ip": "10.10.10.2/24",
                    "tor_2_tep_ip": "10.10.10.3/24",
                    "vrrp": "10.10.10.1/24"
                },
                "Vlan20": {
                    "id": "20",
                    "ip": "10.10.20.2/24",
                    "ok": "YES",
                    "protocol": "up",
                    "status": "up",
                    "dhcp_scope": "10.10.20.4-10.10.20.254",
                    "tor_1_tep_ip": "10.10.20.2/24",
                    "tor_2_tep_ip": "10.10.20.3/24",
                    "vrrp": "10.10.20.1/24"
                }
            }
        }
    ]

我得到的实际输出是

    "my_new_dict|from_yaml": {
        "switch-ls01": {
            "Vlan20": {
                "id": "20",
                "ip": "10.10.20.2/24",
                "ok": "YES",
                "protocol": "up",
                "status": "up"
            }
        }
    }

如果除了使用 Jinja 之外还有其他梳理方法,请告诉我。

同样,如果可以使用 ansible.utils.ipaddr 模块直接在 tor_vlans 中创建子网详细信息,我也无法弄清楚。

“Vlan1”、“Vlan10”等...在尝试直接在 tor_vlans 上使用 ipaddr 模块时给我带来了问题,因为这些密钥是动态学习的,所以我不能假设它们总是相同的,即有时它们可能是“Vlan25”、“Vlan55”等...

我找到了一些关于 Python 的帖子,但是似乎找不到任何类似的 Ansible 帖子

dictionary ansible jinja2 key-value
1个回答
0
投票

创建更新列表

    update: |
      {% filter from_yaml %}
      {% for vlan in tor_vlans %}
      {% for sw,vlans in vlan.items() %}
      [ {{ sw }}: {
      {% for k,v in vlans.items() %}
      {% for s,d in subnet_details.items() %}
      {% if [v.ip]|ansible.utils.ipaddr(s)|length > 0 %}
      {{ k }}: {{ v|combine(d) }},
      {% endif %}
      {% endfor %}
      {% endfor %} },
      {% endfor %} ]
      {% endfor %}
      {% endfilter %}

给予

  update:
  - switch-ls01:
      Vlan10:
        dhcp_scope: 10.10.10.4-10.10.10.254
        id: '10'
        ip: 10.10.10.2/24
        ok: 'YES'
        protocol: up
        status: up
        tor_1_ip: 10.10.10.2/24
        tor_2_ip: 10.10.10.3/24
        vrrp: 10.10.10.1/24
      Vlan20:
        dhcp_scope: 10.10.20.4-10.10.20.254
        id: '20'
        ip: 10.10.20.2/24
        ok: 'YES'
        protocol: up
        status: up
        tor_1_ip: 10.10.20.2/24
        tor_2_ip: 10.10.20.3/24
        vrrp: 10.10.20.1/24

压缩列表并合并项目

    my_new_dict: "{{ tor_vlans |
                     zip(update) |
                     map('combine', recursive=True) }}"

给予

  my_new_dict:
  - switch-ls01:
      Vlan1:
        id: '1'
        ip: unassigned
        ok: 'NO'
        protocol: down
        status: up
      Vlan10:
        dhcp_scope: 10.10.10.4-10.10.10.254
        id: '10'
        ip: 10.10.10.2/24
        ok: 'YES'
        protocol: up
        status: up
        tor_1_ip: 10.10.10.2/24
        tor_2_ip: 10.10.10.3/24
        vrrp: 10.10.10.1/24
      Vlan20:
        dhcp_scope: 10.10.20.4-10.10.20.254
        id: '20'
        ip: 10.10.20.2/24
        ok: 'YES'
        protocol: up
        status: up
        tor_1_ip: 10.10.20.2/24
        tor_2_ip: 10.10.20.3/24
        vrrp: 10.10.20.1/24

用于测试的完整剧本示例

- hosts: all

  vars:

    tor_vlans:
      - switch-ls01:
          Vlan1:
            id: '1'
            ip: unassigned
            ok: 'NO'
            protocol: down
            status: up
          Vlan10:
            id: '10'
            ip: 10.10.10.2/24
            ok: 'YES'
            protocol: up
            status: up
          Vlan20:
            id: '20'
            ip: 10.10.20.2/24
            ok: 'YES'
            protocol: up
            status: up

    subnet_details:
      10.10.10.2/24:
        dhcp_scope: 10.10.10.4-10.10.10.254
        tor_1_ip: 10.10.10.2/24
        tor_2_ip: 10.10.10.3/24
        vrrp: 10.10.10.1/24
      10.10.20.2/24:
        dhcp_scope: 10.10.20.4-10.10.20.254
        tor_1_ip: 10.10.20.2/24
        tor_2_ip: 10.10.20.3/24
        vrrp: 10.10.20.1/24

    update: |
      {% filter from_yaml %}
      {% for vlan in tor_vlans %}
      {% for sw,vlans in vlan.items() %}
      [ {{ sw }}: {
      {% for k,v in vlans.items() %}
      {% for s,d in subnet_details.items() %}
      {% if [v.ip]|ansible.utils.ipaddr(s)|length > 0 %}
      {{ k }}: {{ v|combine(d) }},
      {% endif %}
      {% endfor %}
      {% endfor %} },
      {% endfor %} ]
      {% endfor %}
      {% endfilter %}

    my_new_dict: "{{ tor_vlans |
                     zip(update) |
                     map('combine', recursive=True) }}"

  tasks:

    - debug:
        var: update
    - debug:
        var: my_new_dict
© www.soinside.com 2019 - 2024. All rights reserved.