当每个密钥/值对匹配时,在Ansible中合并列表

当每个密钥/值对匹配时,在Ansible中合并列表,ansible,Ansible,我有两个字典列表(port_info和int_trunk),当“port”键的值匹配时,我会尝试合并它们,但是并非每个端口都会在“int_trunk”中表示。在本例中,只需将“trunked_vlan”值留空即可。我使用“with_nested”来迭代列表。我似乎无法得到我想要的输出。我尝试了combine()过滤器,并手动尝试创建变量,但没有完全实现。如何将这两个列表合并 --- - hosts: localhost connection: local gather_facts: no

我有两个字典列表(port_info和int_trunk),当“port”键的值匹配时,我会尝试合并它们,但是并非每个端口都会在“int_trunk”中表示。在本例中,只需将“trunked_vlan”值留空即可。我使用“with_nested”来迭代列表。我似乎无法得到我想要的输出。我尝试了combine()过滤器,并手动尝试创建变量,但没有完全实现。如何将这两个列表合并

---
- hosts: localhost
  connection: local
  gather_facts: no

  vars:
    trunk_ports: []
    non_trunk_ports: []
    new_port_info: []
    port_info: 
      - desc: "*** Voice Server Port ***"
        duplex: "a-full"
        port: "Gi1/0/1"
        speed: "a-1000"
        status: connected
        trunk_vlans: ""
        type: "10/100/1000BaseTX"
        vlan: 3
      - desc: "*** Voice Server Port ***"
        duplex: "a-full"
        port: "Gi1/0/2"
        speed: "a-1000"
        status: connected
        trunk_vlans: ""
        type: "10/100/1000BaseTX"
        vlan: 3
      - desc: "Some Port"
        duplex: auto
        port: "Gi1/0/3"
        speed: auto
        status: notconnect
        trunk_vlans: ""
        type: "10/100/1000BaseTX"
        vlan: 23
    int_trunk:
      - port: "Gi1/0/1"
        vlans: "1-50"
      - port: "Gi1/0/2"
        vlans: "50-60"
其输出应为:

port_info: 
  - desc: "*** Voice Server Port ***"
    duplex: "a-full"
    port: "Gi1/0/1"
    speed: "a-1000"
    status: connected
    trunk_vlans: "1-50"
    type: "10/100/1000BaseTX"
    vlan: 3
  - desc: "*** Voice Server Port ***"
    duplex: "a-full"
    port: "Gi1/0/2"
    speed: "a-1000"
    status: connected
    trunk_vlans: "50-60"
    type: "10/100/1000BaseTX"
    vlan: 3
  - desc: "Some Port"
    duplex: auto
    port: "Gi1/0/3"
    speed: auto
    status: notconnect
    trunk_vlans: ""
    type: "10/100/1000BaseTX"
    vlan: 23
这是我尝试过的事情之一:

---
- hosts: localhost
  connection: local
  gather_facts: no

  vars:
    trunk_ports: []
    non_trunk_ports: []
    new_port_info: []
    port_info: 
      - desc: "*** Voice Server Port ***"
        duplex: "a-full"
        port: "Gi1/0/1"
        speed: "a-1000"
        status: connected
        trunk_vlans: ""
        type: "10/100/1000BaseTX"
        vlan: 3
      - desc: "*** Voice Server Port ***"
        duplex: "a-full"
        port: "Gi1/0/2"
        speed: "a-1000"
        status: connected
        trunk_vlans: ""
        type: "10/100/1000BaseTX"
        vlan: 3
      - desc: " "
        duplex: auto
        port: "Gi1/0/3"
        speed: auto
        status: notconnect
        trunk_vlans: ""
        type: "10/100/1000BaseTX"
        vlan: 23
    int_trunk:
      - port: "Gi1/0/1"
        vlans: "1-50"
      - port: "Gi1/0/2"
        vlans: "50-60"

  tasks:
    - name: Merge trunk ports
      set_fact:
        trunk_ports: "{{ trunk_ports + [ { 'desc': item.0.desc, 'duplex': item.0.duplex, 'port': item.0.port, 'speed': item.0.speed, 'status
': item.0.status, 'trunk_vlans': item.1.vlans, 'type': item.0.type, 'vlan': item.0.vlan } ] }}"
      with_nested:
        - "{{ port_info }}"
        - "{{ int_trunk }}"
      when: item.0.port == item.1.port 

    - name: Merge non-trunk ports
      set_fact:
        non_trunk_ports: "{{ non_trunk_ports + [ { 'desc': item.0.desc, 'duplex': item.0.duplex, 'port': item.0.port, 'speed': item.0.speed,
 'status': item.0.status, 'trunk_vlans': item.0.trunk_vlans, 'type': item.0.type, 'vlan': item.0.vlan } ] }}"
      with_nested:
        - "{{ port_info }}"
        - "{{ int_trunk }}"
      when: item.0.port != item.1.port

    - name: Merge all ports
      set_fact:
        new_port_info: "{{ new_port_info + [item.0|combine(item.1)] }}"
      with_nested:
        - "{{ port_info }}"
        - "{{ trunk_ports }}"
      when: item.0.port == item.1.port

    - name: Echo
      debug: var=trunk_ports


    - name: Echo
      debug: var=non_trunk_ports

    - name: Echo
      debug: var=new_port_info
我最终使用的是端口Gi1/0/1和Gi1/0/2,但不是Gi1/0/3。

不确定是否有“一行”过滤可以做到这一点。以下是我的想法,首先是对流程的解释:

  • 我们使用2个
    set\u fact
    步骤填充2个列表中常见的所有端口的列表
  • 我们一起解析这两个列表,当
    port\u info
    中的元素具有与
    int\u trunk
    中的元素相等的port属性时,我们合并这两个字典
  • 完成了公共条目的合并。现在我们需要再次解析
    port\u info
    列表,并将
    port\u info\u final
    列表添加到
    int\u trunk
    中没有匹配元素的所有元素
  • 我们在
    port\u info\u final
    列表中获得了合并元素和唯一元素

    剧本:

    ---
    - hosts: localhost
      connection: local
      gather_facts: false
      vars:
        trunk_ports: []
        non_trunk_ports: []
        new_port_info: []
        port_info: 
          - desc: "*** Voice Server Port ***"
            duplex: "a-full"
            port: "Gi1/0/1"
            speed: "a-1000"
            status: connected
            trunk_vlans: ""
            type: "10/100/1000BaseTX"
            vlan: 3
          - desc: "*** Voice Server Port ***"
            duplex: "a-full"
            port: "Gi1/0/2"
            speed: "a-1000"
            status: connected
            trunk_vlans: ""
            type: "10/100/1000BaseTX"
            vlan: 3
          - desc: "Some Port"
            duplex: auto
            port: "Gi1/0/3"
            speed: auto
            status: notconnect
            trunk_vlans: ""
            type: "10/100/1000BaseTX"
            vlan: 23
        int_trunk:
          - port: "Gi1/0/1"
            vlans: "1-50"
          - port: "Gi1/0/2"
            vlans: "50-60"
        port_info_final: []
    
      tasks:
    
      - name: get the lists of ports per list
        set_fact:
          portlist_1: "{{ port_info | map(attribute='port') | list }}"
          portlist_2: "{{ int_trunk | map(attribute='port') | list }}"
    
      - name: get the ports that exist in port_info but not in int_trunk
        set_fact:
          ports_not_in_int_trunk: "{{ portlist_1 | difference(portlist_2) }}"
    
      - name: merge the dictionaries when the port is matched
        set_fact:
          port_info_final: "{{ port_info_final + [item[0] | combine(item[1])] }}"
        when: item[0].port == item[1].port
        loop: "{{ query('nested', int_trunk, port_info) }}"
    
      - name: add all the port_info elements that dont have entry in int_trunk
        set_fact:
          port_info_final: "{{ port_info_final + [item] }}"
        when: item.port in ports_not_in_int_trunk
        loop: "{{ port_info }}"
    
      - name: print results
        debug:
          msg: "{{ port_info_final }}"
    
    结果:

    TASK [print results] ************************************************************************************************************************************************************************************************
    ok: [localhost] => {
        "msg": [
            {
                "desc": "*** Voice Server Port ***", 
                "duplex": "a-full", 
                "port": "Gi1/0/1", 
                "speed": "a-1000", 
                "status": "connected", 
                "trunk_vlans": "", 
                "type": "10/100/1000BaseTX", 
                "vlan": 3, 
                "vlans": "1-50"
            }, 
            {
                "desc": "*** Voice Server Port ***", 
                "duplex": "a-full", 
                "port": "Gi1/0/2", 
                "speed": "a-1000", 
                "status": "connected", 
                "trunk_vlans": "", 
                "type": "10/100/1000BaseTX", 
                "vlan": 3, 
                "vlans": "50-60"
            }, 
            {
                "desc": "Some Port", 
                "duplex": "auto", 
                "port": "Gi1/0/3", 
                "speed": "auto", 
                "status": "notconnect", 
                "trunk_vlans": "", 
                "type": "10/100/1000BaseTX", 
                "vlan": 23
            }
        ]
    }
    
    PLAY RECAP **********************************************************************************************************************************************************************************************************
    localhost                  : ok=5    changed=0    unreachable=0    failed=0   
    

    希望它能有所帮助

    尽管由于我自己在提供的输入中的错误,我不得不做一些轻微的修改。在port_info中,我们有“集群VLAN”,它一开始没有任何值。在int_中继中,我们有“VLAN”。我希望“VLAN”与“集群VLAN”相结合,而不是创建新的k/v对。因此,我所做的是将“VLAN”重命名为“集群VLAN”,然后反转联合循环中的列表,以便int_集群键覆盖端口信息键。这似乎是我想要的。谢谢