Ansible合并列表内字典元素生成VM网络配置失败求助
问题需求
需要从API返回的子网信息列表中提取VLAN编号,整合成如下格式的单一字典,用于调用API创建VM:
"network": { "nic0": [ "100" ], "nic1": [ "200" ] },
尝试过程
- 通过API以子网为检索条件获取网络信息,存储为事实
net_info,数据结构如下:
[ { "item": "10.20.0.0", "json": { "data": { "attributes": { "az": "a", "env": "test" }, "subnet": "10.20.0.0", "vlanNumber": 100 } } }, { "item": "10.20.1.0", "json": { "data": { "attributes": { "az": "a", "env": "test" }, "subnet": "10.20.1.0", "vlanNumber": 200 } } } ]
- 使用
set_fact循环提取VLAN编号,生成了字典列表而非预期的单一字典:
- name: Set nic number and vlan facts for provision payload set_fact: Network: "{{ Network | default([]) + [{ 'nic' + nicnum|string: [item.json.data.vlanNumber | string] }] }}" loop: "{{ net_info.results }}" loop_control: index_var: nicnum
得到结果:
{ "Network": [ { "nic0": [ "100" ] }, { "nic1": [ "200" ] } ] }
- 后续尝试合并字典列表时,错误地将字典转为字符串,导致合并操作报错:
fatal: [localhost]: FAILED! => {"msg": "failed to combine variables, expected dicts but got a 'dict' and a 'str': \n{\"nics\": \"{'nic1': ['2308']}\"}\n\"nics\""}
解决方案
无需先生成字典列表再合并,以下两种方法可直接生成目标格式的单一字典:
方法一:循环合并字典
在每次循环中使用combine过滤器,将新生成的nic字典逐步合并到已有字典中:
- name: Build network dict directly set_fact: network: "{{ network | default({}) | combine({ 'nic' + nicnum|string: [item.json.data.vlanNumber | string] }) }}" loop: "{{ net_info.results }}" loop_control: index_var: nicnum
执行后直接得到目标结果:
{ "network": { "nic0": ["100"], "nic1": ["200"] } }
方法二:用dict过滤器一次性生成
先构造键名列表和对应的值列表,再通过dict过滤器组合成目标字典:
- name: Create network dict with dict filter set_fact: network: "{{ dict(nic_keys | zip(nic_values)) }}" vars: nic_keys: "{{ net_info.results | indices | map('regex_replace', '^', 'nic') | list }}" nic_values: "{{ net_info.results | map(attribute='json.data.vlanNumber') | map('string') | map('list') | list }}"
nic_keys:通过indices获取循环索引,拼接成nic0、nic1格式的键名nic_values:提取每个结果中的VLAN编号,转为字符串后包装成列表
两种方法都能直接得到符合API调用要求的network字典,无需额外的合并或扁平化操作。
内容的提问来源于stack exchange,提问作者tom
相关产品推荐
相关产品推荐

