81 lines
2.4 KiB
Go
81 lines
2.4 KiB
Go
// Package config reads the service's settings from the environment.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Config is the whole configuration surface. Environment only: a control plane is deployed, not
|
|
// hand-run, and a settings file is one more thing to keep in sync with the deployment.
|
|
type Config struct {
|
|
Addr string
|
|
// DSN is the Postgres connection string. Empty is allowed and means "start unready": the
|
|
// service answers liveness and reports on /readyz why it cannot serve.
|
|
//
|
|
// ⚠ It carries a password. It is read from the environment, never logged, and never echoed
|
|
// into an error message.
|
|
DSN string
|
|
// TrustedOrigins are origins besides our own that may make unsafe requests.
|
|
TrustedOrigins []string
|
|
// SessionIdleTTL is how long a session survives without use; SessionMaxAge is the ceiling no
|
|
// amount of use can extend.
|
|
SessionIdleTTL time.Duration
|
|
SessionMaxAge time.Duration
|
|
// Migrate applies pending migrations at boot. Off by default: a rollout should migrate once,
|
|
// deliberately, not once per replica.
|
|
Migrate bool
|
|
}
|
|
|
|
// Load reads the environment.
|
|
func Load() (Config, error) {
|
|
c := Config{
|
|
Addr: env("TM_PLATFORM_ADDR", "127.0.0.1:8080"),
|
|
DSN: os.Getenv("TM_PLATFORM_DSN"),
|
|
SessionIdleTTL: 14 * 24 * time.Hour,
|
|
SessionMaxAge: 90 * 24 * time.Hour,
|
|
Migrate: os.Getenv("TM_PLATFORM_MIGRATE") == "1",
|
|
}
|
|
if raw := os.Getenv("TM_PLATFORM_TRUSTED_ORIGINS"); raw != "" {
|
|
for _, o := range strings.Split(raw, ",") {
|
|
if o = strings.TrimSpace(o); o != "" {
|
|
c.TrustedOrigins = append(c.TrustedOrigins, o)
|
|
}
|
|
}
|
|
}
|
|
var err error
|
|
if c.SessionIdleTTL, err = duration("TM_PLATFORM_SESSION_IDLE", c.SessionIdleTTL); err != nil {
|
|
return Config{}, err
|
|
}
|
|
if c.SessionMaxAge, err = duration("TM_PLATFORM_SESSION_MAX_AGE", c.SessionMaxAge); err != nil {
|
|
return Config{}, err
|
|
}
|
|
if c.SessionIdleTTL > c.SessionMaxAge {
|
|
return Config{}, fmt.Errorf("config: session idle TTL %s exceeds max age %s", c.SessionIdleTTL, c.SessionMaxAge)
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func env(key, def string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
|
|
func duration(key string, def time.Duration) (time.Duration, error) {
|
|
raw := os.Getenv(key)
|
|
if raw == "" {
|
|
return def, nil
|
|
}
|
|
d, err := time.ParseDuration(raw)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("config: %s: %w", key, err)
|
|
}
|
|
if d <= 0 {
|
|
return 0, fmt.Errorf("config: %s must be positive", key)
|
|
}
|
|
return d, nil
|
|
}
|