kubernetes / kubectl

Issue tracker and mirror of kubectl code
Apache License 2.0
2.77k stars 899 forks source link

kubectl wait --for=jsonpath parse #1224

Open hholst80 opened 2 years ago

hholst80 commented 2 years ago

Background:

kubectl does not offer a direct way to wait for multiple signals.

https://stackoverflow.com/questions/55073453/wait-for-kubernetes-job-to-complete-on-either-failure-success-using-command-line

Workaround attempt:

Use jsonpath

❯ kubectl create job test --image=ubuntu:20.04 -- false
❯ kubectl wait '--for=jsonpath={.status.conditions[?(@.type=="Failed"||@.type=="Complete")].status}="True"'  job/test
error: jsonpath wait format must be --for=jsonpath='{.status.readyReplicas}'=3

However, this blew up, as seen above, in an unexpected way.

Side note this will likely not work anyway as a workaround to the original issue, since the output of a jsonpath might be many paths matching, it would have been easier to just have --for=..accepted many times and use the condition form.

mpuckett159 commented 2 years ago

Something to note is that kubectl uses a fairly basic implementation of the jsonpath spec. You can find out more about the specifics of it here. Specifically we do not support the || operator here. Unfortunately I believe that currently to support this specific use case you would need to use a shell function to wait on two separate fields like that.

To support this we would need to implement the usage of multiple -for flags, which should be doable, as well as support using contexts or goroutines to wait for these conditions in parallel, and finally a flag to specify whether to wait for all the conditions passed or only one of them.

/triage accepted

k8s-triage-robot commented 1 year ago

The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

You can:

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

mpuckett159 commented 1 year ago

/remove-lifecycle stale

k8s-triage-robot commented 1 year ago

The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

You can:

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

mpuckett159 commented 1 year ago

/remove-lifecycle stale

tommie commented 1 year ago

Even without ||, using ?(x==y) fails to parse, due to this split on =: https://github.com/kubernetes/kubectl/blob/838ae9fd9ec21c92d9ad690a902bbbd459f98ee4/pkg/cmd/wait/wait.go#L208

The jsonpath/ docs suggests this syntax should work.

I propose a simple improvement: Separate the splitting on equal sign into two phases:

  1. Remove the jsonpath= prefix.
  2. Do a single last-occurrence-split on = to separate the expression and condition value.

This would improve the situation for the case above, but would e.g. still not allow values with = in them.

A nicer solution would be to match curly brackets, but since RelaxedJSONPathExpression doesn't require them, that would also be prone to gotchas, AFAICT.

nouaman commented 1 year ago

A work around for a job is to use this version :

kubectl wait job job-test  --for jsonpath='{.status.conditions[*].status}'=True -o jsonpath='{.status.conditions[*].type}

This will return if the job is complete or failed. It need the version 1.26 and higher to support missing fields.

ssuriyan7 commented 10 months ago

/assign

luisdavim commented 2 months ago

another case that is not working is the following:

kubectl wait --for jsonpath='{.status.readyReplicas}={.spec.replicas}' KubeadmControlPlane -n vmsp-platform management-7qck2-8p7t6 -n vmsp-platform --timeout=20m

however, this works:

$ kubectl get KubeadmControlPlane -n vmsp-platform management-7qck2-8p7t6 -o jsonpath='{.status.readyReplicas}={.spec.replicas}'
3=3

and this also works:

$ kubectl wait --for jsonpath='{.status.readyReplicas}'=3 KubeadmControlPlane -n vmsp-platform management-7qck2-8p7t6 -n vmsp-platform --timeout=20m
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/management-7qck2-8p7t6 condition met