---
- name: Replace dict in list example
  hosts: localhost
  gather_facts: false
  vars:
    vpc:
      provider:
        - net_type: 'db'
          net_ipv4_subnet: '10.0.0.0/16'
          net_ipv6_subnet: 'FD00::/64'
          net_id: 0
          nic_ids:
            - 1111111111
            - 2222222222
        - net_type: 'dns'
          net_ipv4_subnet: '10.1.0.0/16'
          net_ipv6_subnet: 'FD01::/64'
          net_id: 1
          nic_ids:
            - 3333333333
            - 4444444444
        - net_type: 'ns'
          net_ipv4_subnet: '10.2.0.0/16'
          net_ipv6_subnet: 'FD02::/64'
          net_id: 2
          nic_ids:
            - 5555555555
            - 6666666666
    fix:
      net_type: 'dns'
      net_ipv4_subnet: '10.3.0.0/16'
      net_ipv6_subnet: 'FD03::/64'
      net_id: 3
      nic_ids: []
  tasks:
    - name: Do this if the order doesn't matter
      # N.B. This assumes there is 1 provider to replace.
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop:
        - "{{ [vpc.provider | selectattr('net_type', 'ne', fix.net_type)] | 
sum(start=[fix]) }}"

    - name: Do this if the order matters
      # N.B. This will replace _all_ "dns" providers with 'fix'.
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop:
        - |
          {% set providers = [] %}
          {% for p in vpc.provider %}
          {%   set _ = providers.append(p if p.net_type != fix.net_type else 
fix) %}
          {% endfor %}{{ providers }}


On 8/18/23 9:40 AM, jean-christophe manciot wrote:
The source nested dictionary is for instance the following:
                vpc:
                        provider:
                                - net_type: 'db'
                                  net_ipv4_subnet: '10.0.0.0/16'
                                  net_ipv6_subnet: 'FD00::/64'
                                  net_id: 0
                                  nic_ids:
                                        - 1111111111
                                        - 2222222222
                                - net_type: 'dns'
                                  net_ipv4_subnet: '10.1.0.0/16'
                                  net_ipv6_subnet: 'FD01::/64'
                                  net_id: 1
                                  nic_ids:
                                        - 3333333333
                                        - 4444444444
                                - net_type: 'ns'
                                  net_ipv4_subnet: '10.2.0.0/16'
                                  net_ipv6_subnet: 'FD02::/64'
                                  net_id: 2
                                  nic_ids:
                                        - 5555555555
                                        - 6666666666

We need to replace only the whole entry indexed by "net_type: 'dns'" with:
                                - net_type: 'dns'
                                  net_ipv4_subnet: '10.3.0.0/16'
                                  net_ipv6_subnet: 'FD03::/64'
                                  net_id: 3
                                  nic_ids: []

so the result would look like:
                vpc:
                        provider:
                                - net_type: 'db'
net_ipv4_subnet: '10.0.0.0/16'
net_ipv6_subnet: 'FD00::/64'
                                  net_id: 0
                                  nic_ids:
                                        - 1111111111
                                        - 2222222222
                                - net_type: 'dns'
                                  net_ipv4_subnet: '10.3.0.0/16'
                                  net_ipv6_subnet: 'FD03::/64'
                                  net_id: 3
                                  nic_ids: []
                                - net_type: 'ns'
net_ipv4_subnet: '10.2.0.0/16'
net_ipv6_subnet: 'FD02::/64'
                                  net_id: 2
                                  nic_ids:
                                        - 5555555555
                                        - 6666666666

I've tried the following task using the *combine* filter:
        - name: Combining 2 <vpc> dictionaries with combine/list_merge='replace'
          vars:
                vpc:
                        provider:
                                - net_type: 'db'
                                  net_ipv4_subnet: '10.0.0.0/16'
                                  net_ipv6_subnet: 'FD00::/64'
                                  net_id: 0
                                  nic_ids:
                                        - 1111111111
                                        - 2222222222
                                - net_type: 'dns'
                                  net_ipv4_subnet: '10.1.0.0/16'
                                  net_ipv6_subnet: 'FD01::/64'
                                  net_id: 1
                                  nic_ids:
                                        - 3333333333
                                        - 4444444444
                                - net_type: 'ns'
                                  net_ipv4_subnet: '10.2.0.0/16'
                                  net_ipv6_subnet: 'FD02::/64'
                                  net_id: 2
                                  nic_ids:
                                        - 5555555555
                                        - 6666666666
                net_id: 3
                net_ipv4_subnet: '10.3.0.0/16'
                net_ipv6_subnet: 'FD03::/64'
                new_vpc: "{{ vpc | combine({'provider': [{'net_type': 'dns', 'net_id': net_id, 'net_ipv4_subnet': net_ipv4_subnet, 'net_ipv6_subnet': net_ipv6_subnet, 'nic_ids': []}]}, recursive=True, list_merge='replace') }}"
          debug:
                msg: "{{ new_vpc }}"

which unfortunately removes the other 2 entries:
ok: [localhost] =>
  msg:
    provider:
    - net_id: 3
      net_ipv4_subnet: 10.3.0.0/16
      net_ipv6_subnet: FD03::/64
      net_type: dns
      nic_ids: []

Same result with community.general.*lists_mergeby* filter:
        - name: Combining 2 <vpc> dictionaries with lists_mergeby/list_merge='replace'
          vars:
                vpc:
                        provider:
                                - net_type: 'db'
                                  net_ipv4_subnet: '10.0.0.0/16'
                                  net_ipv6_subnet: 'FD00::/64'
                                  net_id: 0
                                  nic_ids:
                                        - 1111111111
                                        - 2222222222
                                - net_type: 'dns'
                                  net_ipv4_subnet: '10.1.0.0/16'
                                  net_ipv6_subnet: 'FD01::/64'
                                  net_id: 1
                                  nic_ids:
                                        - 3333333333
                                        - 4444444444
                                - net_type: 'ns'
                                  net_ipv4_subnet: '10.2.0.0/16'
                                  net_ipv6_subnet: 'FD02::/64'
                                  net_id: 2
                                  nic_ids:
                                        - 5555555555
                                        - 6666666666
                seed_vpc:
                        provider:
                                - net_type: 'dns'
                                  net_ipv4_subnet: '10.3.0.0/16'
                                  net_ipv6_subnet: 'FD03::/64'
                                  net_id: 3
                                  nic_ids: []
                new_vpc: "{{ [vpc.provider, seed_vpc.provider] | community.general.lists_mergeby('net_type=dns', recursive=True, list_merge='replace') }}"
          debug:
                msg: "{{ new_vpc }}"

leads to:
ok: [localhost] =>
  msg:
    provider:
    - net_id: 3
      net_ipv4_subnet: 10.3.0.0/16
      net_ipv6_subnet: FD03::/64
      net_type: dns
      nic_ids: []

Am I missing something or is it impossible to perform with the currently available ansible filters?
--
You received this message because you are subscribed to the Google Groups "Ansible Project" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/f77880a9-c219-41ec-ad7d-d5381594489an%40googlegroups.com <https://groups.google.com/d/msgid/ansible-project/f77880a9-c219-41ec-ad7d-d5381594489an%40googlegroups.com?utm_medium=email&utm_source=footer>.

--
Todd

--
You received this message because you are subscribed to the Google Groups "Ansible 
Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ansible-project/b259c2a4-9dfa-ee2f-a840-7ee769f7afc5%40gmail.com.

Reply via email to