将列表中的 2 个字典元素加入到 1 个中不起作用

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

我正在从前一个任务的 json 结果列表中提取数据,以获取基于子网的 VLAN 号。

使用这个我需要一个包含两个 vlan 的列表,格式为:

“nic1”:[“100”],“nic1”:[“200”]

我将使用它来调用另一个 api 来配置虚拟机,我必须在其中提供 vlan 信息列表,如下所示:

    "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
     }
}

接下来,我使用 net_info.results 仅提取 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

这给出:

ok: [localhost] => {
    "Network": [
        {
            "nic0": [
                "100"
            ]
        },
        {
            "nic1": [
                "200"
            ]
        }
    ]
}

理想情况下,上一步会给出所需的最终结果,但没有。 我尝试将网络展平,但没有效果,看起来与之前的输出相同。

我想在这一点上合并,但没有共同元素,所以我创建了第二个列表,以 nics 作为共同点:

- name: set new list with nics and items from Network
  set_fact:
    Network2: "{{ Network2 | default([]) + [{ 'nics': [item] | join() }] }}"
  loop: "{{ Network }}"

gives:

ok: [localhost] => {
    "Network2": [
        {
            "nics": "{'nic0': ['2309']}"
        },
        {
            "nics": "{'nic1': ['2308']}"
        }
    ]
}

我尝试了一个简单的映射,虽然很接近,但它在列表的每个元素上都包含额外的大括号和引号。

- name: Try mapping
  debug:
    msg: "{{ Network2 | map(attribute='nics') }}"

gives:

TASK [provisionvms : Try mapping] *******************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "{'nic0': ['2309']}",
        "{'nic1': ['2308']}"
    ]
}

最后我尝试合并(看起来与之前的任务相同),然后我尝试合并但它抱怨:

- name: show network2 merged and then combined
  debug:
    #msg: "{{ Network2 | community.general.lists_mergeby('nics') }}"
    msg: "{{ Network2 | ansible.builtin.combine('nics') }}"

-----
TASK [provisionvms : show network2 combined] ********************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "failed to combine variables, expected dicts but got a 'dict' and a 'str': \n{\"nics\": \"{'nic1': ['2308']}\"}\n\"nics\""}

我确实看到了 zip 过滤器,并认为这看起来很有希望,但不确定“values_list”是什么。

- name: Try zippig Network two based on nics
  debug:
    msg: "{{ Network2(nics | zip<unsure of this>)) }}"

我觉得这应该很简单,我只是不明白。

提前致谢。

linux ansible jinja2
1个回答
0
投票

问:“给出迭代结果

  net_info.results:
    - 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']

创建字典

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

A:获取属性列表vlanNumber

  vns: "{{ net_info.results | map(attribute='json.data.vlanNumber') }}"

给予

  vns:
    - ['100']
    - ['200']

创建索引列表

  idx: "{{ range(1, vns|length +1) }}"

给予

  idx:
  - 1
  - 2

创建字典键列表

  nic: "{{ ['nic'] | product(idx) | map('join') }}"

给予

  nic:
  - nic1
  - nic2

创建字典

  network: "{{ dict(nic|zip(vns)) }}"

在 YAML 中提供您想要的内容

  network:
    nic1: ['100']
    nic2: ['200']

,或 JSON

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

用于测试的完整剧本示例

- hosts: localhost

  vars:

    net_info:
      results:
        - 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"]

    vns: "{{ net_info.results | map(attribute='json.data.vlanNumber') }}"
    idx: "{{ range(1, vns|length +1) }}"
    nic: "{{ ['nic'] | product(idx) | map('join') }}"
    network: "{{ dict(nic|zip(vns)) }}"

  tasks:

    - debug:
        var: net_info.results | to_yaml
    - debug:
        var: vns | to_yaml
    - debug:
        var: idx
    - debug:
        var: nic
    - debug:
        var: network | to_yaml
    - debug:
        var: network | to_nice_json
© www.soinside.com 2019 - 2024. All rights reserved.