Home > database >  Using jq to filter and keep original json structure
Using jq to filter and keep original json structure

Time:03-11

I have a json structure, which contains a list of annotations from kubectl - jsonpath='{.spec.template.metadata.annotations}

{
  "kubectl.kubernetes.io/restartedAt": "2022-03-09T16:09:47-08:00",
  "sidecar.istio.io/proxyCPU": "100m",
  "sidecar.istio.io/proxyCPULimit": "2",
  "sidecar.istio.io/proxyMemory": "128Mi",
  "sidecar.istio.io/proxyMemoryLimit": "1Gi",
  "traffic.sidecar.istio.io/excludeOutboundPorts": "8200",
  "vault.hashicorp.com/agent-cache-enable": "true",
  "vault.hashicorp.com/agent-cache-use-auto-auth-token": "force",
  "vault.hashicorp.com/agent-init-first": "true",
  "vault.hashicorp.com/agent-inject": "true",
  "vault.hashicorp.com/ca-cert": "/run/secrets/kubernetes.io/serviceaccount/ca.crt",
  "vault.hashicorp.com/preserve-secret-case": "true",
  "vault.hashicorp.com/role": "my-role",
  "vault.hashicorp.com/secret-volume-path-a": "/var/path",
  "vault.hashicorp.com/secret-volume-path-b": "/var/path",
  "vault.hashicorp.com/secret-volume-path-c": "/var/path",
  "vault.hashicorp.com/secret-volume-path-d": "/var/path",
  "vault.hashicorp.com/secret-volume-path-e": "/var/path"
}

I am looking to use jq to only grab the keys that contain "vault", so the output should be:

{
  "vault.hashicorp.com/agent-cache-enable": "true",
  "vault.hashicorp.com/agent-cache-use-auto-auth-token": "force",
  "vault.hashicorp.com/agent-init-first": "true",
  "vault.hashicorp.com/agent-inject": "true",
  "vault.hashicorp.com/ca-cert": "/run/secrets/kubernetes.io/serviceaccount/ca.crt",
  "vault.hashicorp.com/preserve-secret-case": "true",
  "vault.hashicorp.com/role": "my-role",
  "vault.hashicorp.com/secret-volume-path-a": "/var/path",
  "vault.hashicorp.com/secret-volume-path-b": "/var/path",
  "vault.hashicorp.com/secret-volume-path-c": "/var/path",
  "vault.hashicorp.com/secret-volume-path-d": "/var/path",
  "vault.hashicorp.com/secret-volume-path-e": "/var/path"
}

I've tried using something like

$ kubectl get deployment test -n test -o jsonpath='{.spec.template.metadata.annotations}' |jq '. | to_entries[] | select(.key | startswith("vault"))'

{
  "key": "vault.hashicorp.com/agent-cache-enable",
  "value": "true"
}
{
  "key": "vault.hashicorp.com/agent-cache-use-auto-auth-token",
  "value": "force"
}

but I don't know how to convert that output back to the original json format.

CodePudding user response:

to_entries deconstructs an object into an array of key-value pairs. Use map(…) to modify its items without decomposing the array, and from_entries to reconstruct the original object from the modified array:

… | jq 'to_entries | map(select(.key | startswith("vault"))) | from_entries'

Or use with_entries(…) which is a builtin shortcut to to_entries | map(…) | from_entries:

… | jq 'with_entries(select(.key | startswith("vault")))'
{
  "vault.hashicorp.com/agent-cache-enable": "true",
  "vault.hashicorp.com/agent-cache-use-auto-auth-token": "force",
  "vault.hashicorp.com/agent-init-first": "true",
  "vault.hashicorp.com/agent-inject": "true",
  "vault.hashicorp.com/ca-cert": "/run/secrets/kubernetes.io/serviceaccount/ca.crt",
  "vault.hashicorp.com/preserve-secret-case": "true",
  "vault.hashicorp.com/role": "my-role",
  "vault.hashicorp.com/secret-volume-path-a": "/var/path",
  "vault.hashicorp.com/secret-volume-path-b": "/var/path",
  "vault.hashicorp.com/secret-volume-path-c": "/var/path",
  "vault.hashicorp.com/secret-volume-path-d": "/var/path",
  "vault.hashicorp.com/secret-volume-path-e": "/var/path"
}

Demo

  • Related