From 965cc033dbc3f0008e59c9eb023e05221384ffe5 Mon Sep 17 00:00:00 2001 From: Roman Leventov Date: Mon, 10 Aug 2020 11:14:12 +0200 Subject: [PATCH] Add BindEnvSliceValue() # Conflicts: # viper.go --- viper.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/viper.go b/viper.go index f900e58..f7cb313 100644 --- a/viper.go +++ b/viper.go @@ -174,6 +174,7 @@ type Viper struct { kvstore map[string]any pflags map[string]FlagValue env map[string][]string + envSliceValues map[string]bool aliases map[string]string typeByDefValue bool @@ -204,6 +205,7 @@ func New() *Viper { v.kvstore = make(map[string]any) v.pflags = make(map[string]FlagValue) v.env = make(map[string][]string) + v.envSliceValues = make(map[string]bool) v.aliases = make(map[string]string) v.typeByDefValue = false v.logger = slog.New(&discardHandler{}) @@ -1103,6 +1105,7 @@ func (v *Viper) BindFlagValue(key string, flag FlagValue) error { // If more arguments are provided, they will represent the env variable names that // should bind to this key and will be taken in the specified order. // EnvPrefix will be used when set when env name is not provided. +// Use BindEnvSliceValue() for binding slice variables. func BindEnv(input ...string) error { return v.BindEnv(input...) } func (v *Viper) BindEnv(input ...string) error { @@ -1132,6 +1135,20 @@ func (v *Viper) MustBindEnv(input ...string) { } } +// BindEnvSliceValue is identical to BindEnv but converts the value of the environment variable into +// a slice using strings.Fields(), e. g. variable with value " a b" is converted into ["a", "b"]. +func BindEnvSliceValue(input ...string) error { return v.BindEnvSliceValue(input...) } +func (v *Viper) BindEnvSliceValue(input ...string) error { + if len(input) == 0 { + return fmt.Errorf("missing key to bind to") + } + + key := strings.ToLower(input[0]) + _ = v.BindEnv(input...) + v.envSliceValues[key] = true + return nil +} + // Given a key, find the value. // // Viper will check to see if an alias exists first. @@ -1209,6 +1226,9 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) any { // even if it hasn't been registered, if automaticEnv is used, // check any Get request if val, ok := v.getEnv(v.mergeWithEnvPrefix(envKey)); ok { + if v.envSliceValues[envKey] { + return strings.Fields(val) + } return val } if nested && v.isPathShadowedInAutoEnv(path) != "" { @@ -1219,6 +1239,9 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) any { if exists { for _, envkey := range envkeys { if val, ok := v.getEnv(envkey); ok { + if v.envSliceValues[envkey] { + return strings.Fields(val) + } return val } } @@ -2025,6 +2048,7 @@ func (v *Viper) DebugTo(w io.Writer) { fmt.Fprintf(w, "Override:\n%#v\n", v.override) fmt.Fprintf(w, "PFlags:\n%#v\n", v.pflags) fmt.Fprintf(w, "Env:\n%#v\n", v.env) + fmt.Fprintf(w, "Env Slice Values:\n%#v\n", v.envSliceValues) fmt.Fprintf(w, "Key/Value Store:\n%#v\n", v.kvstore) fmt.Fprintf(w, "Config:\n%#v\n", v.config) fmt.Fprintf(w, "Defaults:\n%#v\n", v.defaults)