kubectl
kubectl copied to clipboard
kubectl wait with `jsonpath` fails when field is not found
What happened?
Waiting for a field to be set on a resource using --for=jsonpath=
fails when the field is not found.
kubectl wait brokers -n knative-eventing --timeout 300s --for=jsonpath='{.status.state}'=https://example.com
error: state is not found
What did you expect to happen?
The jsonpath
syntax behaves differently when compared to --for=condition=
since this:
kubectl wait deployment <deployment_name> --timeout 300s --for=condition=Nope=True
waits even when there is no condition called Nope
.
In addition, waiting on status fields that are set asynchronously is really useful, so the usual flow of creating and waiting for a resource to have a specific field isn't reliably solvable with this error thrown.
How can we reproduce it (as minimally and precisely as possible)?
Run:
$ kubectl create deployment nginx --image=nginx; kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/nginx
deployment.apps/nginx created
error: readyReplicas is not found
Anything else we need to know?
I see a test with this behavior [1], however, I think it's not consistent with the existing wait behavior.
[1] https://github.com/kubernetes/kubernetes/blob/10dcc6c5f44a0607881cd2f3bd5c4d80f61ad120/staging/src/k8s.io/kubectl/pkg/cmd/wait/wait_test.go#L1167-L1176
Kubernetes version
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.5", GitCommit:"c285e781331a3785a7f436042c65c5641ce8a9e9", GitTreeState:"clean", BuildDate:"2022-03-16T15:58:47Z", GoVersion:"go1.17.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.3", GitCommit:"816c97ab8cff8a1c72eccca1026f7820e93e0d25", GitTreeState:"clean", BuildDate:"2022-01-26T08:02:07Z", GoVersion:"go1.17.6", Compiler:"gc", Platform:"linux/amd64"}
Cloud provider
OS version
NAME="Fedora Linux"
VERSION="35 (Workstation Edition)"
ID=fedora
VERSION_ID=35
VERSION_CODENAME=""
PLATFORM_ID="platform:f35"
PRETTY_NAME="Fedora Linux 35 (Workstation Edition)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:35"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f35/system-administrators-guide/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=35
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=35
PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
VARIANT="Workstation Edition"
VARIANT_ID=workstation
Install tools
Container runtime (CRI) and version (if applicable)
Related plugins (CNI, CSI, ...) and versions (if applicable)
@pierDipi: This issue is currently awaiting triage.
If a SIG or subproject determines this is a relevant issue, they will accept it by applying the triage/accepted
label and provide further guidance.
The triage/accepted
label can be added by org members by writing /triage accepted
in a comment.
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
/sig cli
I think it's not consistent with the existing wait behavior.
Could u please explain this more? IMO, If the field is not exist, wait will return field is not found
just like the test.
Currently, waiting on a condition with
kubectl wait deployment <deployment_name> --timeout 300s --for=condition=Nope=True
waits even when the condition Nope
doesn't exist, while waiting on a custom field with jsonpath
like:
kubectl wait <my_crd> <name> --timeout 300s --for=jsonpath='{.status.state}'=https://example.com
fails immediately when .status.state
doesn't exist which defeats the purpose of waiting for a specific value that is set asynchronously.
Example use case where the wait with jsonpath
fails immediately:
$ kubectl create deployment nginx --image=nginx; kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/nginx
deployment.apps/nginx created
error: readyReplicas is not found
instead with condition
it waits even when the condition doesn't exist:
kubectl create deployment nginx --image=nginx; kubectl wait --for=condition=Available=True deploy/nginx
deployment.apps/nginx created
deployment.apps/nginx condition met
I think this is more like a feature which keep the behavior of both logics consistent. I'm interest in implementing this. /assign
Already implement this and test locally.
kubectl create deployment nginx --image=nginx; kubectl wait --for=jsonpath=.status.readyReplicas=1 deploy/nginx
deployment.apps/nginx created
deployment.apps/nginx condition met
For fileds that not exist, will return timeout.
/transfer kubectl
/triage accepted
This might be a duplicate of #1204