ansiblejson-query

How to filter and rename elements in a list of hasmaps with `json_query`


I am trying to filter and rename some elements from a list of hashmaps using json_query

I have the following sample data in my ansible facts:

"ansible_mounts": [
    {
        "block_used": 136260,
        "uuid": "fa28207c-c4cf-4afd-a2e8-7090c3e4263e",
        "size_total": 2136997888,
        "block_total": 521728,
        "mount": "/disk1",
        "block_available": 385468,
        "size_available": 1578876928,
        "fstype": "xfs",
        "inode_total": 1048576,
        "inode_available": 1048572,
        "device": "/dev/sdb1",
        "inode_used": 4,
        "block_size": 4096,
        "options": "rw,seclabel,relatime,attr2,inode64,noquota"
    },
    {
        "block_used": 443460,
        "uuid": "f2a3d15f-f63a-4b07-bfe6-aa1fa3366c58",
        "size_total": 3210739712,
        "block_total": 783872,
        "mount": "/mnt/disk2",
        "block_available": 340412,
        "size_available": 1394327552,
        "fstype": "xfs",
        "inode_total": 1572864,
        "inode_available": 1572860,
        "device": "/dev/sdb2",
        "inode_used": 4,
        "block_size": 4096,
        "options": "rw,seclabel,relatime,attr2,inode64,noquota"
    },
    {
        "block_used": 482382,
        "uuid": "17764e52-0259-4918-b8c6-d4b99041db75",
        "size_total": 10725883904,
        "block_total": 2618624,
        "mount": "/",
        "block_available": 2136242,
        "size_available": 8750047232,
        "fstype": "xfs",
        "inode_total": 5242368,
        "inode_available": 5184047,
        "device": "/dev/sda1",
        "inode_used": 58321,
        "block_size": 4096,
        "options": "rw,seclabel,relatime,attr2,inode64,noquota"
    }
]

Currently I am using the following query:

- set_fact:
    mountlist: "{{ ansible_mounts | json_query('{device: [*].device, name: [*].mount, size: [*].size_available}') }}"

- debug:
    msg: "{{ mountlist }}"

And I am getting the following result:

"msg": {
  "device": [
    "/dev/sdb1", 
    "/dev/sdb2", 
    "/dev/sda1"
  ], 
  "name": [
    "/disk1", 
    "/mnt/disk2", 
    "/"
  ], 
  "size": [
    1578876928, 
    1394327552, 
    8736772096
  ]
}

However, what I expect is:

"msg": [
   {
      "name": "/disk1",
      "device": "/dev/sdb1"
      "size": 1578876928
   },
   {
      "name": "/mnt/disk2",
      "device": "/dev/sdb2"
      "size": 1394327552
   },
   {
      "name": "/",
      "device": "/dev/sda1"
      "size": 8736772096
   }
]

I cannot figure out what is wrong with my query and how to change it to obtain the correct result.


Solution

  • json_query uses the jmespath library. You should review the tutorial, examples and specification

    In your specific case, the result you get is strictly coherent with the filter you wrote. The below task is an example of how to modify it to get the desired result:

    - name: Filter + Rename elements from my source list
      debug:
        msg: "{{ ansible_mounts | json_query('[].{device: device, name: mount, size: size_available}') }}"
    

    Which gives using your sample data:

    TASK [Filter + Rename elements from my source list] ***********************************************************************************************************************************************************************
    ok: [localhost] => {
        "msg": [
            {
                "device": "/dev/sdb1",
                "name": "/disk1",
                "size": 1578876928
            },
            {
                "device": "/dev/sdb2",
                "name": "/mnt/disk2",
                "size": 1394327552
            },
            {
                "device": "/dev/sda1",
                "name": "/",
                "size": 8750047232
            }
        ]
    }