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
相关产品推荐
相关产品推荐

