mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 17:11:30 +00:00
100 lines
2.9 KiB
Go
100 lines
2.9 KiB
Go
// lb-agent runs inside load balancer VMs and manages HAProxy configuration.
|
|
//
|
|
// It polls the AWS gateway for config updates and reports health via heartbeats.
|
|
// All communication uses SigV4-signed HTTP requests.
|
|
//
|
|
// Usage:
|
|
//
|
|
// lb-agent --lb-id=lb-xxxxx --gateway=https://192.168.1.33:9999 --access-key=AKIA... --secret-key=...
|
|
//
|
|
// Flags default to environment variables set by cloud-init:
|
|
// LB_LB_ID, LB_GATEWAY_URL, LB_ACCESS_KEY, LB_SECRET_KEY, LB_REGION.
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log/slog"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"github.com/mulgadc/bluebottle/pkg/otelsetup"
|
|
"github.com/mulgadc/spinifex/spinifex/lbagent"
|
|
|
|
_ "github.com/mulgadc/bluebottle/pkg/fipsboot"
|
|
)
|
|
|
|
func main() {
|
|
// Without this the agent falls back to slog's default text handler, which folds
|
|
// attributes into the message so the console scraper recovers a level and nothing
|
|
// else. No OTLP export: the agent's only egress is the gateway it is watching.
|
|
otelsetup.SetDefaultJSONLogger("lb-agent", slog.LevelInfo)
|
|
|
|
var (
|
|
lbID string
|
|
gatewayURL string
|
|
accessKey string
|
|
secretKey string
|
|
region string
|
|
)
|
|
|
|
hostname, _ := os.Hostname()
|
|
|
|
flag.StringVar(&lbID, "lb-id", envOrDefault("LB_LB_ID", hostname), "Load balancer ID")
|
|
flag.StringVar(&gatewayURL, "gateway", os.Getenv("LB_GATEWAY_URL"), "Gateway URL (e.g. https://192.168.1.33:9999)")
|
|
flag.StringVar(&accessKey, "access-key", os.Getenv("LB_ACCESS_KEY"), "AWS access key ID")
|
|
flag.StringVar(&secretKey, "secret-key", os.Getenv("LB_SECRET_KEY"), "AWS secret access key")
|
|
flag.StringVar(®ion, "region", envOrDefault("LB_REGION", "us-east-1"), "AWS region for SigV4 signing")
|
|
flag.Parse()
|
|
|
|
if lbID == "" {
|
|
slog.Error("--lb-id is required (or set LB_LB_ID)")
|
|
os.Exit(1)
|
|
}
|
|
if gatewayURL == "" {
|
|
slog.Error("--gateway is required (or set LB_GATEWAY_URL)")
|
|
os.Exit(1)
|
|
}
|
|
// Empty keys select IMDS instance-role credentials (the SDK default chain
|
|
// falls back to the in-VM IMDS endpoint); static keys sign as-is.
|
|
credSource := "imds"
|
|
if accessKey != "" && secretKey != "" {
|
|
credSource = "static"
|
|
}
|
|
slog.Info("Starting LB agent", "lbId", lbID, "gateway", gatewayURL, "credSource", credSource)
|
|
|
|
agent, err := lbagent.New(lbID, gatewayURL, accessKey, secretKey, region)
|
|
if err != nil {
|
|
slog.Error("Failed to create agent", "err", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Start poll loop in a goroutine — it blocks until Stop is called.
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
if err := agent.Start(); err != nil {
|
|
errCh <- err
|
|
}
|
|
}()
|
|
|
|
// Wait for shutdown signal or fatal error.
|
|
sigCh := make(chan os.Signal, 1)
|
|
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
select {
|
|
case sig := <-sigCh:
|
|
slog.Info("Received signal, shutting down", "signal", sig)
|
|
case err := <-errCh:
|
|
slog.Error("Agent error", "err", err)
|
|
}
|
|
|
|
agent.Stop()
|
|
}
|
|
|
|
func envOrDefault(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|