当每个匹配的键/值对匹配时,合并Ansible中的列表

时间:2018-06-03 00:04:08

标签: ansible

我有两个字典列表(port_info和int_trunk),当'port'键的值匹配时我试图合并但是并不是每个端口都会在'int_trunk'中表示。在这种情况下,只需将“trunked_vlans”值留空即可。我使用'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。

1 个答案:

答案 0 :(得分:0)

不确定是否有"一行"过滤可以做到这一点。这是我想出的东西,首先解释流程:

  1. 我们使用2个set_fact步骤填充2个列表中常见的所有端口的列表。
  2. 我们一起解析2个列表,当port_info中的元素的port属性等于int_trunk中的元素时,我们合并/合并2个词典。
  3. 完成常用条目的合并。现在我们需要再次解析port_info列表,并在port_info_final列表中添加int_trunk中没有匹配元素的所有元素。
  4. 我们在port_info_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   
    

    希望有所帮助