79 lines
2.5 KiB
Go
79 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"scm.bstein.dev/bstein/ananke/internal/cluster"
|
|
"scm.bstein.dev/bstein/ananke/internal/config"
|
|
"scm.bstein.dev/bstein/ananke/internal/execx"
|
|
"scm.bstein.dev/bstein/ananke/internal/state"
|
|
)
|
|
|
|
// buildOrchestrator runs one orchestration or CLI step.
|
|
// Signature: buildOrchestrator(logger *log.Logger, cfgPath string, dryRun bool) (config.Config, *cluster.Orchestrator, error).
|
|
// Why: keeps behavior explicit so startup/shutdown workflows remain maintainable as services evolve.
|
|
func buildOrchestrator(logger *log.Logger, cfgPath string, dryRun bool) (config.Config, *cluster.Orchestrator, error) {
|
|
cfg, err := config.LoadWithFragments(cfgPath, configFragmentPaths(cfgPath)...)
|
|
if err != nil {
|
|
return config.Config{}, nil, err
|
|
}
|
|
if err := state.EnsureDir(cfg.State.Dir); err != nil {
|
|
return config.Config{}, nil, err
|
|
}
|
|
if err := state.EnsureDir(cfg.State.ReportsDir); err != nil {
|
|
return config.Config{}, nil, err
|
|
}
|
|
runner := &execx.Runner{
|
|
DryRun: dryRun,
|
|
Kubeconfig: cfg.Kubeconfig,
|
|
Logger: logger,
|
|
}
|
|
store := state.New(cfg.State.RunHistoryPath)
|
|
orch := cluster.New(cfg, runner, store, logger)
|
|
return cfg, orch, nil
|
|
}
|
|
|
|
// configFragmentPaths runs one orchestration or CLI step.
|
|
// Signature: configFragmentPaths(cfgPath string) []string.
|
|
// Why: keeps generated inventory overlays discoverable without changing every
|
|
// systemd command line or recovery script invocation.
|
|
func configFragmentPaths(cfgPath string) []string {
|
|
paths := []string{}
|
|
if env := strings.TrimSpace(os.Getenv("ANANKE_CONFIG_FRAGMENTS")); env != "" {
|
|
for _, path := range filepath.SplitList(env) {
|
|
path = strings.TrimSpace(path)
|
|
if path != "" {
|
|
paths = append(paths, path)
|
|
}
|
|
}
|
|
}
|
|
defaultPath := defaultInventoryFragmentPath(cfgPath)
|
|
if defaultPath != "" {
|
|
if _, err := os.Stat(defaultPath); err == nil {
|
|
paths = append(paths, defaultPath)
|
|
}
|
|
}
|
|
return paths
|
|
}
|
|
|
|
// defaultInventoryFragmentPath runs one orchestration or CLI step.
|
|
// Signature: defaultInventoryFragmentPath(cfgPath string) string.
|
|
// Why: pairs ananke.yaml with an adjacent Terraform-generated inventory
|
|
// fragment using a deterministic host-local convention.
|
|
func defaultInventoryFragmentPath(cfgPath string) string {
|
|
dir := filepath.Dir(cfgPath)
|
|
base := filepath.Base(cfgPath)
|
|
ext := filepath.Ext(base)
|
|
name := strings.TrimSuffix(base, ext)
|
|
if name == "" {
|
|
return ""
|
|
}
|
|
if ext == "" {
|
|
return filepath.Join(dir, name+".inventory.yaml")
|
|
}
|
|
return filepath.Join(dir, name+".inventory"+ext)
|
|
}
|