package config // defaults runs one orchestration or CLI step. // Signature: defaults() Config. // Why: keeps behavior explicit so startup/shutdown workflows remain maintainable as services evolve. func defaults() Config { c := Config{ IACRepoPath: "/opt/titan-iac", ExpectedFluxBranch: "main", ExpectedFluxSource: "ssh://git@scm.bstein.dev:2242/bstein/titan-iac.git", SSHPort: 2277, ControlPlanes: []string{"titan-0a", "titan-0b", "titan-0c"}, LocalBootstrapPaths: []string{ "infrastructure/core", "clusters/atlas/flux-system", "infrastructure/sources/helm", "infrastructure/metallb", "infrastructure/traefik", "infrastructure/cert-manager", "infrastructure/vault-csi", "infrastructure/vault-injector", "services/vault", "infrastructure/postgres", "services/gitea", "services/keycloak", "services/oauth2-proxy", }, ExcludedNamespaces: []string{ "kube-system", "kube-public", "kube-node-lease", "flux-system", "traefik", "metallb-system", "cert-manager", "longhorn-system", "vault", "postgres", "maintenance", }, Startup: Startup{ APIWaitSeconds: 1200, APIPollSeconds: 2, ShutdownCooldownSeconds: 45, RequireNodeInventoryReach: true, NodeInventoryReachWaitSeconds: 300, NodeInventoryReachPollSeconds: 5, RequireTimeSync: true, TimeSyncWaitSeconds: 240, TimeSyncPollSeconds: 5, TimeSyncMode: "quorum", TimeSyncQuorum: 2, ReconcileAccessOnBoot: true, AutoEtcdRestoreOnAPIFailure: true, EtcdRestoreControlPlane: "titan-0a", RequireStorageReady: true, StorageReadyWaitSeconds: 420, StorageReadyPollSeconds: 5, StorageMinReadyNodes: 2, StorageCriticalPVCs: []string{ "vault/data-vault-0", "postgres/postgres-data-postgres-0", "gitea/gitea-data", "sso/keycloak-data", }, MinimumBatteryPercent: 20, RequiredNodeLabels: map[string]map[string]string{ "titan-09": { "ananke.bstein.dev/harbor-bootstrap": "true", }, }, RequirePostStartProbes: true, PostStartProbeWaitSeconds: 240, PostStartProbePollSeconds: 5, PostStartProbes: []string{ "https://sso.bstein.dev/realms/atlas/.well-known/openid-configuration", "https://scm.bstein.dev/api/healthz", "https://metrics.bstein.dev/api/health", }, RequireServiceChecklist: true, ServiceChecklistWaitSeconds: 420, ServiceChecklistPollSeconds: 5, ServiceChecklistStabilitySec: 120, ServiceChecklistAuth: ServiceChecklistAuthSettings{ Mode: "keycloak_robotuser", KeycloakBaseURL: "https://sso.bstein.dev", Realm: "atlas", RobotUsername: "robotuser", AdminSecretNamespace: "sso", AdminSecretName: "keycloak-admin", AdminSecretUsernameKey: "username", AdminSecretPasswordKey: "password", }, ServiceChecklist: defaultServiceChecklist(), RequireCriticalServiceEndpoints: true, CriticalServiceEndpointWaitSec: 420, CriticalServiceEndpointPollSec: 5, CriticalServiceEndpoints: defaultCriticalServiceEndpoints(), RequireIngressChecklist: true, IngressChecklistWaitSeconds: 420, IngressChecklistPollSeconds: 5, IngressChecklistAccepted: []int{200, 301, 302, 307, 308, 401, 403, 404}, IngressChecklistIgnoreHosts: []string{}, RequireNodeSSHAuth: true, NodeSSHAuthWaitSeconds: 240, NodeSSHAuthPollSeconds: 5, RequireFluxHealth: true, FluxHealthWaitSeconds: 900, FluxHealthPollSeconds: 5, IgnoreFluxKustomizations: []string{}, RequireWorkloadConvergence: true, WorkloadConvergenceWaitSeconds: 900, WorkloadConvergencePollSeconds: 5, IgnoreWorkloadNamespaces: []string{}, IgnoreWorkloads: []string{}, IgnoreUnavailableNodes: []string{}, AutoRecycleStuckPods: true, StuckPodGraceSeconds: 180, VaultUnsealKeyFile: "/var/lib/ananke/vault-unseal.key", VaultUnsealBreakglassTimeout: 15, }, Shutdown: Shutdown{ DefaultBudgetSeconds: 1380, HistoryMinSamples: 3, EmergencyBudgetSec: 420, EmergencyMinSamples: 3, EmergencySkipEtcd: true, EmergencySkipDrain: true, DrainParallelism: 6, ScaleParallelism: 8, SSHParallelism: 8, }, UPS: UPS{ Enabled: true, Provider: "nut", PollSeconds: 5, RuntimeSafetyFactor: 1.25, DebounceCount: 3, TelemetryTimeoutSeconds: 90, }, Coordination: Coordination{ ForwardShutdownConfig: "/etc/ananke/ananke.yaml", PeerHosts: []string{}, FallbackLocalShutdown: true, CommandTimeoutSeconds: 25, StartupGuardMaxAgeSec: 900, Role: "coordinator", AllowStartupOnBattery: false, }, Metrics: Metrics{ Enabled: true, BindAddr: "0.0.0.0:9560", Path: "/metrics", }, State: State{ Dir: "/var/lib/ananke", ReportsDir: "/var/lib/ananke/reports", RunHistoryPath: "/var/lib/ananke/runs.json", LockPath: "/var/lib/ananke/ananke.lock", IntentPath: "/var/lib/ananke/intent.json", }, } c.applyDefaults() return c }