You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible如何为字典列表批量添加不同前缀生成新列表

Ansible 字典列表与前缀列表全组合实现方案

现有多个列表(list_node_profile、list_node_id、list_pod_id、list_prefix),已基于前三个列表构建出包含4个字典的列表data。尝试用with_together循环给每个字典添加prefix字段时,仅前两个字典赋值成功,后两个prefix为null。需要实现将list_prefix中的每个前缀分别与data中所有字典组合,生成包含8个字典的新列表data2。


现有数据结构

TASK [debug] *******************************************************************
ok: [26.167.26.11] => {
    "list_node_profile": [
        "L305-306-test1-NP",
        "L305-306-test2-NP",
        "L405-406-test1-NP",
        "L405-406-test2-NP"
    ]
}

TASK [debug] *******************************************************************
ok: [26.167.26.11] => {
    "list_node_id": [
        "305",
        "306",
        "405",
        "406"
    ]
}

TASK [debug] *******************************************************************
ok: [26.167.26.11] => {
    "list_pod_id": [
        "3",
        "3",
        "4",
        "4"
    ]
}

TASK [debug] *******************************************************************
ok: [26.167.26.11] => {
    "list_prefix": [
        "10.x.x.42/31",
        "10.x.x.41/31"
    ]
}

TASK [Create dictionary structure] ***************************************************
ok: [26.167.26.11] => (item=['L305-306-test1-NP', '305', '3'])
ok: [26.167.26.11] => (item=['L305-306-test2-NP', '306', '3'])
ok: [26.167.26.11] => (item=['L405-406-test1-NP', '405', '4'])
ok: [26.167.26.11] => (item=['L405-406-test2-NP', '406', '4'])

TASK [debug] *******************************************************************
ok: [26.167.26.11] => {
    "data": [
        {
            "description": "CHG0101TEST",
            "l3out": "Shared-Test-Internet-L3Out",
            "nexthop": "10.x.x.129",
            "node_id": "305",
            "node_profile": "L305-306-test1-NP",
            "pod_id": "3",
            "tenant": "common"
        },
        {
            "description": "CHG0101TEST",
            "l3out": "Shared-Test-Internet-L3Out",
            "nexthop": "10.x.x.129",
            "node_id": "306",
            "node_profile": "L305-306-test2-NP",
            "pod_id": "3",
            "tenant": "common"
        },
        {
            "description": "CHG0101TEST",
            "l3out": "Shared-Test-Internet-L3Out",
            "nexthop": "10.x.x.129",
            "node_id": "405",
            "node_profile": "L405-406-test1-NP",
            "pod_id": "4",
            "tenant": "common"
        },
        {
            "description": "CHG0101TEST",
            "l3out": "Shared-Test-Internet-L3Out",
            "nexthop": "10.x.x.129",
            "node_id": "406",
            "node_profile": "L405-406-test2-NP",
            "pod_id": "4",
            "tenant": "common"
        }
    ]
}

尝试的代码

- name: Create dictionary structure 2
  set_fact:
    data2: "{{ data2|default([]) + [ item.1 | combine({'prefix': item.0}, recursive=True)] }}"
  with_together:
    - "{{ list_prefix }}"
    - "{{ data }}"

错误输出

"data2": [
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "305",
        "node_profile": "L305-306-test1-NP",
        "pod_id": "3",
        "prefix": "10.x.x.42/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "306",
        "node_profile": "L305-306-test2-NP",
        "pod_id": "3",
        "prefix": "10.x.x.41/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "405",
        "node_profile": "L405-406-test1-NP",
        "pod_id": "4",
        "prefix": null,
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "406",
        "node_profile": "L405-406-test2-NP",
        "pod_id": "4",
        "prefix": null,
        "tenant": "common"
    }
]

期望输出

"data2": [
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "305",
        "node_profile": "L305-306-test1-NP",
        "pod_id": "3",
        "prefix": "10.x.x.42/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "306",
        "node_profile": "L305-306-test2-NP",
        "pod_id": "3",
        "prefix": "10.x.x.42/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "405",
        "node_profile": "L405-406-test1-NP",
        "pod_id": "4",
        "prefix": "10.x.x.42/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "406",
        "node_profile": "L405-406-test2-NP",
        "pod_id": "4",
        "prefix": "10.x.x.42/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "305",
        "node_profile": "L305-306-test1-NP",
        "pod_id": "3",
        "prefix": "10.x.x.41/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "306",
        "node_profile": "L305-306-test2-NP",
        "pod_id": "3",
        "prefix": "10.x.x.41/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "405",
        "node_profile": "L405-406-test1-NP",
        "pod_id": "4",
        "prefix": "10.x.x.41/31",
        "tenant": "common"
    },
    {
        "description": "CHG0101TEST",
        "l3out": "Shared-Test-Internet-L3Out",
        "nexthop": "10.x.x.129",
        "node_id": "406",
        "node_profile": "L405-406-test2-NP",
        "pod_id": "4",
        "prefix": "10.x.x.41/31",
        "tenant": "common"
    }
]

解决方案

with_together的逻辑是按索引一一配对两个列表元素,当其中一个列表长度较短时,超出部分会填充null,这就是后两个字典prefix为null的原因。我们需要的是两个列表的笛卡尔积(每个前缀对应所有字典),可以用以下两种方法实现:

方法1:使用with_nested(兼容旧版Ansible)

- name: 生成全组合字典列表
  set_fact:
    data2: "{{ data2 | default([]) + [ item.1 | combine({'prefix': item.0}) ] }}"
  with_nested:
    - "{{ list_prefix }}"
    - "{{ data }}"

方法2:使用loop+query(Ansible 2.5+推荐写法)

- name: 生成全组合字典列表
  set_fact:
    data2: "{{ data2 | default([]) + [ item.1 | combine({'prefix': item.0}) ] }}"
  loop: "{{ query('nested', list_prefix, data) }}"

说明

nested查询会生成两个输入列表的笛卡尔积,即每个前缀都会与data中的每一个字典配对,总循环次数为2*4=8,正好生成包含8个字典的data2列表,满足需求。


内容的提问来源于stack exchange,提问作者Tomáš Halagan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:07:35