Yq: retrieve object keys names
Asked Answered
A

2

12

I have a YAML file (docker-compose file in my case) that looks like this:

networks:
    foo:
      some_opts: "covfefe"
    bar:
      some_opts: "such wow"
services:
  apache:
    image: 'apache:1.0.0'
    restart: always
  mysql:
    image: 'mysql:1.0.0'
    restart: always
  php:
    image: 'php'
    restart: always

I would like to extract the services name thanks to yq, an equivalent of jq but for YAML, to have this output:

"apache"
"mysql"
"php"

Currently I can achieve it like this:

$ cat docker-compose.yml | yq '.services' | yq 'keys[]'
"apache"
"mysql"
"php"

Even if it works, the double piped yq seems weird to me. I think I'm doing it wrong.

Question: Is there any way to achieve it with a single yq command ?

I tried this without success, taking inspiration from this question:

$ cat docker-compose.yml | yq '.services.keys[]'
jq: error: Cannot iterate over null
Attenuation answered 21/3, 2019 at 12:6 Comment(0)
O
24

keys is a built-in function in jq when given an object, returns its keys in an array. So it is not actually apart of your yaml (not a property) which means you cannot do services.keys.

To get the keys you can do the following when using Python yq:

We will get the object of services in the first part then we pass it to keys which will return a list of keys based on a given object

cat docker-compose.yml | yq '.services | keys'

Or like this (without cat and pipe):

yq '.services | keys' docker-compose.yml

The output will be:

[
  "apache",
  "mysql",
  "php"
]

To get rid of the brackets:

yq '.services | keys[]' docker-compose.yml

The output:

"apache"
"mysql"
"php"

For more about details you can check Builtin operators and functions in jq. Note that yq is a wrapper for jq so the documentation of jq would be helpful as the help of yq recommends.


On Go yq you can do

yq e '.services | keys'
October answered 21/3, 2019 at 12:48 Comment(3)
Thanks @Mostafa, this is what I was looking for. I was missing that point: keys is a built-in function not a property. Also thanks for the doc link :)Attenuation
To make it work I had to write yq eval '.services | keys' docker-compose.ymlEndothermic
yq -r '.services | keys | .[]' will get you the flat list of services without a YAML listSpeakeasy
T
8

Since you just want to list the services from a docker-compose file you could achieve this with a docker-compose command.

docker-compose config --services

Not directly an answer to the question as it is not using yq but maybe it helps ;)

Tsingyuan answered 23/7, 2019 at 9:48 Comment(3)
docker-compose config --services takes over 1 second to load for some reason. interestingly ruby -e 'require "yaml"; puts YAML.load(File.read("docker-compose.yml"))["services"].keys' completes in ~0.1sExacerbate
while docker-compose config scans the config and might be helpful to check the final configuration that will be applied. In this case I would more stick on the solution from Mostafa Hussein yq '.services | keys[]' docker-compose.ymlTsingyuan
i love this option. Pretty straightforward and it doesn't require yqZephyrus

© 2022 - 2024 — McMap. All rights reserved.