skip to Main Content

I’m going through a Kubernetes tutorial and am using jq to filter some of kubectl’s exhaustive output.

One task that’s coming up is to show what images are deployed to what pods, using kubectl get pods. So far I have this:

kubectl get pods -o json | jq '.items[]|[.metadata.name,.spec.containers[].image]'

This gets me output like the this:

[
  "kubernetes-bootcamp-5485cc6795-4blsd",
  "gcr.io/google-samples/kubernetes-bootcamp:v1"
]
[
  "kubernetes-bootcamp-5485cc6795-k824z",
  "gcr.io/google-samples/kubernetes-bootcamp:v1"
]

This is nice, but if I get curious and want to see more information about a specific pod, I’d need to use its index in the .items array. That’s fine here where there are only two items in total, but I imagine a production Kubernetes cluster might have thousands. Is there any way I can include the item’s index in the output? In other words, I want to see:

[
  0,
  "kubernetes-bootcamp-5485cc6795-4blsd",
  "gcr.io/google-samples/kubernetes-bootcamp:v1"
]
[
  1,
  "kubernetes-bootcamp-5485cc6795-k824z",
  "gcr.io/google-samples/kubernetes-bootcamp:v1"
]

I had tried using path(.) in the array constructor, but it just results in an empty array instead of the path to that item. I’ve been reading through the jq man page but so far I’m stumped. Any help would be appreciated!

Sample data

Here’s a snippet from kubectl that can be used to reproduce the output in my question.

{
    "items": [
        {
            "metadata": {
                "name": "kubernetes-bootcamp-5485cc6795-4blsd"
            },
            "spec": {
                "containers": [
                    {
                        "image": "gcr.io/google-samples/kubernetes-bootcamp:v1"
                    }
                ]
            }
        },
        {
            "metadata": {
                "name": "kubernetes-bootcamp-5485cc6795-k824z"
            },
            "spec": {
                "containers": [
                    {
                        "image": "gcr.io/google-samples/kubernetes-bootcamp:v1"
                    }
                ]
            }
        }
    ]
}

If you save this to output.json for example, you can reproduce my problem with the command

cat output.json | jq '.items[]|[.metadata.name,.spec.containers[].image]' 

2

Answers


  1. You could create an index variable, e.g. as follows:

    range(0; .items|length) as $i | .items[$i] | [$i, .metadata.name, .spec.containers[].image]
    

    Alternatively, you could define a generic enumerate function and use it as follows:

    def enumerate(s): foreach s as $x (-1; .+1; [., $x]);
    
    enumerate(.items[] | [.metadata.name, .spec.containers[].image]) | [first] + last
    
    Login or Signup to reply.
  2. You could use the to_entries filter (see the manual) which turns an object into an array of objects containing each field’s key and value. However, if applied to an array, the array’s indices will be used as keys instead:

    .items | to_entries[]
    
    {
      "key": 0,
      "value": ...
    }
    {
      "key": 1,
      "value": ...
    }
    

    Thus, just create your output as before but with .key and .value in mind:

    .items | to_entries[] | [.key, .value.metadata.name, .value.spec.containers[].image]
    # or
    .items | to_entries[] | [.key, (.value | .metadata.name, .spec.containers[].image)]
    
    [
      0,
      "kubernetes-bootcamp-5485cc6795-4blsd",
      "gcr.io/google-samples/kubernetes-bootcamp:v1"
    ]
    [
      1,
      "kubernetes-bootcamp-5485cc6795-k824z",
      "gcr.io/google-samples/kubernetes-bootcamp:v1"
    ]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search