harden(recipes): lockstep DRA driver root with operator install dir#1106
Conversation
Add TestDriverRootLockstep in pkg/recipe to assert that, for every leaf
overlay shipping both nvidia-dra-driver-gpu and gpu-operator, the
resolved nvidia-dra-driver-gpu.nvidiaDriverRoot equals the resolved
gpu-operator.hostPaths.driverInstallDir. These paths are independently
configurable across overlays today with no schema link, so an editor
can change one without the other and CI doesn't notice — that drift
breaks CDI spec generation, stalls DRA-allocated pods, and fails the
validate deployment phase.
The test walks every leaf overlay (same discovery pattern used by
TestBothBuildPathsProduceIdenticalContent), resolves it through the
production builder, and:
- HARD FAIL when both values are explicitly set and differ (the
silent-drift case the issue is guarding against).
- WARN (or fail under AICR_DRIVER_ROOT_LOCKSTEP_STRICT=1) when
exactly one side is explicitly set and the other falls through to
the upstream chart default. The chart default is not visible to
this test, so the lockstep is unverifiable rather than definitively
broken; strict mode is for the eventual cleanup PR that makes
every overlay's pair explicit.
- PASS when both are unset or both are set and match.
Also adds a small unit test for the stringAtPath helper used to dig the
nested gpu-operator.hostPaths.driverInstallDir value out of the
resolved Helm values tree.
Closes #1087
📝 WalkthroughWalkthroughThis PR adds a new test file that introduces driver root lockstep validation across recipe overlays. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@pkg/recipe/driver_root_lockstep_test.go`:
- Around line 61-62: Replace the unbounded context used for I/O in the test with
a timeout-bounded context: instead of using context.Background() for the ctx
passed into loadMetadataStore, create ctx via context.WithTimeout (e.g., a short
test-safe timeout like 5s or 10s), call defer cancel() immediately after, and
then pass that ctx into loadMetadataStore so the metadata/store and build
resolution cannot hang indefinitely in CI.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: a1733925-9309-4b6e-8d76-1ff183f55230
📒 Files selected for processing (1)
pkg/recipe/driver_root_lockstep_test.go
Coverage Report ✅
Coverage BadgeNo Go source files changed in this PR. |
|
Thanks for tackling #1087 — the invariant is real and the direction is right. There are a few gaps. |
Per review feedback on PR #1106: 1. Tighten TestDriverRootLockstep so the guard is real in default CI. The earlier two-tier design ("warn unless AICR_DRIVER_ROOT_LOCKSTEP_STRICT=1") was effectively dormant: make test runs without -v, so the t.Logf warnings were suppressed AND non-failing, leaving 25 overlays unverified. The test now hard-fails when either side is unset or when both are set and differ — both are equally risky because chart defaults differ across components (gpu-operator chart 26.3.1 defaults driverInstallDir to /run/nvidia/driver but DRA chart 25.12.0 defaults nvidiaDriverRoot to /). The AICR_DRIVER_ROOT_LOCKSTEP_STRICT toggle is retired. 2. Broaden discovery to every overlay with non-nil Spec.Criteria, not just leaves. Production resolution is per-query: filterToMaximalLeaves drops an overlay only when a matching descendant exists for that query. Intermediates like h100-gke-cos-training are resolvable directly when the query omits platform — the earlier leaf-only filter missed them. The test now covers 78 overlays (up from 32). 3. Make every overlay's gpu-operator.hostPaths.driverInstallDir explicit so the lockstep is verifiable: - components/gpu-operator/values.yaml: add base hostPaths.driverInstallDir: /run/nvidia/driver (matches the nvidia-dra-driver-gpu base value). - components/gpu-operator/values-oke.yaml + values-oke-training.yaml: set hostPaths.driverInstallDir: / (matches OKE's nvidia-dra-driver-gpu/values-oke.yaml). - overlays/kind.yaml: add gpu-operator override hostPaths.driverInstallDir: "/" (matches kind's existing nvidia-dra-driver-gpu.nvidiaDriverRoot: "/"). All 78 overlays now pass the lockstep guard. `make qualify` clean.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@pkg/recipe/driver_root_lockstep_test.go`:
- Around line 141-146: The test currently only guards against overlayCount == 0
but may still vacuously pass if no overlays were actually checked; change the
guard to assert checked > 0 (replace or add to the existing overlayCount check)
so the test calls t.Fatal when checked == 0, and update the summary t.Logf to
report the number of verified overlays using checked (not overlayCount); ensure
references to GetComponentRef("nvidia-dra-driver-gpu"), IsEnabled(), and the
t.Skipf paths remain the same so the failure triggers when all subtests were
skipped.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 5c1fda06-1996-4752-8088-64d7d8f34739
📒 Files selected for processing (5)
pkg/recipe/driver_root_lockstep_test.gorecipes/components/gpu-operator/values-oke-training.yamlrecipes/components/gpu-operator/values-oke.yamlrecipes/components/gpu-operator/values.yamlrecipes/overlays/kind.yaml
yuanchen8911
left a comment
There was a problem hiding this comment.
/lgtm
Both review findings are fully addressed (verified against the branch, including a negative test confirming the guard hard-fails on one-sided drift in default make qualify mode, and that intermediates like eks/bcm are now covered — 78/78 overlays pass).
One follow-up: update the PR description — it still describes the old strict-mode / leaf-only / test-only version (the AICR_DRIVER_ROOT_LOCKSTEP_STRICT toggle is retired, discovery now covers all 78 overlays not just 32 leaves, and the PR now also modifies gpu-operator values files, so it's no longer test-only).
… and oke PR NVIDIA#1106 set gpu-operator.hostPaths.driverInstallDir to "/" on the kind and oke overlays so it would match nvidia-dra-driver-gpu.nvidiaDriverRoot ("/") and satisfy the new TestDriverRootLockstep guard (issue NVIDIA#1087). But driverInstallDir is the host path the operator-validator bind-mounts as the driver-validation container's rootfs target. runc rejects a mount whose destination is "/" ("mountpoint is on the top of rootfs"), so nvidia-operator-validator crash-loops, ClusterPolicy never goes Ready, and the gpu-operator Helm install retries until it times out. This hung every GPU-on-kind CI job (and main's nightly schedule) starting right after NVIDIA#1106 merged; oke shares the bug but is not in CI. Fix: - Remove the driverInstallDir: "/" override from kind.yaml, values-oke.yaml, and values-oke-training.yaml so they inherit the base default /run/nvidia/driver (the value that ran green before NVIDIA#1106). - Correct TestDriverRootLockstep: the nvidiaDriverRoot == driverInstallDir lockstep only holds when the operator manages the driver (driver.enabled true). With host-installed drivers (driver.enabled false, e.g. kind/oke) the two paths are independent — nvidiaDriverRoot may be "/" while driverInstallDir must be a real subdirectory. Add a hard invariant that driverInstallDir is never "/" for any overlay, which directly guards this regression class.
Summary
Add
TestDriverRootLockstep(and a supportingTestStringAtPath) inpkg/recipeto enforce that, for every leaf overlay shipping bothnvidia-dra-driver-gpuandgpu-operator, the resolvednvidia-dra-driver-gpu.nvidiaDriverRootequals the resolvedgpu-operator.hostPaths.driverInstallDir. This is the lockstep guard requested in #1087.Motivation / Context
These two paths must point to the same on-host driver location, but they're independently configurable across overlays with no schema link between them. An overlay editor can change one without the other and CI won't notice. When they drift:
Driver/library version mismatchor missinglibnvidia-ml.so)ContainerCreatingaicr validatedeployment phase failsFixes: #1087
Related: #1086 (BCM overlay gaps — where this lockstep would have prevented an earlier debug iteration)
Type of Change
Component(s) Affected
pkg/recipe)Implementation Notes
Discovery: mirrors
TestBothBuildPathsProduceIdenticalContent— walksloadMetadataStorefor every overlay not referenced asspec.base(the leaves). Each leaf is resolved through the productionBuildRecipeResultso the wildcard contributions and mixins are exercised.Assertion tiers (per the validation-phase-floor test precedent):
AICR_DRIVER_ROOT_LOCKSTEP_STRICT=1) when exactly one side is explicitly set and the other falls through to the upstream chart default. The chart default isn't visible to this test, so the lockstep is unverifiable rather than definitively broken. Strict mode is for the eventual cleanup PR that makes every overlay's pair explicit.Why two-tier: running the test against current
mainreveals 25 leaf overlays wheregpu-operator.hostPaths.driverInstallDirfalls through to the chart default whilenvidia-dra-driver-gpu.nvidiaDriverRootis explicitly set via the dra-driver's basevalues.yaml. In practice these coincidentally lockstep (both at/run/nvidia/driver), but the lockstep is not enforced by the recipe. Cleaning that up is a separate follow-up; this PR ships the guard now and leaves the cleanup tractable via the strict-mode toggle.Coverage:
TestStringAtPathcovers the nested-map traversal helper.Testing
Results:
-race.golangci-lintclean (0 issues on./pkg/recipe/...).Verified the test catches today's gaps in strict mode:
…and passes in non-strict (default) mode, which is what
make qualifyruns.Coverage delta (
pkg/recipe): 91.9% (no change — the new file is mostly assertions exercising existing code paths).Risk Assessment
Rollout notes: Default-mode CI runs see the test pass today. A follow-up PR that makes the unset-side explicit on each overlay can flip CI to
AICR_DRIVER_ROOT_LOCKSTEP_STRICT=1to promote the warnings to errors.Checklist
make testwith-race)make lint)git commit -S)