package config import ( "context" "flag" "fmt" "os" "runtime/debug" "github.com/caarlos0/env/v9" "gopkg.in/yaml.v3" ) // To be set by ldflags in go build command or // retrieved from build meta below var Version = "(devel)" // Calling this will try to load from config if -config is // provided as a file, and will apply any environment overrides // on-top of configuration defaults. // Config is stored in returned context, and can be retrieved // using config.FromCtx(ctx) func LoadConfig(ctx context.Context) (context.Context, error) { configPath := flag.String("config", "", "Path to the configuration file") flag.Parse() // Start with defaults // Load from config if provided // Layer on environment cfg, err := loadConfig(*configPath) if err != nil { return ctx, err } // Add config to context, and return // an updated context ctx = cfg.AddToCtx(ctx) return ctx, nil } func loadConfig(configPath string) (*AppConfig, error) { cfg := newAppConfig() if configPath != "" { file, err := os.Open(configPath) if err != nil { return nil, fmt.Errorf("could not open config file: %w", err) } defer file.Close() decoder := yaml.NewDecoder(file) if err := decoder.Decode(cfg); err != nil { return nil, fmt.Errorf("could not decode config file: %w", err) } } if err := env.Parse(cfg); err != nil { return nil, fmt.Errorf("could not parse environment variables: %w", err) } return cfg, nil } func getVersion() string { if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "(devel)" { return info.Main.Version } return Version }