Skip to content

fix(validator): bound absent-resource retries in health checks of deployment validation#1324

Merged
mchmarny merged 1 commit into
NVIDIA:mainfrom
yuanchen8911:fix/validator-absent-resource-grace
Jun 12, 2026
Merged

fix(validator): bound absent-resource retries in health checks of deployment validation#1324
mchmarny merged 1 commit into
NVIDIA:mainfrom
yuanchen8911:fix/validator-absent-resource-grace

Conversation

@yuanchen8911

@yuanchen8911 yuanchen8911 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix the deployment validator's expected-resources check so it fails fast and cleanly when a recipe-declared resource is absent or in a different namespace than the recipe expects — instead of retrying to the Job deadline and reporting an opaque other.

Fixes #1323

Problem

On a cluster where a recipe component is absent or misplaced, expected-resources retried the missing resource for the full ChainsawAssertTimeout (6m). With ChainsawMaxParallel = 4 worker slots, a few absent components starved the healthy ones and pushed the check past the Job's activeDeadlineSeconds; the pod was killed and the result surfaced as status=other (~8m) with a misleading client rate limiter Wait … context deadline exceeded message rather than an actionable failure.

Changes

  • Absent-resource grace (pkg/defaults.AbsentResourceGracePeriod = 30s): bound only the entirely-absent (ErrCodeNotFound) case. A not-ready resource (shape mismatch → ErrCodeInternal) and a transient API failure (ErrCodeUnavailable) keep the full readiness budget, so slow-but-healthy rollouts are not failed prematurely.
  • Stateful grace: the grace is disabled once the resource is actually observed (a shape-mismatch ErrCodeInternal), so a later transient NotFound (e.g. a pod recreate mid-rollout) keeps the full deadline. A transient ErrCodeUnavailable does not latch (it proves nothing about existence), so a clean NotFound after an API blip still gets the fast-fail.
  • Preserve the substantive reason at the deadline: the retry loops surface the last real assertion error (e.g. "resource not found"), not the ErrCodeInternal context-cancellation/rate-limiter artifact — so the verdict is a clean failed with the real cause, not an opaque other.
  • Align the raw-resource path: assertSingleDocument now propagates the fetcher's structured code (NotFound/Unavailable) instead of blanket-wrapping as ErrCodeInternal, so the grace/latch logic works identically in both the in-process and raw paths.
  • Raise validator REST client limits (QPS 50 / Burst 100) above the client-go defaults so the multi-component enumeration sweep is not throttled. apiserver APF still protects the server.

Tests

preferSubstantiveErr, notFoundGraceDeadline (incl. the recreate case), resourceObservedErr (incl. Unavailable does-not-latch), assertSingleDocument propagates the structured code, and a canceled-context retry that asserts the substantive error is surfaced. Build, lint, and -race tests pass.

Verified on live clusters

Cluster Topology Result
Managed RTX Pro 6000 (components match recipe) healthy all-pass, 28s
GB300 (components in different namespaces + a component removed) divergent failed in 1m26s, clean reason (Nodewright tuning: not found …)

Same divergent GB300 cluster, before vs after: 8m24s → 1m26s, otherfailed with the real cause.

Risk

  • Low — behavior change scoped to the absent (NotFound) case; not-ready and transient paths keep their full timeout. Easy to revert.

@yuanchen8911 yuanchen8911 added area/tests area/validator theme/validation Constraint evaluation, health checks, and conformance evidence labels Jun 11, 2026
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds validator client QPS/Burst defaults and a 30s AbsentResourceGracePeriod; implements helpers to classify NotFound and choose substantive vs fallback errors with a NotFound-specific deadline gate; updates assert/error retry loops and the runner to preserve substantive failures on timeout/cancellation and to apply the absent-resource grace window; and rebuilds the typed Kubernetes client with raised QPS/Burst.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • mchmarny
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed Description comprehensively explains the problem, changes, and verification, clearly related to the code changes in the PR.
Linked Issues check ✅ Passed Code changes fully address issue #1323 objectives: bound NotFound retries with AbsentResourceGracePeriod, preserve substantive errors, and raise validator REST client QPS/Burst limits.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #1323: new timeout constants, client QPS/Burst settings, grace logic, error propagation, and supporting tests for validation speedup.
Title check ✅ Passed The title accurately describes the main change: bounding retries for absent resources in validator health checks during deployment validation using a grace period.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
validators/chainsaw/inprocess.go (1)

164-185: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Grace window is anchored too early and can prematurely fail transient recreate flows.

absentDeadline is fixed at function start (Line 164), then any later ErrCodeNotFound uses that stale cutoff (Line 184/Line 281). If a resource appears (or returns non-NotFound) and later briefly disappears during rollout, this path can fail immediately even though the resource is not “entirely absent.”
Please make the grace window stateful (only for consecutive initial NotFound, or reset/disable grace after first non-NotFound). Apply the same fix pattern in validators/chainsaw/runner.go Line 169-193.

Also applies to: 280-285

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@validators/chainsaw/inprocess.go` around lines 164 - 185, The current loop
anchors absentDeadline at function start (absentDeadline :=
time.Now().Add(defaults.AbsentResourceGracePeriod)) which causes
notFoundGraceDeadline(lastErr, absentDeadline, deadline) to treat later
transient NotFound errors as still within the original grace window; change the
logic to set/clear the absentDeadline only when you observe a NotFound result
and to reset/disable it when you observe the first non-NotFound (i.e., make the
grace window stateful): remove the fixed absentDeadline initialization,
introduce a nil/zero absentDeadline variable updated inside the loop when
evaluateAssert returns an ErrCodeNotFound, and clear/zero that variable when
evaluateAssert returns any non-NotFound error so subsequent
notFoundGraceDeadline calls use the updated state; apply the same change to the
analogous loop in validators/chainsaw/runner.go (the block around
evaluateAssert/evaluate and notFoundGraceDeadline).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@validators/chainsaw/inprocess.go`:
- Around line 164-185: The current loop anchors absentDeadline at function start
(absentDeadline := time.Now().Add(defaults.AbsentResourceGracePeriod)) which
causes notFoundGraceDeadline(lastErr, absentDeadline, deadline) to treat later
transient NotFound errors as still within the original grace window; change the
logic to set/clear the absentDeadline only when you observe a NotFound result
and to reset/disable it when you observe the first non-NotFound (i.e., make the
grace window stateful): remove the fixed absentDeadline initialization,
introduce a nil/zero absentDeadline variable updated inside the loop when
evaluateAssert returns an ErrCodeNotFound, and clear/zero that variable when
evaluateAssert returns any non-NotFound error so subsequent
notFoundGraceDeadline calls use the updated state; apply the same change to the
analogous loop in validators/chainsaw/runner.go (the block around
evaluateAssert/evaluate and notFoundGraceDeadline).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 90f66859-9279-41f1-b516-9674ced6b783

📥 Commits

Reviewing files that changed from the base of the PR and between e05a236 and 0416cf1.

📒 Files selected for processing (6)
  • pkg/defaults/k8s.go
  • pkg/defaults/timeouts.go
  • validators/chainsaw/grace_test.go
  • validators/chainsaw/inprocess.go
  • validators/chainsaw/runner.go
  • validators/context.go

@yuanchen8911 yuanchen8911 force-pushed the fix/validator-absent-resource-grace branch 2 times, most recently from 7c5bcb5 to 2388e4d Compare June 12, 2026 17:24
@yuanchen8911

Copy link
Copy Markdown
Contributor Author

@coderabbitai Addressed in 2388e4d.

Good catch on the grace window being anchored too early. Made the grace stateful: a sawResource flag is set once any non-NotFound result is observed (resource exists / not-ready / transient error), and notFoundGraceDeadline(err, sawResource, absentDeadline, deadline) returns the full deadline whenever sawResource is true. So the short AbsentResourceGracePeriod now only bounds a resource that has been NotFound from the start; a later transient NotFound (e.g. a pod recreate mid-rollout, after the resource had already appeared) keeps the full readiness budget instead of fast-failing on the stale cutoff.

Applied the same pattern in both validators/chainsaw/inprocess.go (runAssertWithRetry) and validators/chainsaw/runner.go (assertRawResources). Added a notFoundGraceDeadline unit case for the recreate flow (sawResource=true + NotFound → full deadline), plus tests for preferSubstantiveErr and a canceled-context retry that asserts the substantive error is surfaced.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@yuanchen8911 The stateful sawResource flag is exactly the right fix — anchoring the grace-period only to resources that have been absent from the very first probe prevents the false-fast-fail on mid-rollout pod recreates while still delivering the intended speedup for genuinely missing resources. The symmetry across both inprocess.go and runner.go, plus the new recreate-flow unit case, looks thorough. Thanks for the clean implementation!

(ᵔ◡ᵔ)🐇

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
validators/chainsaw/runner.go (1)

169-201: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

NotFound grace is bypassed on raw-resource asserts because fetch errors are re-coded to internal.

At Line 201, the new grace path depends on isNotFoundErr(lastErr), but assertSingleDocument at Line 266 wraps fetcher.Fetch errors as ErrCodeInternal. That clobbers ErrCodeNotFound, so absent resources in raw YAML mode won’t hit the 30s grace and will continue using the full timeout.

💡 Proposed fix (preserve structured codes from fetcher)
diff --git a/validators/chainsaw/runner.go b/validators/chainsaw/runner.go
@@
 	actual, err := fetcher.Fetch(ctx, apiVersion, kind, namespace, name)
 	if err != nil {
-		return errors.Wrap(errors.ErrCodeInternal,
-			fmt.Sprintf("failed to fetch %s %s/%s", kind, namespace, name), err)
+		return errors.PropagateOrWrap(
+			err,
+			errors.ErrCodeInternal,
+			fmt.Sprintf("failed to fetch %s %s/%s", kind, namespace, name),
+		)
 	}

Based on learnings, structured errors should be propagated as-is to preserve their codes, and this grace logic depends on preserving ErrCodeNotFound.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@validators/chainsaw/runner.go` around lines 169 - 201, The NotFound-grace
logic in notFoundGraceDeadline is bypassed because assertSingleDocument
currently re-wraps errors from fetcher.Fetch as ErrCodeInternal, which destroys
ErrCodeNotFound; update assertSingleDocument so it preserves and returns
structured errors from fetcher.Fetch (i.e., if the fetch error already carries a
structured error code such as ErrCodeNotFound, return it as-is) and only wrap
truly unknown/non-structured errors as ErrCodeInternal; this will ensure
assertAllDocuments sees the original ErrCodeNotFound (so isNotFoundErr(lastErr)
and the absentDeadline logic work correctly).

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@validators/chainsaw/runner.go`:
- Around line 169-201: The NotFound-grace logic in notFoundGraceDeadline is
bypassed because assertSingleDocument currently re-wraps errors from
fetcher.Fetch as ErrCodeInternal, which destroys ErrCodeNotFound; update
assertSingleDocument so it preserves and returns structured errors from
fetcher.Fetch (i.e., if the fetch error already carries a structured error code
such as ErrCodeNotFound, return it as-is) and only wrap truly
unknown/non-structured errors as ErrCodeInternal; this will ensure
assertAllDocuments sees the original ErrCodeNotFound (so isNotFoundErr(lastErr)
and the absentDeadline logic work correctly).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: a94c9af4-9adf-4368-a1a0-18dc1b31542e

📥 Commits

Reviewing files that changed from the base of the PR and between 7c5bcb5 and 2388e4d.

📒 Files selected for processing (7)
  • pkg/defaults/k8s.go
  • pkg/defaults/timeouts.go
  • validators/chainsaw/grace_test.go
  • validators/chainsaw/inprocess.go
  • validators/chainsaw/runner.go
  • validators/chainsaw/substantive_test.go
  • validators/context.go

@yuanchen8911 yuanchen8911 force-pushed the fix/validator-absent-resource-grace branch from 2388e4d to 8b9cc20 Compare June 12, 2026 17:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
validators/chainsaw/runner.go (1)

265-268: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve Fetch error codes on the raw-resource path.

assertRawResources() now decides both the short absent-resource grace and the final surfaced failure code from lastErr, but this wrap collapses every fetcher.Fetch() failure into ErrCodeInternal. That means raw YAML asserts never hit the new ErrCodeNotFound fast-fail path, and transient ErrCodeUnavailable fetch failures are also misclassified as internal failures. In practice, raw-resource checks still burn the full timeout and can report other instead of the intended structured failure.

Suggested fix
 	actual, err := fetcher.Fetch(ctx, apiVersion, kind, namespace, name)
 	if err != nil {
-		return errors.Wrap(errors.ErrCodeInternal,
-			fmt.Sprintf("failed to fetch %s %s/%s", kind, namespace, name), err)
+		return errors.PropagateOrWrap(err, errors.ErrCodeInternal,
+			fmt.Sprintf("failed to fetch %s %s/%s", kind, namespace, name))
 	}

Based on learnings, errors that already carry the correct structured code should be propagated as-is, or via errors.PropagateOrWrap(...), instead of being re-wrapped under a new code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@validators/chainsaw/runner.go` around lines 265 - 268, The current wrap in
the fetch path (inside the block handling fetcher.Fetch in runner.go) always
converts any fetch error into ErrCodeInternal which prevents
assertRawResources() from seeing original codes like ErrCodeNotFound or
ErrCodeUnavailable; change the error handling so that errors returned by
fetcher.Fetch (used by functions like assertRawResources and assigned to
lastErr) preserve their structured code—either by using
errors.PropagateOrWrap(...) with the descriptive message or by checking the
error's code and returning it directly instead of wrapping into
ErrCodeInternal—so existing ErrCodeNotFound/ErrCodeUnavailable values flow
through unchanged while still annotating the failure with the "failed to fetch
<kind> <namespace>/<name>" context.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@validators/chainsaw/runner.go`:
- Around line 265-268: The current wrap in the fetch path (inside the block
handling fetcher.Fetch in runner.go) always converts any fetch error into
ErrCodeInternal which prevents assertRawResources() from seeing original codes
like ErrCodeNotFound or ErrCodeUnavailable; change the error handling so that
errors returned by fetcher.Fetch (used by functions like assertRawResources and
assigned to lastErr) preserve their structured code—either by using
errors.PropagateOrWrap(...) with the descriptive message or by checking the
error's code and returning it directly instead of wrapping into
ErrCodeInternal—so existing ErrCodeNotFound/ErrCodeUnavailable values flow
through unchanged while still annotating the failure with the "failed to fetch
<kind> <namespace>/<name>" context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 73d5cce9-985b-4b34-8f1a-260e0748f656

📥 Commits

Reviewing files that changed from the base of the PR and between 2388e4d and 8b9cc20.

📒 Files selected for processing (7)
  • pkg/defaults/k8s.go
  • pkg/defaults/timeouts.go
  • validators/chainsaw/grace_test.go
  • validators/chainsaw/inprocess.go
  • validators/chainsaw/runner.go
  • validators/chainsaw/substantive_test.go
  • validators/context.go

@yuanchen8911 yuanchen8911 force-pushed the fix/validator-absent-resource-grace branch from 8b9cc20 to d9a91e2 Compare June 12, 2026 18:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
validators/chainsaw/runner.go (1)

173-205: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast on terminal assertion-spec errors in the raw-resource retry loop.

assertSingleDocument now classifies malformed/non-evaluable checks as ErrCodeInvalidRequest, but assertRawResources still retries until timeout instead of exiting immediately on terminal errors. This can unnecessarily consume ChainsawMaxParallel slots and prolong runs.

Suggested fix
 for {
 	lastErr = assertAllDocuments(ctx, docs, fetcher)
 	if lastErr == nil {
 		result.Passed = true
 		slog.Info("health check passed", "component", ca.Name)
 		return result
 	}
+	if isTerminalAssertErr(lastErr) {
+		reason := preferSubstantiveErr(lastSubstantiveErr, lastErr)
+		result.Output = reason.Error()
+		result.Error = reason
+		slog.Warn("health check failed", "component", ca.Name, "error", reason)
+		return result
+	}
 
 	// Record the failure seen while the context is still live; after
 	// cancellation assertAllDocuments returns a context / rate-limiter
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@validators/chainsaw/runner.go` around lines 173 - 205, After
assertAllDocuments returns a terminal assertion-spec error (e.g.
ErrCodeInvalidRequest produced by assertSingleDocument), we should stop retrying
and free the ChainsawMaxParallel slot instead of looping to timeout; detect the
terminal code (use the same error-code helper you have for assertions, e.g.
compare assertionErrorCode(lastErr) to ErrCodeInvalidRequest or add an
isTerminalAssertionErr helper), and when true set the result as a clean failure
(populate the result/Error or result.Message similarly to other failure paths),
log the terminal error, and return immediately from the loop (or break to the
same exit path) inside the assertRawResources retry loop that calls
assertAllDocuments so retries do not continue on non-retryable assertion errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@validators/chainsaw/runner.go`:
- Around line 173-205: After assertAllDocuments returns a terminal
assertion-spec error (e.g. ErrCodeInvalidRequest produced by
assertSingleDocument), we should stop retrying and free the ChainsawMaxParallel
slot instead of looping to timeout; detect the terminal code (use the same
error-code helper you have for assertions, e.g. compare
assertionErrorCode(lastErr) to ErrCodeInvalidRequest or add an
isTerminalAssertionErr helper), and when true set the result as a clean failure
(populate the result/Error or result.Message similarly to other failure paths),
log the terminal error, and return immediately from the loop (or break to the
same exit path) inside the assertRawResources retry loop that calls
assertAllDocuments so retries do not continue on non-retryable assertion errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: a63d40ba-3105-4eeb-b214-030fc87a3adf

📥 Commits

Reviewing files that changed from the base of the PR and between 8b9cc20 and d9a91e2.

📒 Files selected for processing (7)
  • pkg/defaults/k8s.go
  • pkg/defaults/timeouts.go
  • validators/chainsaw/grace_test.go
  • validators/chainsaw/inprocess.go
  • validators/chainsaw/runner.go
  • validators/chainsaw/substantive_test.go
  • validators/context.go

@yuanchen8911

Copy link
Copy Markdown
Contributor Author

@coderabbitai The raw-resource path finding (assertSingleDocument collapsing Fetch errors to ErrCodeInternal) is fixed in d9a91e2.

assertSingleDocument now propagates the fetcher's structured code as-is — ErrCodeNotFound (absent) and ErrCodeUnavailable (transient) are no longer blanket-wrapped — and ErrCodeInternal is reserved for an actual shape mismatch (the checks.Check error list) and a malformed assertion is returned as ErrCodeInvalidRequest. So the raw path now matches evaluateAssert: the absent-resource grace fast-fail fires and resourceObservedErr distinguishes "exists but not ready" from "absent / transient" correctly in both paths.

Added TestAssertSingleDocument_PropagatesStructuredCode (absent ⇒ NotFound propagated, not Internal) to guard it. Also fixed the stale notFoundGraceDeadline godoc.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@yuanchen8911 That's a clean resolution — propagating structured codes as-is from the fetcher is the right call, and the clear semantic split (ErrCodeInternal → shape mismatch, ErrCodeInvalidRequest → malformed assertion, ErrCodeNotFound/ErrCodeUnavailable → pass-through) makes the error taxonomy unambiguous. TestAssertSingleDocument_PropagatesStructuredCode tying down the absent-⇒-NotFound propagation is exactly the regression guard needed to keep the raw path aligned with evaluateAssert going forward. Thanks for the thorough follow-through!

The expected-resources deployment validator retried entirely-absent
resources for the full ChainsawAssertTimeout (6m), saturating the
ChainsawMaxParallel worker pool, starving healthy components, and pushing
the check past the Job deadline so it reported an opaque "other" instead
of a clean failure.

- Add AbsentResourceGracePeriod (30s) bounding only the NotFound case;
  not-ready (shape mismatch) and transient (Unavailable) keep the full 6m.
- Make the grace stateful: once any non-NotFound result is observed
  (resource exists / transient error), disable the grace so a later
  transient NotFound (e.g. a pod recreate mid-rollout) keeps the full
  readiness budget instead of fast-failing on the stale grace window.
- Preserve the substantive assertion error at the deadline so the verdict
  is a clean failed with the real reason, not a context-cancellation wrap.
- Raise validator REST client QPS/Burst (50/100) above the client-go
  defaults so the multi-component enumeration sweep is not throttled.
- Tests: preferSubstantiveErr, notFoundGraceDeadline (incl. recreate),
  and a canceled-context retry that asserts the substantive error surfaces.

Fixes NVIDIA#1323
@yuanchen8911 yuanchen8911 force-pushed the fix/validator-absent-resource-grace branch from d9a91e2 to 1000736 Compare June 12, 2026 18:12
@github-actions github-actions Bot added size/XL and removed size/L labels Jun 12, 2026
@yuanchen8911 yuanchen8911 marked this pull request as ready for review June 12, 2026 18:14
@yuanchen8911 yuanchen8911 requested a review from a team as a code owner June 12, 2026 18:14
@yuanchen8911 yuanchen8911 changed the title WIP: fix(validator): bound absent-resource retries in health checks fix(validator): bound absent-resource retries in health checks Jun 12, 2026
@yuanchen8911 yuanchen8911 requested a review from mchmarny June 12, 2026 18:14
@yuanchen8911 yuanchen8911 changed the title fix(validator): bound absent-resource retries in health checks fix(validator): bound absent-resource retries in health checks of deployment validation Jun 12, 2026
@mchmarny mchmarny merged commit 225ff43 into NVIDIA:main Jun 12, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL theme/validation Constraint evaluation, health checks, and conformance evidence

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deployment validator stalls ~8m and reports 'other' on absent resources

2 participants