test: tiered e2e suite (kubeadm-in-container) + per-PR CI job (ADR-13) - #15
Merged
Conversation
…R-13) Prove the implemented use cases against real kubeadm/kubelet/containerd on every PR, not just unit-level config generation. Per ADR-13, e2e runs in a kind-style privileged systemd node container derived FROM the already-built kairos-kubeadm image, driving the REAL reconcile/reset subcommands against the real serialized-Cluster contract (no parallel code path). Tier-1 (per-PR; ci.yml matrix over 1.34/1.35/1.36): - single-node init converges (API healthy, node registered, status.yaml phase=Converged + provider-kubernetes.kairos.io/* annotations) - reset cleans kubeadm artifacts - init-clobber refusal (#4099-5) and upgrade-skew refusal fire - CA-pinned 2-container worker join (never UnsafeSkipCAVerification) Harness is Go-native behind //go:build e2e, runnable locally via make e2e. Supporting changes (reviewed): - internal/reconcile/budget.go: DefaultBudget 2m/3/8m -> 6m/2/8m. A cold kubeadm init pulls control-plane images and waits for health (~3-5m), which 2m PerAttempt could not accommodate; Total stays 8m so the unreachable- endpoint case still surfaces fast (ADR-14; per-action budgets are follow-up). - main.go: add a bounded reset subcommand (operator escape hatch + e2e entry) running the same validated reset.Run path as EventClusterReset. Security (ADR-13 E3): the privileged e2e job is pinned to read-only permissions and constrained to GitHub-hosted ephemeral runners, no secrets, pull_request trigger -- the controls that contain a hostile PR. Validation: unit gates + e2e compile/lint green; single-node init scenario run green locally. The full suite's authoritative venue is this job on GitHub-hosted CI (the local lab host is resource-contended). Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: William Rizzo <william.rizzo@gmail.com>
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.
What
Add a tiered end-to-end test suite that proves the implemented use cases against real kubeadm/kubelet/containerd on every PR, closing the gap between unit-level config-generation tests and "does a real cluster actually come up" (ADR-13).
Mechanism: a kind-style privileged systemd node container derived
FROMthe already-builtkairos-kubeadmimage (reuses the checksum-verified toolchain, no rebuild). The harness drives the realreconcile/resetsubcommands against the real serialized-Cluster contract — no parallel code path. Go-native behind//go:build e2e, runnable locally viamake e2e.Tier-1 (per-PR;
ci.ymlmatrix over 1.34 / 1.35 / 1.36)initconverges: apiserver healthy, node registered,status.yamlphase=Converged, allprovider-kubernetes.kairos.io/*annotations presentresetcleans kubeadm artifactsUnsafeSkipCAVerification)Heavyweight scenarios (full Kairos VM boot, HA failover, A/B upgrade) remain manual libvirt smokes — GitHub-hosted runners can't host them. That boundary is intentional and documented (E5 follow-up).
Supporting changes (reviewed)
internal/reconcile/budget.go—DefaultBudget2m/3/8m -> 6m/2/8m. A coldkubeadm initpulls control-plane images and waits for health (~3-5m), which 2m PerAttempt couldn't accommodate; Total stays 8m so the unreachable-endpoint case still surfaces fast. (ADR-14; per-action budgets are a tracked follow-up.)main.go— a boundedresetsubcommand (operator escape hatch + e2e entry) running the same validatedreset.Runpath asEventClusterReset.Security (ADR-13 E3)
The privileged e2e job is pinned to read-only
permissionsand constrained to GitHub-hosted ephemeral runners, no secrets,pull_requesttrigger — the controls that contain a hostile PR. (Reviewed: image provenance from our own checksum-verified base, CA-pinned join, argv-only exec, bounded teardown all PASS.)Validation
Unit gates + e2e compile/lint green; the single-node init scenario was run green locally. The full suite's authoritative venue is this job on GitHub-hosted CI (the local lab host is resource-contended) — so this PR's own e2e run is the proof.
Reviews: staff-engineer (E1/E2), security-architect (budget + privileged-CI), staff-architect (budget ADR-14).
🤖 Generated with Claude Code