fix(chart): reconcile the telemetry Collector in place once its token Secret exists - #1048
Open
LukasWodka wants to merge 5 commits into
Open
fix(chart): reconcile the telemetry Collector in place once its token Secret exists#1048LukasWodka wants to merge 5 commits into
LukasWodka wants to merge 5 commits into
Conversation
… Secret exists The <release>-telemetry-status record for skipped-no-token promised the skip "resolves itself once jobs-manager writes the Secret". Nothing performed that: the lookup deciding the Collector's three-state rule runs only inside a helm upgrade, and the hourly auto-upgrade tick upgraded only onto a NEWER published chart. Measured on a fresh edge: Secret present within minutes, three ticks, no DaemonSet, until a new chart happened to ship a day later. Tracked internally. Mechanism: with no newer chart to install, the tick now runs one tri-state decider (telemetry_reconcile_verdict): stored state skipped-no-token AND no Collector DaemonSet in the stored manifest AND the repo serves the deployed version AND a --dry-run=server of that same version resolves `enabled` -> a same-version `helm upgrade --version "$CURRENT"` with the normal flags. Any other state behaves as before; "cannot tell" (unreadable manifest, failed dry-run, contradictory record, version not served by the repo) never acts and is logged. Derived from the chart's own decider and helpers; nothing restated. Record: names the real trigger (the next auto-upgrade tick, schedule and repo read from autoUpgrade.*; or "run helm upgrade" when autoUpgrade is off) and says plainly that a version ahead of the repo's index cannot be re-rendered. Tests: scripts/tests/auto-upgrade-telemetry-reconcile.sh drives the rendered script through a stub helm (23 cases) and its -mutations.sh sibling proves all four gates red on their own regression; both registered in `make drift`. helm-unittest +7 (kubernetesProvider reaches skipped-no-token offline). Chart 1.9.116 -> 1.9.117. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
|
bugbot run |
…-same-version-reconcile
…e this PR was open Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
|
bugbot run |
… in the Helm unit tests job, refuse without the plugin The drift job has no helm-unittest plugin, so (d) read `unknown command "unittest"` as "suite reddened, but not on the honest-record test": a gate red for the wrong reason (measured 2026-09-11, run 34581907348). The script now has two modes: reconcile (default, `make drift`: baseline + a-c) and record (`make helm-unittest` + helm-unit.yaml: baseline + d), and record mode refuses rather than skips when the plugin is missing, so it can never go decorative. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
|
bugbot run |
…e under errexit+pipefail The pipefail early-close gate flagged `helm plugin list | grep -q unittest`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 47b68ac. Configure here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
The
<release>-telemetry-statusrecord for theskipped-no-tokenstate promised that the skip "resolves itself once jobs-manager writes the Secret". Nothing performed that: thelookupdeciding the Collector's three-state rule runs only inside ahelm upgrade, and the hourly auto-upgrade tick only upgraded onto a newer published chart (already at latest; nothing to do/deployed version is ahead of repo … skipping). Measured on a fresh installer edge: the token Secret was present within minutes, three ticks passed, no DaemonSet — the Collector rendered a day later only because a new chart happened to ship. Tracked internally.This PR does two things together:
skipped-no-token(which, by the decider's construction, meanstelemetryCollector.enabledwas unset), the stored manifest carries no Collector DaemonSet, the repo serves the deployed chart version, and a server-side dry-run of that same version now resolvesenabled(the token Secret has arrived), the tick re-runshelm upgradepinned to--version "$CURRENT"with the exact flags and values discipline of the normal upgrade (--reset-then-reuse-values --atomic --cleanup-on-fail --timeout). It logs one line naming why. Any other state behaves exactly as before.autoUpgrade.schedule, repo fromautoUpgrade.repoUrl— never restated), or, withautoUpgrade.enabled: false, "runhelm upgradeon this release". Theskipped-incomplete-valuesbranch loses its "resolves itself" as well. No branch of the record promises a self-resolution any more.The condition, in one place
telemetry_reconcile_verdict()in the renderedauto-upgrade.shis the only decider — tri-state, and 2 never acts:0reconcile: stored stateskipped-no-tokenand no DaemonSet named$TELEMETRY_COLLECTOR_NAMEin the stored manifest and the repo serves$CURRENTandhelm upgrade … --version "$CURRENT" --reset-then-reuse-values --dry-run=server --hide-secretresolvesenabled.1nothing to do: any other stored state (enabled,disabled-by-operator,skipped-incomplete-values, no record at all — a release rendered by a chart predating it), or a dry-run that still saysskipped-no-token. Quiet, as today.2cannot tell:helm get manifestunreadable/empty, dry-run failed or rendered no record, the record contradicts the manifest (says skipped, DaemonSet present), the TELEMETRY_* names missing from env, or the deployed version is not served by the repo. Logged asreconcile: NOT re-rendering, cannot tell …, no upgrade.Derived, not restated. No Secret name, Class A rule or DaemonSet gate is copied into the script. The decision is read from the chart's own decider twice — the stored state out of
helm get manifest, the would-be state out of--dry-run=server(helm 3.13+; the image is pinned at 3.16.4), which runs the templates' reallookups (release-scoped, legacy and pre-override Secret names alike) against the cluster. The three names the awk matches on (TELEMETRY_STATUS_NAME,TELEMETRY_STATUS_ANNOTATION,TELEMETRY_COLLECTOR_NAME) arrive in the CronJob env from two new helpers (tracebloc.telemetryStatusName,tracebloc.telemetryStateAnnotation) plus the existingtracebloc.telemetryCollectorName— the same helpers the status template and the DaemonSet render with, pinned bytests/telemetry_status_wiring_test.yaml(including underfullnameOverride). The image has nokubectl, and a barecurlagainst the API is exactly what the house style forbids, so helm is the only client used.Deployed ahead of the index (
current > latest)This is the state the ticket caught, and it deserves a plain statement: an edge running a chart version the repo does not serve (a dev chart installed from a local path) cannot be re-rendered by the tick, because there is nothing it can fetch —
helm upgradeneeds a chart, and the deployed one exists only inside the release. The verdict names it every tick (deployed chart X is not served by <repo> (newest there: Y): a same-version re-render is impossible, the Collector renders on the next published chart), and the status record says the same. The reconcile fixes the fleet case — an edge on the published chart whose Secret arrived after install, which until now loggedalready at latest; nothing to doforever.Type
Chart.yamlversionandappVersion1.9.116 → 1.9.117)Test plan
Everything CI runs for the chart tier, locally at CI severity (outputs kept):
make lint(bash -n on every script +shellcheck -S error) — green;shellcheck -S warning -xon both new gates — clean.make drift—drift: all 50 guards green(48 existing + the 2 new ones;auto-upgrade-inflight-vs-wedge.shunchanged and green) (includes the two new guards).make helm-lint helm-vocab— 5 lints green,chart-env-vocabulary: all 177 checks passed.make helm-templatewith kubeconform — aks/bm/eks/oc allInvalid: 0, Errors: 0.make helm-unittest—Test Suites: 42 passed, 42 total/Tests: 750 passed, 750 total(was 743; +7 here).make bats—bats scripts/tests/*.bats2067 ok, 0 not ok, rc=0.sh -n(alpine/helm:3.16.4).New checks
scripts/tests/auto-upgrade-telemetry-reconcile.sh(registered inmake drift) — drives the rendered script with a stubhelmon PATH, 23 cases: the full tick end to end (Secret arrived → reconcile pinned to$CURRENTwith all flags; Secret still absent / enabled / disabled-by-operator / incomplete-values / no record → no upgrade; contradictory record / unreadable manifest / failed dry-run / dry-run without record / names missing → no upgrade and the log says cannot tell; ahead-of-index → named, no upgrade; newer chart → normal upgrade, dry-run never consulted) and the extractedtelemetry_reconcile_verdictfunction directly for the rc 0/1/2 table. Fixtures are realhelm templaterenders of this chart, not typed YAML; the names come from the rendered CronJob's env.scripts/tests/auto-upgrade-telemetry-reconcile-mutations.sh(registered inmake drift) — the permanent mutation proof, each asserting the specific finding: (a) drop the DaemonSet-absent check → contradictory case reconciles, gate red; (b) accept askipped-no-tokendry-run → Secret-still-absent case reconciles, gate red; (c) unhook the reconcile from the at-latest branch → Secret-arrived case does not reconcile, gate red; (d) restore "this resolves itself once it does" in the status template →telemetry_collector_test.yamlreddens on "the no-token skip names the trigger that actually re-renders it, not a self-resolution". All four seen red, tree as shipped seen green first.telemetry_collector_test.yaml(viakubernetesProvider, which is what lets theskipped-no-tokenstate be reached offline — a kube-system Namespace and no Secret), 1 script-shape case inauto_upgrade_test.yaml, and the 2-case wiring suite.Deliberately not changed
telemetryCollector.enabledstays tri-state with no default; the collector is not defaulted on (option 4 of the internal ticket). The refusal-when-enabled-and-no-token path is untouched.auto-upgrade-inflight-vs-wedge.shgate still passes unchanged: it runs the script without the TELEMETRY_* env, which now takes the fail-closed2branch and logs, rather than erroring underset -u.manifest.sha256is unchanged.already at latest; nothing to dobecamealready at latest; nothing to upgrade(and… skipping→… skipping the upgrade) so the line is not contradicted by a reconcile that follows it; nothing in the repo asserted the old strings.Checklist
Chart.yamlversion + appVersion)shellcheck -S warning -x+bash -nclean on every shell touchedNote
Medium Risk
Changes fleet auto-upgrade to run conditional same-version helm upgrades and depends on server-side dry-run lookups; mistakes could trigger extra upgrades or leave collectors disabled, but tri-state fail-closed logic and extensive new tests mitigate that.
Overview
Fixes a gap where the telemetry Collector stayed off after the token Secret appeared because collector state only updates on
helm upgrade, while the hourly auto-upgrade job previously exited when there was no newer chart.When the release is already at latest (or ahead of the repo index), the tick now runs
telemetry_reconcile_verdict: if the stored manifest showsskipped-no-token, no Collector DaemonSet, the repo serves the deployed version, and a server-side dry-run of that same version would resolveenabled, it performs a same-versionhelm upgradewith the usual flags. Ambiguous cases fail closed with logged “cannot tell” and no upgrade.The telemetry-status ConfigMap stops claiming skips “resolve themselves”; it names the real trigger (next auto-upgrade tick with schedule/repo from values, manual upgrade if auto-upgrade is off, or wait for a published chart on dev builds). Shared helpers
tracebloc.telemetryStatusNameandtracebloc.telemetryStateAnnotationwire the CronJob env to the status template. Chart 1.9.118; drift guards, helm-unittest cases, and mutation proofs exercise the behavior (record-honesty mutation runs in the Helm unit tests job where helm-unittest is installed).Reviewed by Cursor Bugbot for commit 47b68ac. Bugbot is set up for automated code reviews on this repo. Configure here.