Search code examples
ansiblejqjmespathjson-query

Getting the values of keys of Ansible JSON output


I have the following JSON data

{
    "docker_compose_init_result": {
        "changed": true,
        "failed": false,
        "services": {
            "grafana": {
                "docker-compose_grafana_1": {
                    "cmd": [],
                    "image": "grafana/grafana:8.5.14",
                    "labels": {
                        "com.docker.compose.config-hash": "4d0b5dd6e697a8fe5bf5074192770285e54da43ad32cc34ba9c56505cb709431",
                        "com.docker.compose.container-number": "1",
                        "com.docker.compose.oneoff": "False",
                        "com.docker.compose.project": "docker-compose",
                        "com.docker.compose.project.config_files": "/appl/docker-compose/docker-compose-init.yml",
                        "com.docker.compose.project.working_dir": "/appl/docker-compose",
                        "com.docker.compose.service": "grafana",
                        "com.docker.compose.version": "1.29.2"
                    },
                    "networks": {
                        "docker-compose_homeserver-net": {
                            "IPAddress": "172.20.0.2",
                            "IPPrefixLen": 16,
                            "aliases": [
                                "3d19f54271b2",
                                "grafana"
                            ],
                            "globalIPv6": "",
                            "globalIPv6PrefixLen": 0,
                            "links": null,
                            "macAddress": "02:42:ac:14:00:02"
                        }
                    },
                    "state": {
                        "running": true,
                        "status": "running"
                    }
                }
            },
            "node-red": {
                "docker-compose_node-red_1": {
                    "cmd": [],
                    "image": "nodered/node-red:2.2.2",
                    "labels": {
                        "authors": "Dave Conway-Jones, Nick O'Leary, James Thomas, Raymond Mouthaan",
                        "com.docker.compose.config-hash": "5610863d4b28b11645acb5651e7bab174125743dc86a265969788cc8ac782efe",
                        "com.docker.compose.container-number": "1",
                        "com.docker.compose.oneoff": "False",
                        "com.docker.compose.project": "docker-compose",
                        "com.docker.compose.project.config_files": "/appl/docker-compose/docker-compose-init.yml",
                        "com.docker.compose.project.working_dir": "/appl/docker-compose",
                        "com.docker.compose.service": "node-red",
                        "com.docker.compose.version": "1.29.2",
                        "org.label-schema.arch": "",
                        "org.label-schema.build-date": "2022-02-18T21:01:04Z",
                        "org.label-schema.description": "Low-code programming for event-driven applications.",
                        "org.label-schema.docker.dockerfile": ".docker/Dockerfile.alpine",
                        "org.label-schema.license": "Apache-2.0",
                        "org.label-schema.name": "Node-RED",
                        "org.label-schema.url": "https://nodered.org",
                        "org.label-schema.vcs-ref": "",
                        "org.label-schema.vcs-type": "Git",
                        "org.label-schema.vcs-url": "https://github.com/node-red/node-red-docker",
                        "org.label-schema.version": "2.2.2"
                    },
                    "networks": {
                        "docker-compose_homeserver-net": {
                            "IPAddress": "172.20.0.4",
                            "IPPrefixLen": 16,
                            "aliases": [
                                "fc56e973c98d",
                                "node-red"
                            ],
                            "globalIPv6": "",
                            "globalIPv6PrefixLen": 0,
                            "links": null,
                            "macAddress": "02:42:ac:14:00:04"
                        }
                    },
                    "state": {
                        "running": true,
                        "status": "running"
                    }
                }
            },
            "organizr": {
                "docker-compose_organizr_1": {
                    "cmd": [],
                    "image": "organizr/organizr:linux-amd64",
                    "labels": {
                        "base.maintainer": "christronyxyocum,Roxedus",
                        "base.s6.arch": "amd64",
                        "base.s6.rel": "2.2.0.3",
                        "com.docker.compose.config-hash": "430b338b0c0892a25522e1b641a9e3a08eedd255309b1cd275b22a3362dcac58",
                        "com.docker.compose.container-number": "1",
                        "com.docker.compose.oneoff": "False",
                        "com.docker.compose.project": "docker-compose",
                        "com.docker.compose.project.config_files": "/appl/docker-compose/docker-compose-init.yml",
                        "com.docker.compose.project.working_dir": "/appl/docker-compose",
                        "com.docker.compose.service": "organizr",
                        "com.docker.compose.version": "1.29.2",
                        "maintainer": "christronyxyocum,Roxedus",
                        "org.label-schema.description": "Baseimage for Organizr",
                        "org.label-schema.name": "organizr/base",
                        "org.label-schema.schema-version": "1.0",
                        "org.label-schema.url": "https://organizr.app/",
                        "org.label-schema.vcs-url": "https://github.com/organizr/docker-base",
                        "org.opencontainers.image.created": "2022-05-08_15",
                        "org.opencontainers.image.source": "https://github.com/Organizr/docker-organizr/tree/master",
                        "org.opencontainers.image.title": "organizr/base",
                        "org.opencontainers.image.url": "https://github.com/Organizr/docker-organizr/blob/master/README.md"
                    },
                    "networks": {
                        "docker-compose_homeserver-net": {
                            "IPAddress": "172.20.0.3",
                            "IPPrefixLen": 16,
                            "aliases": [
                                "organizr",
                                "f3f61d8938fe"
                            ],
                            "globalIPv6": "",
                            "globalIPv6PrefixLen": 0,
                            "links": null,
                            "macAddress": "02:42:ac:14:00:03"
                        }
                    },
                    "state": {
                        "running": true,
                        "status": "running"
                    }
                }
            },
            "prometheus": {
                "docker-compose_prometheus_1": {
                    "cmd": [
                        "--config.file=/etc/prometheus/prometheus.yml",
                        "--storage.tsdb.path=/prometheus",
                        "--web.console.libraries=/etc/prometheus/console_libraries",
                        "--web.console.templates=/etc/prometheus/consoles",
                        "--web.enable-lifecycle"
                    ],
                    "image": "prom/prometheus:v2.35.0",
                    "labels": {
                        "com.docker.compose.config-hash": "7d2ce7deba1a152ebcf4fe5494384018c514f6703b5e906aef6f2e8820733cb2",
                        "com.docker.compose.container-number": "1",
                        "com.docker.compose.oneoff": "False",
                        "com.docker.compose.project": "docker-compose",
                        "com.docker.compose.project.config_files": "/appl/docker-compose/docker-compose-init.yml",
                        "com.docker.compose.project.working_dir": "/appl/docker-compose",
                        "com.docker.compose.service": "prometheus",
                        "com.docker.compose.version": "1.29.2",
                        "maintainer": "The Prometheus Authors <[email protected]>"
                    },
                    "networks": {
                        "docker-compose_homeserver-net": {
                            "IPAddress": "172.20.0.5",
                            "IPPrefixLen": 16,
                            "aliases": [
                                "04f346e6694f",
                                "prometheus"
                            ],
                            "globalIPv6": "",
                            "globalIPv6PrefixLen": 0,
                            "links": null,
                            "macAddress": "02:42:ac:14:00:05"
                        }
                    },
                    "state": {
                        "running": true,
                        "status": "running"
                    }
                }
            }
        }
    }
}

And I need an output similar to

- docker-compose_grafana_1
- docker-compose_node-red_1
- docker-compose_organizr_1
- docker-compose_prometheus_1

I can do that with jq easy-peasy:

jq --raw-output '.docker_compose_init_result.services\[\] | keys | .\[\]' jsondata.json

But I am not able to do it with Ansible and especially json_query (and thus JMESPath).

I was able to get one key with

jp -f jsondata.json "keys(docker_compose_init_result.services.grafana)"
[ 
  "docker-compose_grafana_1"
]

But have no idea how to get all four. Also sometimes expressions that worked with jp did not work in Ansible with json_query, which additionally made me mad.

If anyone can give me a solution for this (wether its with json_query or not) in the best case explains how it works, I would be very glad.


Solution

  • In a pure JMESPath way, you query should be:

    docker_compose_init_result.services.*.keys(@)[]
    

    Where:

    • .* is the notation for an object project, that will make you get the values under docker_compose_init_result.services, whatever the key might be.
    • .keys(@) is the keys() function, in order to get the keys, mapped to the current node — @, which effectively means that keys() is going to be applied to every object which are children of docker_compose_init_result.services.*, (e.g.: on docker_compose_init_result.services.grafana."docker-compose_grafana_1", docker_compose_init_result.services."node-red"."docker-compose_node-red_1", and so on)
    • [] is the flatten operator, in order to reduce your array of arrays to a single level array