How to combine two dictionaries an ansible by some key

Viewed 252

I have two yaml dictionaries that i need to join between by key

server_groups:
  - name: grp1
    servers: server1-1,server1-2,server1-3
  - name: grp2
    servers: server2-1,server2-2,server2-3
  - name: grp3
    servers: server3-1,server3-2,server3-3

server_paths:
  - name: path1
    src: grp1
    dest: grp2
    payload: ...
  - name: path2
    src: grp3
    dest: grp1
    payload: ...

I want to enrich server_paths dictionary by adding src_servers and dest_servers by group name.

I tried to achieve it by such way:

    - set_fact:
        serverpaths: "{{ server_paths }}"
     - set_fact:
         serverpaths: "{{ serverpaths|combine({'dest_servers':server_groups| selectattr('name', 'equalto', item.dest) | map(attribute='servers') | first})}}"
       loop: "{{ server_paths }}"

Expected result is:

server_paths:
  - name: path1
    src: server1-1,server1-2,server1-3
    dest: server2-1,server2-2,server2-3
    payload: ...
  - name: path2
    src: server3-1,server3-2,server3-3
    dest: server1-1,server1-2,server1-3
    payload: ...

It works fine with joining but returns only last enriched element. So I'm stuck how to get all enriched elements?

1 Answers

Convert the list server_groups to the dictionary server_groups_dict, e.g. put the expression below to the place where the lists come from

server_groups_dict: "{{ server_groups|items2dict(key_name='name',
                                                 value_name='servers') }}"

gives

server_groups_dict:
  grp1: server1-1,server1-2,server1-3
  grp2: server2-1,server2-2,server2-3
  grp3: server3-1,server3-2,server3-3

Now you can iterate the list server_paths and create the required structure, e.g.

    - set_fact:
        serverpaths: "{{ serverpaths|d([]) + [item|combine(_dict)] }}"
      loop: "{{ server_paths }}"
      vars:
        _dict: "{{ {'src': server_groups_dict[item.src],
                    'dest': server_groups_dict[item.dest]} }}"

gives

serverpaths:
  - dest: server2-1,server2-2,server2-3
    name: path1
    src: server1-1,server1-2,server1-3
  - dest: server1-1,server1-2,server1-3
    name: path2
    src: server3-1,server3-2,server3-3

Notes

  • For simplicity, I removed the attribute payload. The code should prevent the structure, however.
Related