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

Ansible合并列表内字典元素生成VM网络配置失败求助

问题需求

需要从API返回的子网信息列表中提取VLAN编号,整合成如下格式的单一字典,用于调用API创建VM:

"network": {
    "nic0": [
        "100"
    ],
    "nic1": [
        "200"
    ]
},

尝试过程

  1. 通过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
            }
        }
    }
]
  1. 使用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"
            ]
        }
    ]
}
  1. 后续尝试合并字典列表时,错误地将字典转为字符串,导致合并操作报错:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:54:54