Retrieve facts from Ansible Setup module using JQ

589 views
Skip to first unread message

dmc...@gmail.com

unread,
Dec 31, 2021, 8:24:57 AM12/31/21
to Ansible Project
Is anyone good with ./JQ?

I'm trying to pull out data from the setup output from Ansible. I can do most of what I need to but I'm stuck on something that is probably quite simple.

I'm trying to generate a list of hosts including disks + sizes and partitions + sizes AND mount points.

I can get the first two quite easily like this (this should work on any server running on localhost) - I need the sed to format the json correctly:

$ ansible localhost -m setup | sed '1 s/^.*$/{/' | jq '.ansible_facts | {hostname: .ansible_hostname, Disks: .ansible_devices| with_entries(.value |= .size), Partitions: .ansible_devices[].partitions | with_entries(.value |= .size) }'

{
"hostname": "ip-172-31-16-55",
"Disks": {
  "xvda": "10.00 GB"
  },
"Partitions": {
  "xvda1": "1.00 GB",
  "xvda2": "9.00 GB"
  }
}


(formatting is a little off with copy and paste)

Now if I want to collect mount points I can do it like this:

$ ansible localhost -m setup | sed '1 s/^.*$/{/' | jq -r '.ansible_facts.ansible_mounts[].mount'
/
/boot


But because the mount information is an array (I think?) i need to map it to get it to work? I'd like to get the results in the same list as the one above but when i add it in it works, but it gives me a new list for every mount point instead of just one list!

This is what I get:

$ ansible localhost -m setup | sed '1 s/^.*$/{/' | jq '.ansible_facts | {hostname: .ansible_hostname, Disks: .ansible_devices|  with_entries(.value |= .size), Partitions: .ansible_devices[].partitions |  with_entries(.value |= .size), Mounts: .ansible_mounts[].mount }'
{
  "hostname": "ip-172-31-16-55",
  "Disks": {
    "xvda": "10.00 GB"
  },
  "Partitions": {
    "xvda1": "1.00 GB",
    "xvda2": "9.00 GB"
  },
  "Mounts": "/"
}
{
  "hostname": "ip-172-31-16-55",
  "Disks": {
    "xvda": "10.00 GB"
  },
  "Partitions": {
    "xvda1": "1.00 GB",
    "xvda2": "9.00 GB"
  },
  "Mounts": "/boot"
}

BUT, this is what I'm trying to get:

{
  "hostname": "ip-172-31-16-55",
  "Disks": {
    "xvda": "10.00 GB"
  },
  "Partitions": {
    "xvda1": "1.00 GB",
    "xvda2": "9.00 GB"
  },
  "Mounts": "/"
  "Mounts": "/boot"
  }
}

or even a "," separated list on one line?

  },
  "Mounts": "/", "/boot"
  }

I think I can't see the wood for the trees now and a little nudge would be greatly appreciated.

Thanks


Message has been deleted

Todd Lewis

unread,
Dec 31, 2021, 11:11:16 AM12/31/21
to Ansible Project
Weird. The shell script version got split into multiple text boxes by the groups back-end. Anyway, the jq query should be pretty clear anyway.

On Friday, December 31, 2021 at 10:58:55 AM UTC-5 Todd Lewis wrote:

It feels like there should be a cleaner way to get the non-empty Partitions, but I’m no jq guru. This was a fun one.

I put this into a shell script just because it’s easier to make tweaks while testing. It should work as a one-liner if that suites you better.

#!/bin/bash


ansible localhost -m setup | \
    sed '1 s/^.*$/{/' | \
    jq 
'.ansible_facts |
          {hostname: .ansible_hostname,
              Disks: .ansible_devices |  with_entries(.value |= .size),
         Partitions: [.ansible_devices[].partitions | with_entries(.value |= .size)] | .[] | select(length>0),
             Mounts: [.ansible_mounts[].mount] }'

On my system, this produces the following output:

{
  "hostname": "tango",
  "Disks": {
    "dm-0": "475.34 GB",
    "nvme0n1": "476.94 GB",
    "zram0": "8.00 GB"
  },
  "Partitions": {
    "nvme0n1p1": "600.00 MB",
    "nvme0n1p2": "1.00 GB",
    "nvme0n1p3": "475.35 GB"
  },
  "Mounts": [
    "/",
    "/home",
    "/boot",
    "/boot/efi"
  ]
}

On 12/31/21:

dmc...@gmail.com

unread,
Jan 3, 2022, 11:07:11 AM1/3/22
to Ansible Project

Thanks for that, It was exactly what I was looking for. I was so close...

This is what I get:

$ ansible localhost -m setup | sed '1 s/^.*$/{/' | jq '.ansible_facts | {hostname: .ansible_hostname, Disks: .ansible_devices |  with_entries(.value |= .size), Partitions: [.ansible_devices[].partitions | with_entries(.value |= .size)] | .[] | select(length>0), Mounts: [.ansible_mounts[].mount] }'

{
  "hostname": "ip-172-31-16-55",
  "Disks": {
    "xvda": "10.00 GB"
  },
  "Partitions": {
    "xvda1": "1.00 GB",
    "xvda2": "9.00 GB"
  },
  "Mounts": [
    "/",
    "/boot"
  ]
}
Reply all
Reply to author
Forward
0 new messages