mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-20 16:40:29 +00:00
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
package config
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-viper/mapstructure/v2"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// NewViper creates a configured Viper instance with common settings.
|
|
// prefix is the env var prefix (e.g., "ATCR" or "HOLD").
|
|
// yamlPath is the optional YAML config file path (empty = env-only).
|
|
func NewViper(prefix string, yamlPath string) *viper.Viper {
|
|
v := viper.New()
|
|
|
|
// Env prefix: ATCR_ or HOLD_
|
|
v.SetEnvPrefix(prefix)
|
|
|
|
// Map YAML dots/dashes to env underscores: server.base_url -> ATCR_SERVER_BASE_URL
|
|
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
|
|
|
|
// Enable automatic env var binding
|
|
v.AutomaticEnv()
|
|
|
|
// Bind shared log shipper env vars (no service prefix)
|
|
BindLogShipper(v)
|
|
|
|
// Load YAML config file if provided
|
|
if yamlPath != "" {
|
|
v.SetConfigFile(yamlPath)
|
|
// Ignore missing file — env-only is valid
|
|
_ = v.ReadInConfig()
|
|
}
|
|
|
|
return v
|
|
}
|
|
|
|
// BindLogShipper registers BindEnv calls for shared (unprefixed) log shipper env vars.
|
|
func BindLogShipper(v *viper.Viper) {
|
|
_ = v.BindEnv("log_shipper.backend", "LOG_SHIPPER_BACKEND")
|
|
_ = v.BindEnv("log_shipper.url", "LOG_SHIPPER_URL")
|
|
_ = v.BindEnv("log_shipper.batch_size", "LOG_SHIPPER_BATCH_SIZE")
|
|
_ = v.BindEnv("log_shipper.flush_interval", "LOG_SHIPPER_FLUSH_INTERVAL")
|
|
_ = v.BindEnv("log_shipper.username", "LOG_SHIPPER_USERNAME")
|
|
_ = v.BindEnv("log_shipper.password", "LOG_SHIPPER_PASSWORD")
|
|
}
|
|
|
|
// UnmarshalOption returns the Viper decoder option that uses yaml struct tags
|
|
// and supports time.Duration string parsing.
|
|
func UnmarshalOption() viper.DecoderConfigOption {
|
|
return viper.DecoderConfigOption(func(dc *mapstructure.DecoderConfig) {
|
|
dc.TagName = "yaml"
|
|
dc.DecodeHook = mapstructure.ComposeDecodeHookFunc(
|
|
dc.DecodeHook,
|
|
StringToTimeDurationHook(),
|
|
)
|
|
})
|
|
}
|
|
|
|
// StringToTimeDurationHook returns a mapstructure DecodeHookFunc that converts
|
|
// string values to time.Duration. This handles env vars like "15m" or "5s".
|
|
func StringToTimeDurationHook() mapstructure.DecodeHookFunc {
|
|
return func(from reflect.Type, to reflect.Type, data any) (any, error) {
|
|
if from.Kind() != reflect.String {
|
|
return data, nil
|
|
}
|
|
if to != reflect.TypeOf(time.Duration(0)) {
|
|
return data, nil
|
|
}
|
|
|
|
s := data.(string)
|
|
if s == "" {
|
|
return time.Duration(0), nil
|
|
}
|
|
|
|
return time.ParseDuration(s)
|
|
}
|
|
}
|