From 54f0b29bce7356b662626690657f737181244fe6 Mon Sep 17 00:00:00 2001 From: codex Date: Thu, 18 Jun 2026 23:42:29 -0300 Subject: [PATCH] recovery: require flux bootstrap health --- internal/cluster/orchestrator_startup_scope.go | 9 ++++++++- testing/orchestrator/hooks_flux_workload_matrix_test.go | 1 + testing/orchestrator/hooks_startup_scope_vault_test.go | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/internal/cluster/orchestrator_startup_scope.go b/internal/cluster/orchestrator_startup_scope.go index 7b6c515..eb0039b 100644 --- a/internal/cluster/orchestrator_startup_scope.go +++ b/internal/cluster/orchestrator_startup_scope.go @@ -2,6 +2,8 @@ package cluster import "strings" +const fluxSystemSelfKustomization = "flux-system/flux-system" + // startupRequiredNodes runs one orchestration or CLI step. // Signature: startupRequiredNodes(nodes []string, required []string) []string. // Why: lets startup enforce a smaller core node set during outage recovery @@ -52,7 +54,12 @@ func (o *Orchestrator) startupNodeStrictlyRequired(node string) bool { // Why: lets outage recovery wait on a declared core GitOps slice while leaving // optional stacks free to converge after bootstrap succeeds. func (o *Orchestrator) startupRequiredFluxKustomizations() map[string]struct{} { - return makeStringSet(o.cfg.Startup.FluxHealthRequiredKustomizations) + required := makeStringSet(o.cfg.Startup.FluxHealthRequiredKustomizations) + ignored := makeStringSet(o.cfg.Startup.IgnoreFluxKustomizations) + if _, ok := ignored[fluxSystemSelfKustomization]; !ok { + required[fluxSystemSelfKustomization] = struct{}{} + } + return required } // startupRequiredWorkloadNamespaces runs one orchestration or CLI step. diff --git a/testing/orchestrator/hooks_flux_workload_matrix_test.go b/testing/orchestrator/hooks_flux_workload_matrix_test.go index 4f93ecb..57f0341 100644 --- a/testing/orchestrator/hooks_flux_workload_matrix_test.go +++ b/testing/orchestrator/hooks_flux_workload_matrix_test.go @@ -89,6 +89,7 @@ func TestHookFluxAndWorkloadMatrix(t *testing.T) { case name == "kubectl" && strings.Contains(command, "get kustomizations.kustomize.toolkit.fluxcd.io -A -o json"): return `{"items":[ {"metadata":{"namespace":"flux-system","name":"monitoring"},"spec":{"suspend":false},"status":{"conditions":[{"type":"Ready","status":"True","message":"ok"}]}}, +{"metadata":{"namespace":"flux-system","name":"flux-system"},"spec":{"suspend":false},"status":{"conditions":[{"type":"Ready","status":"True","message":"ok"}]}}, {"metadata":{"namespace":"flux-system","name":"jellyfin"},"spec":{"suspend":false},"status":{"conditions":[{"type":"Ready","status":"False","message":"optional still down"}]}} ]}`, nil default: diff --git a/testing/orchestrator/hooks_startup_scope_vault_test.go b/testing/orchestrator/hooks_startup_scope_vault_test.go index 6d9b0fe..a743874 100644 --- a/testing/orchestrator/hooks_startup_scope_vault_test.go +++ b/testing/orchestrator/hooks_startup_scope_vault_test.go @@ -78,6 +78,15 @@ func TestHookStartupScopeAndVaultHelpers(t *testing.T) { if _, ok := flux["flux-system/gitea"]; !ok { t.Fatalf("expected trimmed gitea kustomization in required set: %v", flux) } + if _, ok := flux["flux-system/flux-system"]; !ok { + t.Fatalf("expected Flux bootstrap kustomization in required set: %v", flux) + } + + cfgScoped.Startup.IgnoreFluxKustomizations = []string{"flux-system/flux-system"} + orchIgnoredFluxSelf, _ := newHookOrchestrator(t, cfgScoped, nil, nil) + if _, ok := orchIgnoredFluxSelf.TestHookStartupRequiredFluxKustomizations()["flux-system/flux-system"]; ok { + t.Fatalf("expected explicit ignore to remove Flux bootstrap kustomization from required set") + } namespaces := orchScoped.TestHookStartupRequiredWorkloadNamespaces() if _, ok := namespaces["vault"]; !ok {