HOMELAB-990: feat(talos-cluster): bring bootstrap helm_releases into module #192

Merged
aaron merged 1 commit from plane/HOMELAB-990-talos-cluster-bootstrap into live 2026-04-26 06:24:08 +00:00
Owner

First PR of two for HOMELAB-990. Moves the Cilium + ArgoCD helm bootstrap (and root-app kubectl_manifest, kubeconfig file, wait_for_nodes) from prod/terraform/main.tf INTO this module, gated by feature flags.

Why: prod/main.tf had cross-repo ../../../core/... refs that only resolved on the deprecated mgmt VM 110. K8s Forgejo runner (HOMELAB-988) couldn't plan because of them. Module fetch downloads the entire infra-core repo into .terraform/modules/cluster/, so reading values from ${path.module}/../../../charts/platform/.../values.yaml resolves cleanly AND reads the same single file ArgoCD reconciles from steady-state.

No state migration in this PR — that lands with the prod-side simplification PR.

Key safety wires (from 3-specialist design review):

  • prevent_destroy=true + ignore_changes=all + server_side_apply=true on root-app kubectl_manifest (defends against state-mv mistakes that would cascade to deleting all child Applications)
  • null_resource triggers DON'T use path.module (otherwise different absolute paths between local and module-fetched contexts force re-runs)
  • Providers stay configured in parent (chicken-and-egg with kubeconfig output)
  • All resources behind feature flags, defaulted false (preserves module reusability)
First PR of two for HOMELAB-990. Moves the Cilium + ArgoCD helm bootstrap (and root-app kubectl_manifest, kubeconfig file, wait_for_nodes) from prod/terraform/main.tf INTO this module, gated by feature flags. Why: prod/main.tf had cross-repo `../../../core/...` refs that only resolved on the deprecated mgmt VM 110. K8s Forgejo runner (HOMELAB-988) couldn't plan because of them. Module fetch downloads the entire infra-core repo into `.terraform/modules/cluster/`, so reading values from `${path.module}/../../../charts/platform/.../values.yaml` resolves cleanly AND reads the same single file ArgoCD reconciles from steady-state. No state migration in this PR — that lands with the prod-side simplification PR. Key safety wires (from 3-specialist design review): - `prevent_destroy=true` + `ignore_changes=all` + `server_side_apply=true` on root-app kubectl_manifest (defends against state-mv mistakes that would cascade to deleting all child Applications) - null_resource triggers DON'T use path.module (otherwise different absolute paths between local and module-fetched contexts force re-runs) - Providers stay configured in parent (chicken-and-egg with kubeconfig output) - All resources behind feature flags, defaulted false (preserves module reusability)
HOMELAB-990: feat(talos-cluster): bring bootstrap helm_releases into module
Some checks failed
0/0 projects applied successfully.
CI Review / pr-title (pull_request) Has been cancelled
CI Review / helm-validate (pull_request) Has been cancelled
CI Review / ai-review (pull_request) Has been cancelled
Lint & Validate / terraform-validate (pull_request) Has been cancelled
Lint & Validate / yaml-lint (pull_request) Has been cancelled
Lint & Validate / shellcheck (pull_request) Has been cancelled
ad329ca444
Moves Cilium + ArgoCD bootstrap helm_release, the wait_for_nodes
null_resource, the kubeconfig local_file, and the root ArgoCD
Application kubectl_manifest from prod/terraform/main.tf INTO this
module. All gated behind feature flags (default false) so the module
remains reusable for scratch / dev / future-second-cluster workspaces.

Why this exists: prod/terraform/main.tf historically referenced these
chart values + the wait-for-nodes script via cross-repo relative paths
(`../../../core/...`) that only resolved when prod and infra-core were
sibling directories on disk — i.e. only on the now-deprecated mgmt VM
110. The K8s Forgejo runner (HOMELAB-988) needs a clean module-fetch
path with no sibling-checkout dance. Atlantis benefits transitively.

Source-of-truth preservation: when this module is fetched as a git
source, the entire infra-core repo materializes inside
`.terraform/modules/cluster/`. The new helm_releases read from
`${path.module}/../../../charts/platform/X/values.yaml` — the SAME
file ArgoCD's steady-state Applications read. No fork, no drift bomb.

Risks the design defends against:

  - Bad state mv on the root-app kubectl_manifest cascading to
    deletion of every child Application: prevent_destroy = true +
    ignore_changes = all + server_side_apply.
  - ArgoCD reinstalling cilium (taking the CNI down): preserved release
    name + namespace match the existing ArgoCD Application; helm
    release adoption works because the new module produces the same
    release identity that ArgoCD looks up from release-history Secrets.
  - Chart-version skew between TF and ArgoCD Application:
    cilium_chart_version + argocd_chart_version must match the
    ArgoCD Application targetRevision. Will guard with a CI check in
    a follow-up ticket; pre-flight verified equal today (1.16.5 +
    7.7.10 on both sides).
  - null_resource trigger forced re-run: triggers rewritten to NOT
    use path.module; uses node count + kubeconfig sha256 + a
    script_version literal instead.

Providers stay configured in the parent (helm/kubernetes/kubectl all
depend on this module's kubeconfig_raw output — chicken-and-egg if
they were configured here). Module declares required_providers but
not configuration_aliases; the caller passes one helm/kubernetes/
kubectl provider via the standard providers={} block.

New variables (all default false / sane pin):

  enable_cilium_bootstrap, enable_argocd_bootstrap, enable_root_app,
  enable_kubeconfig_output_file, enable_wait_for_nodes,
  cilium_namespace (default "kube-system"; HOMELAB-995 will reconcile
  the cilium-system drift), cilium_chart_version, cilium_values_file,
  argocd_namespace, argocd_chart_version, argocd_values_file,
  root_app_manifest_path, kubeconfig_output_path,
  wait_for_nodes_timeout.

New output: bootstrap_complete (id of the last-applied bootstrap
resource; chains downstream depends_on).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aaron merged commit 2fee10151f into live 2026-04-26 06:24:08 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aaron/infra-core!192
No description provided.