package cluster import "strings" // 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 // without losing the stricter all-nodes behavior when no override is configured. func startupRequiredNodes(nodes []string, required []string) []string { requiredSet := makeStringSet(required) if len(requiredSet) == 0 { return nodes } filtered := make([]string, 0, len(nodes)) for _, node := range nodes { node = strings.TrimSpace(node) if node == "" { continue } if _, ok := requiredSet[node]; ok { filtered = append(filtered, node) } } return filtered } // startupNodeStrictlyRequired runs one orchestration or CLI step. // Signature: (o *Orchestrator) startupNodeStrictlyRequired(node string) bool. // Why: absent or broken non-core nodes should not block recovery-only actions // like label reconciliation once the operator has narrowed startup to core nodes. func (o *Orchestrator) startupNodeStrictlyRequired(node string) bool { node = strings.TrimSpace(node) if node == "" { return false } if len(o.cfg.Startup.NodeInventoryReachRequiredNodes) == 0 && len(o.cfg.Startup.NodeSSHAuthRequiredNodes) == 0 { return true } for _, controlPlane := range o.cfg.ControlPlanes { if strings.TrimSpace(controlPlane) == node { return true } } if containsNode(o.cfg.Startup.NodeInventoryReachRequiredNodes, node) { return true } return containsNode(o.cfg.Startup.NodeSSHAuthRequiredNodes, node) } // startupRequiredFluxKustomizations runs one orchestration or CLI step. // Signature: (o *Orchestrator) startupRequiredFluxKustomizations() map[string]struct{}. // 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) } // startupRequiredWorkloadNamespaces runs one orchestration or CLI step. // Signature: (o *Orchestrator) startupRequiredWorkloadNamespaces() map[string]struct{}. // Why: keeps workload readiness scoped to core namespaces during recovery while // preserving broad convergence checks when no explicit core list is configured. func (o *Orchestrator) startupRequiredWorkloadNamespaces() map[string]struct{} { return makeStringSet(o.cfg.Startup.WorkloadConvergenceRequiredNamespaces) } // containsNode runs one orchestration or CLI step. // Signature: containsNode(entries []string, needle string) bool. // Why: keeps node-scope checks small and explicit anywhere startup narrows its // recovery gates to a declared core set. func containsNode(entries []string, needle string) bool { needle = strings.TrimSpace(needle) if needle == "" { return false } for _, entry := range entries { if strings.TrimSpace(entry) == needle { return true } } return false }