kubernetes / kubernetes/kubectl

`kubectl wait --for=jsonpath`: support inequality/negation operators (`!=`) in addition to `=`

Open
#1,881 1 comment 1 reaction 0 assignees View on GitHub
kind/feature needs-triage sig/cli
Dominant language
Go
Stars
3.3k
Forks
1k
PR merge metrics
No merged PRs in 30d

Description

**What would you like to be added:**

`kubectl wait --for=jsonpath='{...}'=` currently supports only equality — it blocks until the field *equals* a known value. This request is to extend the existing jsonpath predicate with an inequality operator so you can wait until a field is *not* equal to a value:

```
# wait until .status.phase is no longer Pending
kubectl wait pod/foo --for=jsonpath='{.status.phase}'!=Pending --timeout=2m

# wait until .status.certificate is no longer empty
kubectl wait csr/alice --for=jsonpath='{.status.certificate}'!='' --timeout=60s
```

This is deliberately scoped down from #1878 (a `--while` flag), which was closed. Rather than a new flag with inverse semantics, this reuses the `--for=jsonpath` machinery that already exists and only adds an operator — a strictly smaller surface area that covers the same core use cases #1878 was trying to reach.

**Why is this needed:**

`--for=jsonpath=` can only express "wait for a field to *reach* a specific, known-in-advance value." A common and currently unaddressable class of waits is the opposite: "wait until a field *leaves* its current/transient value," where you either don't know the terminal value ahead of time or there are many possible terminal values.

Concrete examples:

- **Transient states.** Wait until `.status.phase` is anything other than `Pending`, without enumerating every possible next phase (`Running`, `Failed`, `Succeeded`, …).
- **CertificateSigningRequests.** After `kubectl certificate approve`, the signed bytes appear in `.status.certificate` at some later point, and in some configurations issuance may never happen (see #132947, #47911). You want to wait until that field is *non-empty*, but you can't express that with `=` because the certificate bytes are unknowable in advance. `!=''` expresses it directly.
- **Draining / teardown.** Wait until a replica count is `!=0`, or until a status field leaves a "reconciling"/"in-progress" value.

Today all of these require a hand-rolled `while true; do kubectl get ...; sleep; done` loop — the same pattern that motivated #83094 and #1899 — precisely because the one missing piece is a not-equal comparison.

**Worked example — CertificateSigningRequest issuance:**

After approval, the `Approved` condition flips true immediately but `.status.certificate` stays empty until (and unless) the signer issues it:

```
kubectl certificate approve alice
# alice is now Approved, but .status.certificate may still be empty
```

No single `kubectl wait` invocation covers "wait for issuance" today: `--for=condition=Approved` returns too early (approval ≠ issuance), and `--for=jsonpath='{.status.certificate}'=` can't be used because the cert bytes aren't known in advance. So people fall back to:

```
# current workaround: hand-rolled polling loop
for _ in $(seq 1 30); do
cert="$(kubectl get csr alice -o jsonpath='{.status.certificate}')"
[ -n "$cert" ] && break
sleep 1
done
[ -z "$cert" ] && { echo "approved but never issued"; exit 1; }
```

With an inequality operator this collapses to a single, timeout-aware call whose exit code cleanly distinguishes "issued" from "approved but never issued" (the failure mode in #132947):

```
kubectl wait csr/alice --for=jsonpath='{.status.certificate}'!='' --timeout=60s \
&& kubectl get csr alice -o jsonpath='{.status.certificate}' | base64 -d > alice.crt
```

**Proposed semantics / open questions:**

- **Operator set.** Minimum ask is `!=` (not-equal). `==`/`=` remains as today. Ordered comparisons (`<`, `>`, `>=`, `<=`) are a possible extension for numeric fields (e.g. replica counts) but are explicitly out of scope for a first cut to keep it small — worth noting only so the syntax chosen for `!=` doesn't preclude them later.
- **Absent fields.** This is the key decision and ties into #1236 (`--for=jsonpath` errors when the field isn't found). For `!=`, a not-yet-present field should be treated as "not equal to the target value" → predicate satisfied, rather than erroring. In the CSR case an absent-or-empty `.status.certificate` should count as "still empty, keep waiting" for `!=''`. Aligning absent-field handling with #1236's fix direction is a prerequisite for this to be useful.
- **Empty-string comparison.** `!=''` (not-empty) is the single most valuable case and should be explicitly supported, since "wait until this field is populated" is the recurring need.
- **Timeout behavior.** Unchanged from today: exceeding `--timeout` is a non-zero exit, so "field never changed" stays diagnosable — which is what makes the never-issued CSR case safe to script.

**Alternatives considered:**

- **`--while` flag (#1878).** Closed. This request is the narrower follow-up: same goal, but as an operator on existing syntax rather than a new flag.
- **Polling loops in shell.** Works, but is exactly what `wait` exists to replace; no consistent timeout/exit semantics.
- **`--for=jsonpath=` (equality only).** Requires knowing and enumerating every terminal value in advance, which the transient-state and CSR cases can't do.

/kind feature
/sig cli

Contributor guide

Open the contributing guide

Research direction

Start with kubectl's existing --for=jsonpath implementation and predicate handling, then trace how equality, missing fields, empty strings, and timeouts are currently processed. Define the != behavior, especially for absent fields and !='', and verify that equality and timeout behavior remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.