Skip to content

fix(bundler): the helm readiness gate blocks and re-runs on upgrade - #2863

Merged
mchmarny merged 13 commits into
NVIDIA:mainfrom
turfbuild:fix/readiness-gate-hooks-stripped
Sep 22, 2026
Merged

mchmarny merged 13 commits into
NVIDIA:mainfrom
turfbuild:fix/readiness-gate-hooks-stripped

Conversation

@EronWright

Copy link
Copy Markdown
Contributor

Summary

The readiness gate is emitted without its helm.sh/hook annotations, so under --deployer helm it neither blocks the deploy nor re-runs on upgrade. This keeps them.

Motivation / Context

gatemanifest.Render emits helm.sh/hook: post-install,post-upgrade and helm.sh/hook-delete-policy: before-hook-creation for --deployer helm. localformat's stripHelmHooks, applied to every folder it writes, removes them again — the gate Job ships with annotations: {}.

A Job blocks helm upgrade if it is a hook (--wait) or if Helm is told to wait for a bare one (--wait-for-jobs). deploy.sh drops --wait-for-jobs because the gate is a hook; the gate is not a hook, because the annotations were stripped. The bundle has neither mechanism.

So the gate does not block — dependents install against a cluster it has not finished checking — and does not re-run, since a Job's spec.template is immutable and nothing deletes it. helm upgrade reports success either way.

Not a regression: byte-identical output at #1110, where the gate was introduced, and at current main. #1110's notes describe this path as --wait --wait-for-jobs, but the merged template only ever passed --wait.

Fixes: #2862
Related: #904, #2408 (the same failure, fixed for Argo CD only)

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • Build/CI/tooling

Component(s) Affected

  • CLI (cmd/aicr, pkg/cli)
  • API server (cmd/aicrd, pkg/server)
  • Recipe engine / data (pkg/recipe)
  • Bundlers (pkg/bundler, pkg/component/*)
  • Collectors / snapshotter (pkg/collector, pkg/snapshotter)
  • Validator (pkg/validator)
  • Core libraries (pkg/errors, pkg/k8s)
  • Docs/examples (docs/, examples/)

Implementation Notes

Keyed on the injection phase, not the deployer. localformat/doc.go invariant 1 forbids per-deployer branches in Write, and this adds none: the readiness folder is the only folder localformat writes whose content its own caller authored. Recipe content, whose author cannot know the target deployer, is stripped exactly as before.

Not a blanket exemption for non-Argo deployers. That reopens #1835 — 31 recipe files carry 96 hook annotations including before-hook-creation, which under plain Helm made resources fire-and-forget, skipped by upgrade, left behind by uninstall, and delete-recreated on every upgrade.

The exempt path still round-trips the YAML. stripHelmHooks also re-encodes at a consistent indent (what keeps goldens stable) and rejects unparseable input (the only YAML check a manifest gets before a cluster sees it). The round-trip moves into a shared rewriteYAMLDocs; the exemption skips the filter, never the rewrite — which is why Argo CD's bytes do not move.

Testing

make lint      # 0 issues
go test ./...  # all pass

The new golden catches the bug. TestBundleGolden_ReadinessGate fails with the fix reverted and passes with it, and pins both annotations by name as well as by golden bytes. pkg/bundler/deployer/helm/testdata/ previously had no readiness golden at all, which is why nothing caught this.

The Argo goldens must not move — they don't. git diff --exit-code over argocd/testdata and argocdhelm/testdata is clean and TestBundleGolden* pass unchanged; they are not -updated here.

The exemption is phase-scoped. TestWrite_HookExemptionIsScopedToReadiness puts a readiness folder beside a hook-annotated post folder and asserts the gate keeps its annotations and the post wrapper is still stripped. A blanket exemption passes the first half and reopens #1835.

Coverage: localformat 81.9%, helm 88.1%. normalizeYAMLDocs and stripHelmHooks are at 100%.

Risk Assessment

  • Low — Isolated change, well-tested, easy to revert
  • Medium — Touches multiple components or has broader impact
  • High — Breaking change, affects critical paths, or complex rollout

Rollout notes: the only output that changes is the readiness folder of a --deployer helm --readiness-hooks bundle, which regains two annotations it was always meant to ship with. Argo CD output is byte-identical; the Flux and Helmfile gates carry no annotations to keep. No flags, config or API surface.

Checklist

  • Tests pass locally (make test with -race)
  • Linter passes (make lint)
  • I did not skip/disable tests to make CI green
  • I added/updated tests for new functionality
  • I updated docs if user-facing behavior changed — no user-facing docs describe the gate's annotations
  • Changes follow existing patterns in the codebase
  • Commits are cryptographically signed (git commit -S)

gatemanifest.Render picks the readiness gate's annotations with full knowledge
of the target deployer: Helm hooks for helm, argocd.argoproj.io/sync-options
for Argo CD, and -- documented in its own comment -- deliberately no
helm.sh/hook for Argo, because Argo maps one to a PostSync hook that never
fires under syncPolicy.automated. writeLocalHelmFolder then strips the Helm
ones back off on the way to disk.

Under --deployer helm that leaves the gate shipping as a bare Job, and both
annotations it lost were load-bearing:

  - helm.sh/hook: post-install,post-upgrade is what makes the gate BLOCK.
    deploy.sh passes --wait without --wait-for-jobs, and says why in its own
    comment: "Helm --wait blocks on hook completion regardless of
    --wait-for-jobs". True of a hook. A bare Job under --wait alone returns as
    soon as the object exists, so dependents start against a cluster the gate
    has not finished checking -- which is the entire thing a gate exists to
    prevent.

  - helm.sh/hook-delete-policy: before-hook-creation is what makes it RE-RUN.
    A Job's spec.template is immutable, so an identical manifest is a no-op
    patch. Without the delete-and-recreate the gate asserts once, at install,
    and every subsequent upgrade ships unverified.

There is no golden for a helm readiness bundle, which is why this has been
invisible. This adds one.

The fix is keyed on the PHASE, not on the deployer -- localformat gains no
deployer knowledge, and the invariant in its doc.go, that it never grows
per-deployer branches, still holds. The readiness folder is simply the only
folder localformat writes that localformat's caller authored: every other one
carries recipe content whose author cannot know the consuming deployer, and
stripping those stays exactly as it was. That distinction is not cosmetic --
31 recipe files carry hook annotations whose mandated trio includes
before-hook-creation, and doc.go records what keeping those did under plain
Helm before NVIDIA#1835.

Mechanically: the yaml.v3 round-trip moves out of stripHelmHooks into a shared
rewriteYAMLDocs, and normalizeYAMLDocs exposes it without the hook filter. The
round-trip is not incidental -- it is the only YAML-validity check a rendered
manifest gets, and the consistent re-encode is what keeps every golden stable
-- so the exempt path skips the filter, never the rewrite.

That is also what makes this a no-op for Argo CD: its gate carries
sync-options, which the filter never touched, so normalize-only reproduces the
same bytes. git diff --exit-code over the argocd and argocd-helm testdata is
empty, and is the regression proof.

Terraform's gate is separate: it is annotation-free by construction and does
not change here.

Signed-off-by: Eron Wright <eronwright@gmail.com>
@EronWright
EronWright requested a review from a team as a code owner September 19, 2026 19:21
@copy-pr-bot

copy-pr-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown
Contributor

Welcome to AICR, @EronWright! Thanks for your first pull request.

Before review, please ensure:

  • All commits are signed off per the DCO
  • CI checks pass (tests, lint, security scan)
  • The PR description explains the why behind your changes

A maintainer will review this soon.

@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: NVIDIA/aicr/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 5fbb56fe-75a7-4bcc-ae35-6c56ac9ca3a8

📥 Commits

Reviewing files that changed from the base of the PR and between 964b12a and 36bf781.

📒 Files selected for processing (1)
  • pkg/bundler/deployer/helm/testdata/readiness_gate/001-foo/install.sh

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

The local Helm writer now preserves Helm hook annotations for readiness folders while continuing to strip them from pre and post folders. Shared YAML rewriting supports both normalization and hook removal. New readiness-gate fixtures define charts, scripts, RBAC, a hook Job, deployment orchestration, and documentation. Tests verify phase-scoped handling and compare the generated bundle with a golden fixture.

Priority: ⬆️ High

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: High

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the Helm readiness-gate fix and states the two primary behavior changes: blocking deployments and rerunning on upgrades.
Description check ✅ Passed The description directly explains the Helm readiness-gate annotation bug, the scoped implementation, tests, affected component, and expected behavior.
Linked Issues check ✅ Passed The pull request satisfies the coding requirements in #2862. injectAuxiliaryFolder sets annotation retention only for phaseReadiness. writeLocalHelmFolder still strips Helm hooks for other folde…
Out of Scope Changes check ✅ Passed The changes stay within #2862. The implementation, readiness fixture, golden output, and scoped tests verify the Helm readiness gate and preserve existing hook stripping for other content. The increme…
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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

@github-actions

Copy link
Copy Markdown
Contributor

Recipe evidence check

No leaf overlays affected by this PR.

This gate is warning-only and never blocks merge.

mchmarny
mchmarny previously approved these changes Sep 20, 2026

@mchmarny mchmarny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approve: no findings against d048752. Required checks and focused localformat/Helm tests pass at the reviewed SHA.

@mchmarny
mchmarny enabled auto-merge (squash) September 20, 2026 12:05
@mchmarny
mchmarny dismissed their stale review September 20, 2026 13:54

Withdrawing approval because current-head CI deterministically fails TestBundleGolden_ReadinessGate after #2855 changed the generated install script; see the follow-up comment for the required golden refresh.

@mchmarny

Copy link
Copy Markdown
Member

I removed my approval because the current-head CI failure is deterministic and needs a branch update.

The new readiness-gate golden was generated before #2855 changed install-upstream-helm.sh.tmpl. The generator now adds the dry-run stale-archive guard and its explanatory comment, but pkg/bundler/deployer/helm/testdata/readiness_gate/001-foo/install.sh still contains the old unconditional .aicr-chart.tgz check. Consequently, TestBundleGolden_ReadinessGate fails its generated-versus-golden comparison; the final gate failure only propagates that result.

The PR was green at d048752 and 8f230e7, before #2855's b510a0f6 entered the branch, and has failed with this same mismatch from 085f316 onward. Please regenerate or update the readiness-gate golden against current main, then verify with:

GOFLAGS=-mod=readonly go test ./pkg/bundler/deployer/helm -run '^TestBundleGolden_ReadinessGate$' -count=1

Failing test job

NVIDIA#2855 added the dry-run stale-archive guard to
install-upstream-helm.sh.tmpl after this branch captured its golden, so
TestBundleGolden_ReadinessGate compared freshly generated output against
the pre-NVIDIA#2855 install.sh and failed.

Regenerated with -update; the only file that moves is
testdata/readiness_gate/001-foo/install.sh, which now carries the same
DRY_RUN_FLAG guard and comment the other helm goldens already have. No
production code changes.

Signed-off-by: Eron Wright <eronwright@gmail.com>
auto-merge was automatically disabled September 20, 2026 19:06

Head branch was pushed to by a user without write access

@EronWright

Copy link
Copy Markdown
Contributor Author

Thanks — diagnosis confirmed, and fixed in 36bf781.

Regenerated the readiness-gate golden with -update. The only file that moves is pkg/bundler/deployer/helm/testdata/readiness_gate/001-foo/install.sh, which now carries #2855's DRY_RUN_FLAG guard and its comment, matching the other helm goldens. No production code changed.

Verified on the pushed head:

GOFLAGS=-mod=readonly go test ./pkg/bundler/deployer/helm -run '^TestBundleGolden_ReadinessGate$' -count=1   # ok
go test -race ./pkg/bundler/...                                                                              # ok

main has moved two commits past the last branch merge (b2cd290b, 81555ac1); neither touches pkg/bundler, so the golden is current against main as of 81555ac1. I appended rather than rebased to keep the branch merges you made intact — happy to update the branch again if the gate wants it.

EronWright added a commit to turfbuild/turf-examples that referenced this pull request Sep 21, 2026
…er under it

Regenerated bundle/ from turfbuild/aicr#3 (the terraform deployer as submitted,
stacked on NVIDIA/aicr#2863) with the README's own command and the pinned
recipe. Three things the submission dropped from the fork's earlier superset,
and the example now reflects each honestly:

  the shim is a terraform_data, referenced whole by replace_triggered_by, so
  hashicorp/helm is the bundle's only provider; no create_before_destroy, so a
  replaced cluster replaces its releases as plain destroy-then-create; no
  content digests, so an edit to bundled chart content does not reach the plan
  and the gate re-runs only on its own upgrade. The last two move from the
  README's feature list to its failure list.

Two other things moved under the same recipe: the embedded component data
(nodewright drops webhook.removalImage, nvsentinel gains the syslog monitor
block), and the bundle now carries bundle-info.yaml.

Measured on turf-engine 1ce29f8, whose sidecar serves the built-in provider,
so the bundle runs exactly as generated: up from empty converges in two
rounds (6 then 25 applied). Then the part the example exists for — replace
the cluster: all sixteen releases are condemned in the round of the replace,
including the ten inside modules that defer whole, the deletes complete
through the old cluster before its destroy does, and round two re-creates
them in the new one (28 then 34 applied, 0 failed). tofu plan against the
engine's statefile says No changes after each converge; down removes 31/31.

Terraform's experimental deferral still refuses the shim, now by the name
terraform_data.cluster; stock Terraform plans 31 to add in one round.
@EronWright
EronWright requested a review from mchmarny September 21, 2026 15:56

@mchmarny mchmarny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approve: no new findings against 895f6a0. Focused Helm and local-format race tests pass.

@mchmarny
mchmarny enabled auto-merge (squash) September 22, 2026 12:34
@mchmarny
mchmarny merged commit 44be0b0 into NVIDIA:main Sep 22, 2026
64 checks passed
EronWright added a commit to turfbuild/turf-examples that referenced this pull request Sep 25, 2026
* An AICR recipe is a graph, and flattening it costs a quarter of the run

Nothing in use-cases/datacenter/aicr-stack was written by hand. The .tf files
are generated from one NVIDIA AI Cluster Runtime recipe — service=kind,
accelerator=h100, intent=inference — which resolves to 14 components, 16
dependency edges and a DAG four levels deep. The generator turns dependencyRefs
into depends_on between module calls and ignores the recipe's precomputed
deploymentOrder, because that field is a linearisation of the graph and the
engine it is being handed to schedules graphs.

That distinction is the example's subject. AICR states it is not a cluster
provisioner, so the cluster is a precondition in everything it renders, and of
the five renderers it ships only flux carries the real edges: helm emits a line
of sixteen, argocd emits sync-waves 1/5/9/13, helmfile emits nested level files.
Both of the latter are barriers. Terraform is the one consumer that can hold the
graph and create the cluster underneath it.

The cost of a barrier is measured, not asserted, and from a single run: helmfile
reports a per-release DURATION, so both scheduling models are computed over one
sync's own numbers. The wave model predicts 204s against that run's observed
213s, which validates it; the DAG over the same durations is 152s. The clearest
case is kube-prometheus-stack waiting 58 seconds for nodewright-operator, a
component with no edges into or out of it anywhere in this recipe.

Two findings carried over from the NGC stack and confirmed at this size: the
whole kind recipe pulls anonymously from seven registries with no key of any
kind, and on a node with no NVIDIA hardware the GPU Operator creates no operand
DaemonSets while nvsentinel and nvidia-dra-driver-gpu sit cleanly at desired=0.
One NFD label is still the entire seam.

The honest failure is that stock Terraform cannot plan this tree. Every module
carries replace_triggered_by as its containment shim, and the experimental
deferred-actions path fails with "no change found" when that references a
resource which is itself deferred — reproduced on v1.17.0-alpha20260827 and on a
source build of main, and needing both halves, since dropping either the
lifecycle block or the depends_on makes it pass. Measured on the Restate engine
only; unlike ngc-stack this example has not been run on the shipping MCP engine,
and the README says so.

* The generator moved upstream, so the example is a wrapper now

Everything under bundle/ is now emitted by `aicr bundle --deployer terraform`
rather than by the bespoke generator that produced the first version of this
example. The hand-written Terraform is down to main.tf and versions.tf, about
forty lines, doing the one thing AICR will not: putting the cluster in the graph.

Regenerating is one command, and it reproduces the committed bytes exactly —
the deployer emits already-fmt-clean HCL, so `git diff` after a regenerate is
the check that this directory is current. That retires two of the three
decisions this PR was left open on: where the generator lives (upstream, as
turfbuild/aicr#1), and whether committed bytes match generated ones (they do).

Two findings came out of moving it, both now in the failure list:

A module that configures its own provider cannot be composed. The default
bundle is a root module — it declares `provider "helm"` and takes the
connection as variables, which is right for an existing cluster. Calling that
as a child module is a different shape: Terraform accepts it but then forbids
depends_on/count/for_each on the call, and the engine refuses it outright with
a message that says so and says why it refuses rather than skips. bundle/ is
therefore generated with --terraform-child-module, and the root's helm provider
— bound to kind_cluster.dc — is inherited.

The replace_triggered_by deferral bug survives verbatim into generated output:
same three modules, same error, now reachable as
`--terraform-cluster-rollover`, which is off by default upstream for exactly
this reason. Regenerate without it and experimental Terraform converges this
tree too, at the cost of the containment.

kai-scheduler's `wait = false` is no longer a hardcode in a bespoke generator:
AICR keeps that fact in one table now shared by deploy.sh, the helmfile
deployer and this one, and the module call carries the reason inline.

Re-run from empty state on turf-engine 0a94e62: round 1 plans 22 addresses and
defers 16, round 2 applies 27, converged in 2 rounds, down removes 33 in one
phase. All 16 releases deployed; ClusterPolicy ready/NoGPUNodes, no pci-*
labels, the same six DaemonSets at desired=0.

No wall-clock figure is quoted any more. Two clean runs of this tree differed
by a factor of three, in round two, which is dominated by pulling sixteen
charts' worth of images into a seconds-old cluster. That measures a laptop, not
the engine. The DAG-vs-waves number stays, because it is derived from a single
run's own per-release durations.

The values.yaml changes are recipe data, not this example: the fork is at a
newer upstream AICR than the one that produced the first bundle, and several
components gained tolerations.

* One module call per component, so depends_on means what it says

Regenerated against the reshaped terraform deployer. The bundle's own folders
are byte-identical; only the .tf layer moved.

16 releases now render as 14 module calls. A component's post-manifest release
lives inside its module, so `depends_on = [module.agentgateway_crds]` covers it
without naming the tail.

Re-run end to end on turf-engine 0076f5d: round 1 applies 6 and defers 24,
round 2 applies 25, converged in 2 rounds; 16 releases deployed, ClusterPolicy
ready, 0 pci-* labels, 6 DaemonSets at desired=0; down removes all 31 in one
phase. The converged total drops 33 -> 31 because there are 14 containment
shims rather than 16.

The first plan got noisier, and the README now says why: an empty count=0 slot
whose dependency is deferred is itself deferred before its count is evaluated,
so cert-manager shows post and readiness slots it does not have. They collapse
in round two.

Also records a measured limitation of gates under Terraform. helm_release tracks
a local chart's path, version and values, not its rendered manifests, so editing
a template produces no diff at all; and a values change does upgrade the release
but leaves the Job untouched, since spec.template is immutable. A gate therefore
verifies once, at creation.

Signed-off-by: Eron Wright <eronwright@gmail.com>

* The gate is absent by choice, and the README said the wrong reason

It claimed no component in this recipe ships a readiness.yaml. gpu-operator
does: regenerating with --readiness-hooks yields 012-gpu-operator-readiness,
a slot on module.gpu_operator that its three dependents already wait for.

The actual reason the flag is off is the gate image. AICR tags it with the
bundler version and publishes it only on release tags; a source build stamps
`dev` and falls back to ghcr.io/nvidia/aicr-gate:dev, a local-only tag you are
meant to build and kind load (404 on ghcr). --deployer terraform exists only on
a fork branch, so no released aicr can emit both the terraform bundle and a
pullable gate, and committing the flag on would ship a bundle that
ImagePullBackOffs anywhere but the machine that built it.

Signed-off-by: Eron Wright <eronwright@gmail.com>

* A gate now re-runs when its component changes

Regenerated: the component module's readiness slot gained a
replace_triggered_by on the component's own release. The bundle still ships
with --readiness-hooks off, so the slot is count=0 here, but the module is the
one upstream now emits.

Nothing reaches a gate Job by accident. spec.template is immutable, so a values
change upgrades the release and leaves the Job alone; and helm_release tracks a
local chart's path, version and values, not its rendered manifests, so editing
a template produces no plan at all. Replacing the release is uninstall plus
install, which creates a new Job.

Measured with the flag on: re-applying unchanged is 0 of 32 addresses; changing
gpu-operator's values is 2 of 32 — helm_release.this updated and
helm_release.readiness[0] replaced — and the other thirteen gates stay put. The
gate itself polls ClusterPolicy through a stability window and passes at T+30s.

Signed-off-by: Eron Wright <eronwright@gmail.com>

* A gate re-verifies without being replaced, and content reaches the plan

Regenerated against the fix in turfbuild/aicr#1. Two changes to the component
module, both about a change failing to reach the cluster.

Every slot installing a chart from this bundle now carries a digest of that
folder's bytes in the release's description. helm_release records a local
chart's path, version and values, never its rendered manifests, so without it
editing a template under NNN-<component>-post/ produces no plan at all —
terraform apply reports "No changes" while the bundle on disk differs from what
is deployed. Two -post wrappers here get one: agentgateway-crds and agentgateway.

The readiness slot no longer uses replace_triggered_by on the component's
release. That shape could not survive this bundle: --terraform-cluster-rollover
gives every slot create_before_destroy and the gate inherits it, so the
replacement installed while the old release still held the name, in the same
cluster, and helm refused it — then the next plan said no changes, so the gate
had silently stopped asserting. Instead the gate Job is a helm
post-install,post-upgrade hook that helm deletes and re-runs on every upgrade
and blocks on, and the release upgrades when either its own digest or the
component's metadata.revision moves. The bundle still ships with
--readiness-hooks off, so the slot is count=0 here.

Measured on kind with the flag on, Terraform v1.16.2 and turf-engine, rollover
both off and on:

  re-apply unchanged     No changes / 0 of 18
  change gpu-operator    0 to add, 2 to change, 0 to destroy — this and
                         readiness[0] BOTH updated in place — and a new Job UID
  then settles           No changes / 0 of 18
  edit a -post template  no diff at all, the hole above
  move its digest        post[0] updated in place, and the ConfigMap lands
  replace the cluster    32 added / 15 destroyed, 17 releases, gate re-ran there

Both engines agree, because the fix is in the generated HCL rather than in
either one.

Signed-off-by: Eron Wright <eronwright@gmail.com>

* The bundle is what the submission generates, and the cluster rolls over under it

Regenerated bundle/ from turfbuild/aicr#3 (the terraform deployer as submitted,
stacked on NVIDIA/aicr#2863) with the README's own command and the pinned
recipe. Three things the submission dropped from the fork's earlier superset,
and the example now reflects each honestly:

  the shim is a terraform_data, referenced whole by replace_triggered_by, so
  hashicorp/helm is the bundle's only provider; no create_before_destroy, so a
  replaced cluster replaces its releases as plain destroy-then-create; no
  content digests, so an edit to bundled chart content does not reach the plan
  and the gate re-runs only on its own upgrade. The last two move from the
  README's feature list to its failure list.

Two other things moved under the same recipe: the embedded component data
(nodewright drops webhook.removalImage, nvsentinel gains the syslog monitor
block), and the bundle now carries bundle-info.yaml.

Measured on turf-engine 1ce29f8, whose sidecar serves the built-in provider,
so the bundle runs exactly as generated: up from empty converges in two
rounds (6 then 25 applied). Then the part the example exists for — replace
the cluster: all sixteen releases are condemned in the round of the replace,
including the ten inside modules that defer whole, the deletes complete
through the old cluster before its destroy does, and round two re-creates
them in the new one (28 then 34 applied, 0 failed). tofu plan against the
engine's statefile says No changes after each converge; down removes 31/31.

Terraform's experimental deferral still refuses the shim, now by the name
terraform_data.cluster; stock Terraform plans 31 to add in one round.

---------

Signed-off-by: Eron Wright <eronwright@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: readiness gate is broken with --deployer helm due to missing hook annotations

2 participants