Kubectl get JSONPath Support: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(67 intermediate revisions by the same user not shown)
Line 6: Line 6:
* [[JSONPath]]
* [[JSONPath]]
=Overview=
=Overview=
=Syntax=
<syntaxhighlight lang='bash'>
==$==
kubectl get -o jsonpath='{<jsonpath-expression>}' ...
* [[JSONPath#.24|JSONPath $]]
</syntaxhighlight>
==Object Fields Selection==
 
* [[JSONPath#.field|JSONPath .''field'']]
supports a JSONPath template, which consists in [[JSONPath#JSONPath_Expression|JSONPath expressions]] enclosed by curly braces.
<syntaxhighlight lang='bash'>
kubectl get pod some-pod -o jsonpath='{.status.phase}'
</syntaxhighlight>


==Array Element Selection==
More than one JSONPath expressions can be concatenated in a JSON template:
* [[JSONPath#.5B0-based-index.5D|[''0-based-index'']]]
<syntaxhighlight lang='bash'>
* [[JSONPath#.5Bindex1.2C_index2.2C_....5D|[''index1'', ''index2'', ...]]]
kubectl get pod some-pod -o jsonpath='the pod name {.metadata.name} and phase {.status.phase}'
* [[JSONPath#.5Bstart:end.5D.2C_.5Bstart:.5D|[''start'':''end''], [''start'':]]]
</syntaxhighlight>
* [[JSONPath#.5B:n.5D|[:''n'']]]


=Concepts=
The JSONPath expression are mainly used to:
==Syntax Elements==
* Filter the JSON content to only allow specific fields in the JSON object, using [[#Filter_Expressions|filter expressions]].
* Format the output.


The result object is printed as its String() function.


In addition to the original [[JSONPath#JSONPath_Expression|JSONPath syntax]], kubectl provides the following extensions:
* The possibility to use double quotes to quote text inside JSONPath expressions.
* The availability of the [[#range_and_end_Operators|range]] and [[#range_and_end_Operators|end]] operators to iterate lists.


Note that when the result of the kubectl query contains more than one item, it is returned as a "List" top-level JSON [[JSON_Concepts#Objects|Object]], where individual results are element of an ".items" array:
<syntaxhighlight lang='json'>
{
  "apiVersion": "v1",
  "kind": "List",
  "metadata": {
    "resourceVersion": "..."
    ...
  }
  "items": [
    {
      "apiVersion": "v1",
      "kind": "Namespace",
      ...
    },
    ...
  ]
}
</syntaxhighlight>
The result should be processed as such:
<syntaxhighlight lang='bash'>
kubectl get pods -o jsonpath="{.items[*]...}"
</syntaxhighlight>


==jsonpath and Queries that Return Arrays==


====Removing Leading and Trailing Single Quotes====
⚠️ If the kubectl query returns an array, as when <code>--selector</code> is used, ensure the JSONPath expression includes <code>.items[*]</code>, otherwise the filter will not work correctly.


<syntaxhighlight lang='text'>
<syntaxhighlight lang='text'>
... | sed -e 's/^'\''//' > ...
kubectl get pod --selector=app=someapp -o jsonpath='{.metadata.name}'
</syntaxhighlight>
will return an empty string, even if there is a pod with a "app=someapp" selector. The correct query is:
<syntaxhighlight lang='text'>
kubectl get pod --selector=app=someapp -o jsonpath='{.items[*].metadata.name}'
</syntaxhighlight>
</syntaxhighlight>


====Get an Individual Attribute Only====
=Syntax=
==$==
As in the generic case, the $ operator is optional, since the expression always starts from the root object by default. However, the leading dot is not optional. More details on $: {{Internal|JSONPath#.24|JSONPath $}}


<font color=darkgray>TODO: https://gist.github.com/so0k/42313dbb3b547a0f51a547bb968696ba</font>
==Element Selection==
===Object Fields Selection===
====Individual Fields====
{{Internal|JSONPath#.field|JSONPath .''field''}}
{{Internal|JSONPath#.5B.27field.27.5D|JSONPath [&#39;''field''&#39;]}}
The value of a specified field can be obtained with the child operator:
<syntaxhighlight lang='bash'>
kubectl get pod <pod-name> -o jsonpath="{.status.phase}"
kubectl get pod <pod-name> -o jsonpath="{['status']['phase']}"
</syntaxhighlight>
When more than one resource is returned as result, the result is a JSON "List" Object with an .items field, which can be queried as such:
<syntaxhighlight lang='bash'>
kubectl get pods -o jsonpath="{.items[*].status.phase}"
</syntaxhighlight>


kubectl ... -o jsonpath="{.status.phase}"
====Field Recursive Descent====
All values for a specific field can be obtained recursively with:
<syntaxhighlight lang='bash'>
kubectl get pod <pod-name> -o jsonpath="{..name}"
</syntaxhighlight>
More details: {{Internal|JSONPath#..field_.28Field_Recursive_Descent.29|JSONPath ..''field'' (field recursive descent)}}


kubectl ... -o jsonpath="{.items[?(@.spec.unschedulable)].metadata.name}"
===Array Element Selection===
Subscript operators:
* [[JSONPath#.5B0-based-index.5D|JSONPath [''0-based-index'']]]
* [[JSONPath#.5Bindex1.2C_index2.2C_....5D|JSONPath [''index1'', ''index2'', ...]]]
* [[JSONPath#.5Bstart:end.5D.2C_.5Bstart:.5D|JSONPath [''start'':''end''], [''start'':]]]
* [[JSONPath#.5B:n.5D|JSONPath [:''n'']]]
* [[JSONPath#.5B-n:.5D|JSONPath [-''n'':]]]


<font color=darkgray>
===<span id='Same_Element_from_Multiple_Resources'></span><span id='Iterate_over_the_Elements_of_an_Array'></span>Wildcard===
Alternative, to explore and document:
Wildcard can be used to iterated over the elements of an Array:
<syntaxhighlight lang='bash'>
kubectl get nodes -o jsonpath='{.items[*]}'
</syntaxhighlight>
Iterate over the elements of an Array and display a specific key:
<syntaxhighlight lang='bash'>
kubectl get pod <pod-name> -o jsonpath=".status.conditions[*].lastTransitionTime"
</syntaxhighlight>
More details: {{Internal|JSONPath#.2A_.28Wildcard.29|JSONPath * (wildcard)}}


kubectl get pods  --no-headers -o custom-columns=\":metadata.name\" ...
==@==
 
"@" represents the current object. For more details, see: {{Internal|JSONPath#.40|JSONPath @}}
</font>
==[,]==
 
[,] is the union operator that allows combining and displaying side by side multiple fields of the same object:
====Filter Elements of an Array based on a Key Value====
 
We assume that the elements of the array are maps, which contain the specified key:
 
kubectl ... -o jsonpath="{.users[?(@.name=="blue")].user.password}"
kubectl get pod ... -o jsonpath='{.items[0].spec.volumes[?(@.name=="vault")].hostPath.path}' 2>/dev/null
 
====Select and Combine Two or More Elements====
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
kubectl get pod \
kubectl get pod <pod-name> -o jsonpath="{.status.conditions[*]['status', 'type']}"
-o jsonpath='{.items[0].spec.volumes[?(@.name=="A")].hostPath.path}'+'{.items[0].spec.volumes[?(@.name=="B")].hostPath.path}'
</syntaxhighlight>
</syntaxhighlight>


returns "/some/path/a+/some/path/b"
More details: {{Internal|JSONPath#.5B.2C.5D|JSONPath Union Operator}}


====Same Element from Multiple Resources====
==Filter Expressions==
<syntaxhighlight lang='bash'>
Filter expressions can be applied to Array elements or Object fields. Filter expressions can provide the same results, and are more flexible than the built-in [[Kubectl_get_field-selector_Support#Overview|kubectl get field selector]].
kubectl get pod -o jsonpath='{.items[*].metadata.name}'
</syntaxhighlight>
====Array Length====
{{Internal|Jq_Usage#Array_Length|jq Array Length}}


====TODO====
To apply to Array elements:
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
kubectl get pods -o=jsonpath='{.items[?(@.metadata.labels.name=="web")].metadata.name}'
[?(expression)]
</syntaxhighlight>
</syntaxhighlight>
=====Iterate over the Elements of an Array=====
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
kubectl get nodes -o jsonpath='{.items[*]}'
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'
</syntaxhighlight>
</syntaxhighlight>


=====Iterate over the Elements of an Array and Select a Specific Key=====
For syntactic details and various particular cases see:{{Internal|JSONPath#Filter_Expressions|JSONPath Filter Expressions}}
===Filter Expressions Examples===
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
kubectl get nodes -o jsonpath='{.items[*].status}'
kubectl get pods -o jsonpath='{.items[?(@.metadata.labels.name=="web")].metadata.name}'
</syntaxhighlight>
</syntaxhighlight>
Filter by an element:
Filter by an element:
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")]}'
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")]}'
</syntaxhighlight>
</syntaxhighlight>
Print the element "address"
Print the element "address"
<syntaxhighlight lang='bash'>
<syntaxhighlight lang='bash'>
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'
</syntaxhighlight>
=JSONPath Extensions=
==<tt>range</tt> and <tt>end</tt> Operators==
=JSONPath and Regular Expression Support=
JSONPath regular expressions are not supported by kubectl -o jsonpath. If you want to match using regular expressions, use [[jq]]:
<syntaxhighlight lang='bash'>
kubectl get pods -o json | jq -r '.items[] | select(.metadata.name | test("test-")).spec.containers[].image'
</syntaxhighlight>
=Other Examples=
==Select and Combine Two or More Elements==
<syntaxhighlight lang='bash'>
kubectl get pod \
-o jsonpath='{.items[0].spec.volumes[?(@.name=="A")].hostPath.path}'+'{.items[0].spec.volumes[?(@.name=="B")].hostPath.path}'
</syntaxhighlight>
returns "/some/path/a+/some/path/b"
==Array Length==
{{Internal|Jq_Usage#Array_Length|jq Array Length}}
==Selecting a Pod Based on the Value of an Annotation==
Assuming the pod returns the following to <code>kubectl get pod -o json</code>:
<syntaxhighlight lang='json'>
{
    "apiVersion": "v1",
    "items": [
        {
            "apiVersion": "v1",
            "kind": "Pod",
            "metadata": {
                "annotations": {
                    "some.random.annotation": "some value",
                    ...
</syntaxhighlight>
then the following jsonpath selects the pod. Note that all dots in the annotation name must be escaped:
<syntaxhighlight lang='bash'>
kubectl get pod -o=jsonpath='{.items[?(@.metadata.annotations.some\.random\.annotation=="some value")].metadata.name}'; echo ""
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 02:45, 16 March 2024

External

Internal

Overview

kubectl get -o jsonpath='{<jsonpath-expression>}' ...

supports a JSONPath template, which consists in JSONPath expressions enclosed by curly braces.

kubectl get pod some-pod -o jsonpath='{.status.phase}'

More than one JSONPath expressions can be concatenated in a JSON template:

kubectl get pod some-pod -o jsonpath='the pod name {.metadata.name} and phase {.status.phase}'

The JSONPath expression are mainly used to:

  • Filter the JSON content to only allow specific fields in the JSON object, using filter expressions.
  • Format the output.

The result object is printed as its String() function.

In addition to the original JSONPath syntax, kubectl provides the following extensions:

  • The possibility to use double quotes to quote text inside JSONPath expressions.
  • The availability of the range and end operators to iterate lists.

Note that when the result of the kubectl query contains more than one item, it is returned as a "List" top-level JSON Object, where individual results are element of an ".items" array:

{
  "apiVersion": "v1",
  "kind": "List",
  "metadata": {
    "resourceVersion": "..."
    ...
  }
  "items": [ 
    {
      "apiVersion": "v1",
      "kind": "Namespace", 
      ...
    },
    ...
  ]
}

The result should be processed as such:

kubectl get pods -o jsonpath="{.items[*]...}"

jsonpath and Queries that Return Arrays

⚠️ If the kubectl query returns an array, as when --selector is used, ensure the JSONPath expression includes .items[*], otherwise the filter will not work correctly.

kubectl get pod --selector=app=someapp -o jsonpath='{.metadata.name}'

will return an empty string, even if there is a pod with a "app=someapp" selector. The correct query is:

kubectl get pod --selector=app=someapp -o jsonpath='{.items[*].metadata.name}'

Syntax

$

As in the generic case, the $ operator is optional, since the expression always starts from the root object by default. However, the leading dot is not optional. More details on $:

JSONPath $

Element Selection

Object Fields Selection

Individual Fields

JSONPath .field
JSONPath ['field']

The value of a specified field can be obtained with the child operator:

kubectl get pod <pod-name> -o jsonpath="{.status.phase}"
kubectl get pod <pod-name> -o jsonpath="{['status']['phase']}"

When more than one resource is returned as result, the result is a JSON "List" Object with an .items field, which can be queried as such:

kubectl get pods -o jsonpath="{.items[*].status.phase}"

Field Recursive Descent

All values for a specific field can be obtained recursively with:

kubectl get pod <pod-name> -o jsonpath="{..name}"

More details:

JSONPath ..field (field recursive descent)

Array Element Selection

Subscript operators:

Wildcard

Wildcard can be used to iterated over the elements of an Array:

kubectl get nodes -o jsonpath='{.items[*]}'

Iterate over the elements of an Array and display a specific key:

kubectl get pod <pod-name> -o jsonpath=".status.conditions[*].lastTransitionTime"

More details:

JSONPath * (wildcard)

@

"@" represents the current object. For more details, see:

JSONPath @

[,]

[,] is the union operator that allows combining and displaying side by side multiple fields of the same object:

kubectl get pod <pod-name> -o jsonpath="{.status.conditions[*]['status', 'type']}"

More details:

JSONPath Union Operator

Filter Expressions

Filter expressions can be applied to Array elements or Object fields. Filter expressions can provide the same results, and are more flexible than the built-in kubectl get field selector.

To apply to Array elements:

[?(expression)]
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'

For syntactic details and various particular cases see:

JSONPath Filter Expressions

Filter Expressions Examples

kubectl get pods -o jsonpath='{.items[?(@.metadata.labels.name=="web")].metadata.name}'

Filter by an element:

kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")]}'

Print the element "address"

kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'

JSONPath Extensions

range and end Operators

JSONPath and Regular Expression Support

JSONPath regular expressions are not supported by kubectl -o jsonpath. If you want to match using regular expressions, use jq:

kubectl get pods -o json | jq -r '.items[] | select(.metadata.name | test("test-")).spec.containers[].image'

Other Examples

Select and Combine Two or More Elements

kubectl get pod \
-o jsonpath='{.items[0].spec.volumes[?(@.name=="A")].hostPath.path}'+'{.items[0].spec.volumes[?(@.name=="B")].hostPath.path}'

returns "/some/path/a+/some/path/b"

Array Length

jq Array Length

Selecting a Pod Based on the Value of an Annotation

Assuming the pod returns the following to kubectl get pod -o json:

{
    "apiVersion": "v1",
    "items": [
        {
            "apiVersion": "v1",
            "kind": "Pod",
            "metadata": {
                "annotations": {
                    "some.random.annotation": "some value",
                    ...

then the following jsonpath selects the pod. Note that all dots in the annotation name must be escaped:

kubectl get pod -o=jsonpath='{.items[?(@.metadata.annotations.some\.random\.annotation=="some value")].metadata.name}'; echo ""