user3655103
user3655103

Reputation: 67

Ansible Convert list of dicts to list of lists concatinating values into one string

I'm trying to convert list of dicts with keys ip and port into list of list where values will be concatenated values ip:port. I have list of dicts in Ansible:

 "updated_pool_members_list": [
        [
            {
                "ip": "10.99.99.99",
                "port": 80
            },
            {
                "ip": "10.99.99.100",
                "port": 80
            },
            {
                "ip": "10.99.99.101",
                "port": 80
            }
        ],
        [
            {
                "ip": "10.98.98.99",
                "port": 80
            },
            {
                "ip": "10.98.98.100",
                "port": 80
            }
        ]
    ]

What I want to get this:

    [
     "10.99.99.99:80",
     "10.99.99.100:80",
     "10.99.99.101:80"

    ],
    [  
      "10.98.98.99:80",
      "10.98.98.100:80"
    ]

Tried to make two separate lists of IPs and Ports:

 - name: Get ip and port into lists
   ansible.builtin.set_fact:
     pool_ip_list: "{{ pool_ip_list + [pool_item | map(attribute='ip') ] }}"
     pool_port_list: "{{ pool_port_list + [pool_item | map(attribute='port') ] }}"
   loop: "{{ updated_pool_members_list }}"
   loop_control:
     loop_var: pool_item

Got

"pool_ip_list": [
        [
            "10.99.99.99",
            "10.99.99.100",
            "10.99.99.101"
        ],
        [
            "10.98.98.99",
            "10.98.98.100"
        ]
    ]

and

"pool_port_list": [
    [
        80,
        80,
        80
    ],
    [
        80,
        80
    ]
]

But stuck on concatenating items in list of lists. Maybe there is a better way how to achieve needed result ?

Upvotes: 2

Views: 420

Answers (2)

Zeitounator
Zeitounator

Reputation: 44635

The easiest way IMO is to use jmespath through the json_query filter. Please note from the above doc that this solution requires to have the relevant collections installed as well as pip install jsmespath on the controller

The following playbook:

---
- hosts: localhost
  gather_facts: false

  vars:
    updated_pool_members_list: [[{"ip":"10.99.99.99","port":80},{"ip":"10.99.99.100","port":80},{"ip":"10.99.99.101","port":80}],[{"ip":"10.98.98.99","port":80},{"ip":"10.98.98.100","port":80}]]

    my_pool_query: "[*][*].join(':', [ip, to_string(port)])"

    my_pool_list: "{{ updated_pool_members_list | json_query(my_pool_query) }}"

  tasks:
    - debug:
        var: my_pool_list

Gives:

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "my_pool_list": [
        [
            "10.99.99.99:80",
            "10.99.99.100:80",
            "10.99.99.101:80"
        ],
        [
            "10.98.98.99:80",
            "10.98.98.100:80"
        ]
    ]
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Upvotes: 1

Frenchy
Frenchy

Reputation: 17017

Another solution using jinja2:

- name: "tips1"
  hosts: localhost
  vars:
    updated_pool_members_list: [[{"ip":"10.99.99.99","port":80},{"ip":"10.99.99.100","port":80},{"ip":"10.99.99.101","port":80}],[{"ip":"10.98.98.99","port":80},{"ip":"10.98.98.100","port":80}]]

  tasks:  
    - name: solution set_fact
      set_fact:
        result: "{{ result | d([]) + [iplist] }}"
      loop: "{{ updated_pool_members_list }}"
      vars:
        iplist: >-
            {%- set ips = [] -%} 
            {%- for d in item -%}
            {{ ips.append(d.ip ~ ':' ~ d.port) }}
            {%- endfor -%}
            {{ ips }}  

    - name: debug users      
      debug:
        var: result

result:

ok: [localhost] => {
    "result": [
        [
            "10.99.99.99:80",
            "10.99.99.100:80",
            "10.99.99.101:80"
        ],
        [
            "10.98.98.99:80",
            "10.98.98.100:80"
        ]
    ]
}

Upvotes: 1

Related Questions