skip to Main Content

I’m trying to integrate joining one array with multiple others into my jq command.

This is a small example of my json document:

{
    "items": [
        {
            "metadata": {
                "name": "pod1"
            },
            "spec": {
                "containers": [
                    {
                        "name": "container1",
                        "volumeMounts": [
                            {
                                "mountPath": "/path1",
                                "name": "mount1"
                            },
                            {
                                "mountPath": "/path2",
                                "name": "mount2"
                            }
                        ]
                    },
                    {
                        "name": "container2",
                        "volumeMounts": [
                            {
                                "mountPath": "/path3",
                                "name": "mount1"
                            }
                        ]
                    }
                ],
                "volumes": [
                    {
                        "name": "mount1",
                        "persistentVolumeClaim": {
                            "claimName": "claim1"
                        }
                    },
                    {
                        "name": "mount2",
                        "emptyDir": {}
                    }
                ]
            }
        }
    ]
}

I want to output the name of all pods, its containers, and the containers mount points & names, and in the end only selecting mounts whose volumes have the key persistentVolumeClaim, e.g.:

pod1;container1;mount1;/path1;claim1
pod1;container2;mount1;/path3;claim1

So far I was able to extract the pod-name, container-name and the mount name and path:

jq -r '.items[]
    | {pod:.metadata.name, c:.spec.containers[]}
    | {pod:.pod, container:.c.name, mount:.c.volumeMounts[]}
    | [.pod, .container, .mount.name, .mount.mountPath]
    | join(";")'

This give the following output:

pod1;container1;mount1;/path1
pod1;container1;mount2;/path2
pod1;container2;mount1;/path3

Now I need to join the volumes array with each volumeMounts array in containers and afterwards select for only those with the persistentVolumeClaim key. I got it to work to join two arrays, but I wasn’t able to integrate it in the command above to join volumes with each volumesMounts in the containers array in the command above:

jq -r '.items[]
    | .spec.containers[].volumeMounts+.spec.volumes
    | group_by(.name)
    | map(add)
    | .[]
    | select(.persistentVolumeClaim)'

2

Answers


  1. While traversing, you could store all parts needed into variables for reference. This includes creating a lookup index using the names under .volumes as keys, realized here as object using INDEX.

    .items[] | .metadata.name as $meta
    | .spec | INDEX(.volumes[]; .name) as $volumes
    | .containers[] | .name as $name
    | .volumeMounts[] | select($volumes[.name].persistentVolumeClaim.claimName)
    | [$meta, $name, .name, .mountPath] | join(";")
    
    pod1;container1;mount1;/path1
    pod1;container2;mount1;/path3
    

    Demo

    Login or Signup to reply.
  2. Here’s a solution which builds an index per item, then transforms the data into structured objects, and finally creates an array to join:

    .items[]
    | INDEX(.spec.volumes[]; .name) as $index
    | { pod: .metadata.name }
    + (
        .spec.containers[]
        | {
            container: .name,
            mount: JOIN($index; .volumeMounts[]; .name; {name: first.name, path: first.mountPath, claim: .[1].persistentVolumeClaim.claimName})
        } | select(.mount.claim)
    )
    | [ .pod, .container, .mount[] ]
    | join(";")
    

    Output:

    pod1;container1;mount1;/path1;claim1
    pod1;container2;mount1;/path3;claim1
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search