Reputation: 82467
I have the following command:
kubectl get pod -A -o=json | jq -r '.items[]|select(any( .status.containerStatuses[]; .state.waiting or .state.terminated))|[.metadata.namespace, .metadata.name]|@csv'
This command works great. It outputs both the namespace and name of my failing pods.
But now I want to add one more column to the results. The column I want is located in one (and only one) of two places:
I first tried adding .status.containerStatuses[].state.*.reason
to the results fields array. But that gave me an unexpected '*'
compile error.
I then got to thinking about how I would do this with SQL or another programming language. They frequently have a function that will return the first non-null value of its parameters. (This is usually called coalesce). However I could not find any such command for jq
.
How can I return the reason
as a result of my query?
Upvotes: 11
Views: 4053
Reputation: 116919
In case you want to go with coalesce
:
# Stream-oriented version
def coalesce(s):
first(s | select(. != null)) // null;
or if you prefer to work with arrays:
# Input: an array
# Output: the first non-null element if any, else null
def coalesce: coalesce(.[]);
Using the stream-oriented version, you could write something along the lines you had in mind with the wildcard, e.g.
coalesce(.status.containerStatuses[].state[].reason?)
Upvotes: 1
Reputation: 116919
jq has a counterpart to "coalesce" in the form of //
.
For example, null // 0
evaluates to 0, and chances are that it will suffice in your case, perhaps:
.status.containerStatuses[].state | (.waiting // .terminated) | .reason
or
.status.containerStatuses[].state | (.waiting.reason // .terminated.reason )
or similar.
However, //
should only be used with some understanding of what it does, as explained in detail on the jq FAQ at https://github.com/stedolan/jq/wiki/FAQ#or-versus-
If //
is inapplicable for some reason, then the obvious alternative would be an if ... then ... else ... end
statement, which is quite like C's _ ? _ : _
in that it can be used to produce a value, e.g. something along the lines of:
.status.containerStatuses[].state
| if has("waiting") then .waiting.reason
else .terminated.reason
end
However, if containerStatuses
is an array, then some care may be required.
Upvotes: 15