用 Ansible 中另一个列表中的相关匹配值替换列表中的键值

Replace the key value in a list with the relevant matching values from another list in Ansible

我正在尝试用另一个列表中的匹配值替换列表中字典中的键值(此处仅针对 Objectids 中的值)。不知何故,我只能替换第一个值但不能迭代整个列表。这里 input.json 中的相同键将具有来自 finallist.json 的多个匹配值,所有这些值都需要匹配并添加到获得最终预期输出中。

Input.json

[
    {
        "name": "DNS_One",
        "objectIds": [
            "DNS_One",
            "DNS_One-HO",
            "NTP"
        ]
    },
    {
        "name": "DNS_Two",
        "objectIds": [
            "NTP"
        ]
    }
]

finallist.json

[
    {
        "id": "123456",
        "net_name": "DNS_One"
    },
    {
        "id": "789101112",
        "net_name": "DNS_One"
    },
    {
        "id": "131415161718",
        "net_name": "DNS_One-HO"
    },
    {
        "id": "23897845",
        "net_name": "NTP"
    },
    {
        "id": "9879879546",
        "net_name": "NTP"
    }
]

剧本

- name: Id mapping
      vars: 
       objectid: >-
        {{ 
          finallist
          | selectattr('net_name', 'in', item.1)
          | map(attribute = 'id')
          | first
          | default([])
          }}
      set_fact:
        obj: >-
         {{
            obj | default([]) + 
            [item.0 | combine({'objectIds': [objectid]})]
         }}
      with_subelements:
           - "{{ input }}"
           - objectIds
      ignore_errors: yes

预期输出

[
    {
        "name": "DNS_One",
        "objectIds": [
            "123456","789101112"
            "131415161718",
            "23897845","9879879546"
        ]
    },
    {
        "name": "DNS_Two",
        "objectIds": [
            "23897845","9879879546"
        ]
    }
]

读取数据并创建变量finallistinput

    - set_fact:
        finallist: "{{ lookup('file', 'finallist.json')|from_yaml }}"
    - set_fact:
        input: "{{ lookup('file', 'input.json')|from_yaml }}"

给予

finallist:
  - id: '123456'
    net_name: DNS_One
  - id: '789101112'
    net_name: DNS_One
  - id: '131415161718'
    net_name: DNS_One-HO
  - id: '23897845'
    net_name: NTP
  - id: '9879879546'
    net_name: NTP
input:
  - name: DNS_One
    objectIds:
    - DNS_One
    - DNS_One-HO
    - NTP
  - name: DNS_Two
    objectIds:
    - NTP

finallist 中,按 net_name 对项目进行分组并将列表转换为字典

    - set_fact:
        finaldict: "{{ finaldict|d({})|
                       combine({item.0: item.1|map(attribute='id')}) }}"
      loop: "{{ finallist|groupby('net_name') }}"

给予

  finaldict:
    DNS_One:
    - '123456'
    - '789101112'
    DNS_One-HO:
    - '131415161718'
    NTP:
    - '23897845'
    - '9879879546'

迭代输入并替换ID

    - set_fact:
        new: "{{ new|d([]) + [item|combine({'objectIds': _ids})] }}"
      loop: "{{ input }}"
      vars:
        _ids: "{{ item.objectIds|map('extract', finaldict)|list }}"

给出了预期的结果

  new:
    - name: DNS_One
      objectIds:
      - ['123456', '789101112']
      - ['131415161718']
      - ['23897845', '9879879546']
    - name: DNS_Two
      objectIds:
      - ['23897845', '9879879546']

如果需要,您可以展平列表

       _ids: "{{ item.objectIds|map('extract', finaldict)|flatten }}"

给予

  new:
    - name: DNS_One
      objectIds: ['123456', '789101112', '131415161718', '23897845', '9879879546']
    - name: DNS_Two
      objectIds: ['23897845', '9879879546']