Search code examples
ansiblejinja2

Sum and combine keys from dictionary in Ansible


I have an Ansible fact like (it might have many hypervisors):

"combined_data": {
    "hypervisor-01": [
        {
            "disk": 150,
            "id": "okd-service-01"
        },
        {
            "disk": 25,
            "id": "okd-master-02"
        },
        {
            "disk": 25,
            "id": "okd-master-01"
        }
    ],
    "hypervisor-02": [
        {
            "disk": 20,
            "id": "okd-bootstrap-01"
        },
        {
            "disk": 30,
            "id": "okd-worker-01"
        },
        {
            "disk": 25,
            "id": "okd-master-03"
        }
    ]
}

And I need to create another fact with the data summarized as:

"result": [
    "hypervisor-01": 200,
    "hypervisor-02": 75
]

I tried with map and combine but didn't get anything working so far. Any idea?


Solution

  • A dictionary might be more convenient. For example,

      cd_keys: "{{ combined_data.keys()|list }}"
      cd_vals: "{{ combined_data.values()|map('sum', attribute='disk')|list }}"
      result: "{{ dict(cd_keys|zip(cd_vals)) }}"
    

    gives

      result:
        hypervisor-01: 200
        hypervisor-02: 75
    

    Optionally, you can use json_query. The below declaration gives the same result

      cd_query2: '[].[key, sum(value[].disk)]'
      result: "{{ dict(combined_data|dict2items|json_query(cd_query2)) }}"
    

    Use community.general.dict if you want to get a list. For example,

      cd_query3: '[].[[key, sum(value[].disk)]]'                                                
      result: "{{ combined_data|dict2items|json_query(cd_query3)|                              
                  map('community.general.dict') }}"
    

    gives

      result:
      - hypervisor-01: 200
      - hypervisor-02: 75
    

    Example of a complete playbook for testing

    - hosts: all
    
      vars:
    
        combined_data:
          hypervisor-01:
            - {disk: 150, id: okd-service-01}
            - {disk: 25, id: okd-master-02}
            - {disk: 25, id: okd-master-01}
          hypervisor-02:
            - {disk: 20, id: okd-bootstrap-01}
            - {disk: 30, id: okd-worker-01}
            - {disk: 25, id: okd-master-03}
    
        cd_keys: "{{ combined_data.keys()|list }}"
        cd_vals: "{{ combined_data.values()|map('sum', attribute='disk')|list }}"
        result1: "{{ dict(cd_keys|zip(cd_vals)) }}"
    
        cd_query2: '[].[key, sum(value[].disk)]'
        result2: "{{ dict(combined_data|dict2items|json_query(cd_query2)) }}"
    
        cd_query3: '[].[[key, sum(value[].disk)]]'
        result3: "{{ combined_data|dict2items|json_query(cd_query3)|
                     map('community.general.dict') }}"
    
      tasks:
    
         - debug:
             var: result1
         - debug:
             var: result2
         - debug:
             var: result3