diff --git a/spindle/config/config.go b/spindle/config/config.go index 661e35f7..bd4aa3e5 100644 --- a/spindle/config/config.go +++ b/spindle/config/config.go @@ -2,6 +2,7 @@ package config import ( "context" + "fmt" "time" "github.com/bluesky-social/indigo/atproto/syntax" @@ -93,12 +94,49 @@ type NixCache struct { UploadURL string `env:"UPLOAD_URL"` } +// Role selects the spindle mode. set explicitly via SPINDLE_ROLE. +type Role string + +const ( + RoleStandalone Role = "standalone" + RoleMill Role = "mill" + RoleExecutor Role = "executor" +) + +// Mill config is shared by all roles; which fields matter depends on Role. +type Mill struct { + URL string `env:"URL"` // mill websocket endpoint (executor) + SharedSecret string `env:"SHARED_SECRET"` // executor bearer token; mill dev bootstrap seed + MaxPending int `env:"MAX_PENDING, default=100"` // mill: pending job cap + ReconnectGrace time.Duration `env:"RECONNECT_GRACE, default=45s"` // mill: reconnect window before failing leases + Seats int `env:"SEATS, default=4"` // executor: seat count advertised to the mill + Labels []string `env:"LABELS"` // executor: runs_on labels +} + type Config struct { + Role Role `env:"SPINDLE_ROLE, default=standalone"` Server Server `env:",prefix=SPINDLE_SERVER_"` NixeryPipelines NixeryPipelines `env:",prefix=SPINDLE_NIXERY_PIPELINES_"` MicroVMPipelines MicroVMPipelines `env:",prefix=SPINDLE_MICROVM_PIPELINES_"` NixCache NixCache `env:",prefix=SPINDLE_NIX_CACHE_"` S3 S3 `env:",prefix=SPINDLE_S3_"` + Mill Mill `env:",prefix=SPINDLE_MILL_"` +} + +func (c *Config) validate() error { + switch c.Role { + case RoleStandalone, RoleMill: + if c.Mill.URL != "" { + return fmt.Errorf("SPINDLE_MILL_URL is set but SPINDLE_ROLE=%s; only an executor dials a mill", c.Role) + } + case RoleExecutor: + if c.Mill.URL == "" { + return fmt.Errorf("SPINDLE_ROLE=executor requires SPINDLE_MILL_URL (the mill to dial)") + } + default: + return fmt.Errorf("unknown SPINDLE_ROLE %q (want standalone, mill, or executor)", c.Role) + } + return nil } func Load(ctx context.Context) (*Config, error) { @@ -107,6 +145,9 @@ func Load(ctx context.Context) (*Config, error) { if err != nil { return nil, err } + if err := cfg.validate(); err != nil { + return nil, err + } return &cfg, nil }