jq: error: syntax error, unexpected if, while checking for a object to be present and if not the adding default value

10/18/2021

Getting the error

jq: error: syntax error, unexpected if (Unix shell quoting issues?) at <top-level> while parsing kubernetes kubectl command,
kubectl get pv -o=json | jq -c '.items[] | {name: .metadata.name, claimName: .spec | if has("claimRef") then .claimRef.name else empty end }'

Trying to get the PV's which have PVC and if there are no PVC can be null of empty. For it uilding a map of name and their respective PVC if there otherwise empty or null.

Below is a sample input to the jq command or the out put of the command kubectl get pv -o=json

{
	"apiVersion": "v1",
	"items": [{
			"apiVersion": "v1",
			"kind": "PersistentVolume",
			"metadata": {
				"annotations": {
					"meta.helm.sh/release-name": "",
					"meta.helm.sh/release-namespace": ""
				},
				"creationTimestamp": "",
				"finalizers": [
					""
				],
				"labels": {
					"app.kubernetes.io/managed-by": ""
				},
				"name": "",
				"resourceVersion": "",
				"uid": ""
			},
			"spec": {
				"accessModes": [
					"ReadWriteMany"
				],
				"capacity": {
					"storage": ""
				},
				"claimRef": {
					"apiVersion": "",
					"kind": "",
					"name": "",
					"namespace": "",
					"resourceVersion": "",
					"uid": ""
				},
				"csi": {
					"driver": "",
					"volumeHandle": ""
				},
				"persistentVolumeReclaimPolicy": "",
				"volumeMode": ""
			},
			"status": {
				"phase": ""
			}
		},
		{
			"apiVersion": "v1",
			"kind": "PersistentVolume",
			"metadata": {
				"annotations": {
					"meta.helm.sh/release-name": "",
					"meta.helm.sh/release-namespace": ""
				},
				"creationTimestamp": "",
				"finalizers": [
					""
				],
				"labels": {
					"app.kubernetes.io/managed-by": ""
				},
				"name": "",
				"resourceVersion": "",
				"uid": ""
			},
			"spec": {
				"accessModes": [
					"ReadWriteMany"
				],
				"capacity": {
					"storage": ""
				},
				"claimRef": {
					"apiVersion": "",
					"kind": "",
					"name": "",
					"namespace": "",
					"resourceVersion": "",
					"uid": ""
				},
				"csi": {
					"driver": "",
					"volumeHandle": ""
				},
				"persistentVolumeReclaimPolicy": "",
				"volumeMode": ""
			},
			"status": {
				"phase": ""
			}
		}
	],
	"kind": "List",
	"metadata": {
		"resourceVersion": "",
		"selfLink": ""
	}
}

For data security have removed the data and only kept the keys Please help

-- user1562687
jq
json
kubectl
kubernetes
shell

1 Answer

10/18/2021

Put parentheses around the value of the claimName field:

{
  name: .metadata.name,
  claimName: (.spec | if has("claimRef") then .claimRef.name else empty end)
}

Depending on how much you simplified your example, you may consider reducing the the if statement to:

{
  name: .metadata.name,
  claimName: (.spec.claimRef.name? // empty)
}

Note that in both cases not just .claimName but the whole object will disappear if the respective test is going to fail.

-- pmf
Source: StackOverflow