feat(bundler/api): add --dynamic query parameter to bundle handler#603
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (10)
📒 Files selected for processing (15)
📝 WalkthroughWalkthroughThe changes introduce a Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Detailed NotesThis review requires careful attention to several interconnected subsystems: New abstraction & validation: The Signature changes: Large removal: The deletion of ~470 lines from YAML serialization refactoring: The shift from post-processing marshaled bytes to using Test comprehensiveness: Several tests were consolidated or removed ( API contract: The handler now accepts 🚥 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 |
Coverage Report ✅
Coverage BadgeMerging this branch changes the coverage (2 decrease, 2 increase)
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
c6292aa to
29c56cb
Compare
29c56cb to
93f77c5
Compare
mchmarny
left a comment
There was a problem hiding this comment.
Clean PR that achieves three things well: (1) CLI/API parity for --dynamic via the shared ComponentPath primitive, (2) replaces the fragile fixValuesTemplate string manipulation with proper yaml.Node LiteralStyle, and (3) removes ~470 lines of dead reflection-based ApplyValueOverrides code. CI all green, test coverage is thorough across the new ComponentPath parser, handler query param parsing, and the reworked ApplyMapOverrides tests.
One nit on the navigateParent / getOrCreateNestedMap near-duplication. Nothing blocks merge.
…ents
The bundler --set flag validator rejected Helm-style array indexing such as
"operator.tolerations[2].key", which is a standard Helm path expression.
Pre-existing KWOK CI scripts rely on bracket indexing to append tolerations;
without it every KWOK recipe validation fails at bundle generation before
any recipe is exercised.
Widen safePathPattern to allow an optional trailing "[N]" (digits only)
per segment. The anti-injection intent is preserved: template expressions
({{ }}), path traversal (../), globs, and non-numeric bracket bodies are
still rejected. Added direct-Parse tests covering acceptance of numeric
indices and rejection of every unsafe bracket form.
This regression was introduced by NVIDIA#603 (added the restrictive regex) but
went undetected because the KWOK workflow only runs on changes under
recipes/** and kwok/**, not pkg/**.
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
…ents
The bundler --set flag validator rejected Helm-style array indexing such as
"operator.tolerations[2].key", which is a standard Helm path expression.
Pre-existing KWOK CI scripts rely on bracket indexing to append tolerations;
without it every KWOK recipe validation fails at bundle generation before
any recipe is exercised.
Widen safePathPattern to allow an optional trailing "[N]" (digits only)
per segment. The anti-injection intent is preserved: template expressions
({{ }}), path traversal (../), globs, and non-numeric bracket bodies are
still rejected. Added direct-Parse tests covering acceptance of numeric
indices and rejection of every unsafe bracket form.
This regression was introduced by NVIDIA#603 (added the restrictive regex) but
went undetected because the KWOK workflow only runs on changes under
recipes/** and kwok/**, not pkg/**.
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
…ents
The bundler --set flag validator rejected Helm-style array indexing such as
"operator.tolerations[2].key", which is a standard Helm path expression.
Pre-existing KWOK CI scripts rely on bracket indexing to append tolerations;
without it every KWOK recipe validation fails at bundle generation before
any recipe is exercised.
Widen safePathPattern to allow an optional trailing "[N]" (digits only)
per segment. The anti-injection intent is preserved: template expressions
({{ }}), path traversal (../), globs, and non-numeric bracket bodies are
still rejected. Added direct-Parse tests covering acceptance of numeric
indices and rejection of every unsafe bracket form.
This regression was introduced by NVIDIA#603 (added the restrictive regex) but
went undetected because the KWOK workflow only runs on changes under
recipes/** and kwok/**, not pkg/**.
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
…ling.sh
The `validate-scheduling.sh` script attempts to append a KWOK-test-specific
toleration to `network-operator` via Helm-style `--set` array-index syntax:
--set networkoperator:operator.tolerations[2].key=aicr.nvidia.com/kwok-test
--set networkoperator:operator.tolerations[2].operator=Equal
--set networkoperator:operator.tolerations[2].value=true
--set networkoperator:operator.tolerations[2].effect=NoSchedule
These lines have never worked. `aicr bundle --set` delegates path resolution
to `pkg/component/overrides.go:getOrCreateNestedMap`, which splits the path
on `.` only — `tolerations[2]` becomes a literal map key, not a list index,
so the generated values emit `{tolerations[2]: {key: ..., ...}}` — a string
key Helm silently ignores while keeping the upstream `tolerations` list's
defaults. PR NVIDIA#603 later tightened `safePathPattern` to reject the `[N]`
segment outright, so the failure turned from silent-wrong-bundle into
loud-parse-error and KWOK Tier 1/2 CI jobs now fail at the bundle step.
Drop the 4 dead `--set` lines. The adjacent `--accelerated-node-toleration
kwok.x-k8s.io/node=fake:NoSchedule` already propagates a tolerate-the-fake-
node rule to every accelerated workload (network-operator included) via
the recipe's per-component nodeScheduling overlay, so nothing about the
scheduling semantics of the KWOK test actually regresses — we only remove
lines that were producing misleading bundle output to begin with.
An additional negative test `helm-style array index rejected` documents
why `foo:bar.tolerations[N].key=x` must stay rejected at parse time until
someone teaches the downstream path walker to interpret `[N]` as a list
index. That's a substantive feature (affects both `ApplyMapOverrides` and
the dynamic-values extractor) and is intentionally out of scope here.
…ents
The bundler --set flag validator rejected Helm-style array indexing such as
"operator.tolerations[2].key", which is a standard Helm path expression.
Pre-existing KWOK CI scripts rely on bracket indexing to append tolerations;
without it every KWOK recipe validation fails at bundle generation before
any recipe is exercised.
Widen safePathPattern to allow an optional trailing "[N]" (digits only)
per segment. The anti-injection intent is preserved: template expressions
({{ }}), path traversal (../), globs, and non-numeric bracket bodies are
still rejected. Added direct-Parse tests covering acceptance of numeric
indices and rejection of every unsafe bracket form.
This regression was introduced by NVIDIA#603 (added the restrictive regex) but
went undetected because the KWOK workflow only runs on changes under
recipes/** and kwok/**, not pkg/**.
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
…ling.sh
The `validate-scheduling.sh` script attempts to append a KWOK-test-specific
toleration to `network-operator` via Helm-style `--set` array-index syntax:
--set networkoperator:operator.tolerations[2].key=aicr.nvidia.com/kwok-test
--set networkoperator:operator.tolerations[2].operator=Equal
--set networkoperator:operator.tolerations[2].value=true
--set networkoperator:operator.tolerations[2].effect=NoSchedule
These lines have never worked. `aicr bundle --set` delegates path resolution
to `pkg/component/overrides.go:getOrCreateNestedMap`, which splits the path
on `.` only — `tolerations[2]` becomes a literal map key, not a list index,
so the generated values emit `{tolerations[2]: {key: ..., ...}}` — a string
key Helm silently ignores while keeping the upstream `tolerations` list's
defaults. PR NVIDIA#603 later tightened `safePathPattern` to reject the `[N]`
segment outright, so the failure turned from silent-wrong-bundle into
loud-parse-error and KWOK Tier 1/2 CI jobs now fail at the bundle step.
Drop the 4 dead `--set` lines. The adjacent `--accelerated-node-toleration
kwok.x-k8s.io/node=fake:NoSchedule` already propagates a tolerate-the-fake-
node rule to every accelerated workload (network-operator included) via
the recipe's per-component nodeScheduling overlay, so nothing about the
scheduling semantics of the KWOK test actually regresses — we only remove
lines that were producing misleading bundle output to begin with.
An additional negative test `helm-style array index rejected` documents
why `foo:bar.tolerations[N].key=x` must stay rejected at parse time until
someone teaches the downstream path walker to interpret `[N]` as a list
index. That's a substantive feature (affects both `ApplyMapOverrides` and
the dynamic-values extractor) and is intentionally out of scope here.
…ling.sh
The `validate-scheduling.sh` script attempts to append a KWOK-test-specific
toleration to `network-operator` via Helm-style `--set` array-index syntax:
--set networkoperator:operator.tolerations[2].key=aicr.nvidia.com/kwok-test
--set networkoperator:operator.tolerations[2].operator=Equal
--set networkoperator:operator.tolerations[2].value=true
--set networkoperator:operator.tolerations[2].effect=NoSchedule
These lines have never worked. `aicr bundle --set` delegates path resolution
to `pkg/component/overrides.go:getOrCreateNestedMap`, which splits the path
on `.` only — `tolerations[2]` becomes a literal map key, not a list index,
so the generated values emit `{tolerations[2]: {key: ..., ...}}` — a string
key Helm silently ignores while keeping the upstream `tolerations` list's
defaults. PR NVIDIA#603 later tightened `safePathPattern` to reject the `[N]`
segment outright, so the failure turned from silent-wrong-bundle into
loud-parse-error and KWOK Tier 1/2 CI jobs now fail at the bundle step.
Drop the 4 dead `--set` lines. The adjacent `--accelerated-node-toleration
kwok.x-k8s.io/node=fake:NoSchedule` already propagates a tolerate-the-fake-
node rule to every accelerated workload (network-operator included) via
the recipe's per-component nodeScheduling overlay, so nothing about the
scheduling semantics of the KWOK test actually regresses — we only remove
lines that were producing misleading bundle output to begin with.
An additional negative test `helm-style array index rejected` documents
why `foo:bar.tolerations[N].key=x` must stay rejected at parse time until
someone teaches the downstream path walker to interpret `[N]` as a list
index. That's a substantive feature (affects both `ApplyMapOverrides` and
the dynamic-values extractor) and is intentionally out of scope here.
Summary
Add
dynamicquery parameter toPOST /v1/bundlefor CLI/API parity with the--dynamicflag. Along the way, extract a sharedComponentPathprimitive so--setand--dynamicshare one parser, and fix two adjacent OpenAPI / godoc doc gaps.Motivation / Context
PR #527 added
--dynamicsupport toaicr bundlevia the CLI (pkg/cli/bundle.go), but the HTTP API handler (pkg/bundler/handler.go) was never updated. Users callingPOST /v1/bundlecould not declare dynamic install-time values — only CLI users could. This closes that parity gap.Closes: #572
Related: #515, #527
Type of Change
Component(s) Affected
cmd/aicr,pkg/cli)cmd/aicrd,pkg/api,pkg/server)pkg/recipe)pkg/bundler,pkg/component/*)pkg/collector,pkg/snapshotter)pkg/validator)pkg/errors,pkg/k8s)docs/,examples/)Implementation Notes
Shared
ComponentPathprimitive (pkg/bundler/config/component_path.go).Exports
ComponentPath{Component, Path string, Value *string}, aParsemethod (single tokenizer forcomponent:path[=value]), and aHasValue()helper.ParseValueOverridesand
ParseDynamicValuesnow return[]ComponentPath. NewWithValueOverridePaths/WithDynamicValuePathsoptions consume the slice; the existing map-shapedWithValueOverrides/WithDynamicValuesoptions stay for direct map-shape test callers.Handler wiring. Added
dynamicValuestobundleParams, parsequery["dynamic"]next toset, wire throughconfig.WithDynamicValuePaths, and log adynamic_declarationscount. Swept the
HandleBundlesgodoc to list all 11 query params the handler actually parses —deployerandrepohad been undocumented before this PR.OpenAPI cleanup. Added
dynamicparameter on/v1/bundle(modeled onset). Expanded thedeployerenum from[helm, argocd]to[helm, argocd, argocd-helm]—argocd-helmhas been a validDeployerTypesince #527 (pkg/bundler/config/config.go:40-43) but was missing from the contract.Behavior narrowing on
--set.safePathPattern(anchored[a-zA-Z0-9][a-zA-Z0-9._-]*) was previously only applied to--dynamicinputs. It now applies to--setas well.Inputs like
bundler:path.{{inject}}=xorbundler:foo/bar=xnow return a clear error instead of silently producing literal keys in the Helm values map. No test fixture ordocumented Helm values convention relies on characters outside that pattern.
Deliberate non-goals (filed as follow-ups):
dynamicfor a registered component that isn't inrecipe.componentRefsis silently dropped today by both CLI and API (same behavior, not changed).parseQueryParamscontinues to wrap per-parser errors withErrCodeInvalidRequesteven though the inner errors already carry that code — consistent with every other paramparse here. A separate follow-up will eliminate the double-wrap across all params.
Config.valueOverrides+Config.dynamicValuesinto a single per-component struct is a larger refactor deferred to its own PR.Testing
# Commands run (prefer `make qualify` for non-trivial changes) make qualifyRisk Assessment
Rollout notes:
Checklist
make testwith-race)make lint)git commit -S) — GPG signing info