From 4f59047658836fc8e6113fe910fbf4c5a0e962be Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Tue, 6 Nov 2018 20:20:07 +0100 Subject: [PATCH] Add AllowEmptyEnv method to preserve backard compatibility --- README.md | 7 ++++++- viper.go | 14 +++++++++++++- viper_test.go | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 64bf474..8da6a93 100644 --- a/README.md +++ b/README.md @@ -179,13 +179,14 @@ viper.GetBool("verbose") // true ### Working with Environment Variables Viper has full support for environment variables. This enables 12 factor -applications out of the box. There are four methods that exist to aid working +applications out of the box. There are five methods that exist to aid working with ENV: * `AutomaticEnv()` * `BindEnv(string...) : error` * `SetEnvPrefix(string)` * `SetEnvKeyReplacer(string...) *strings.Replacer` + * `AllowEmptyEnvVar(bool)` _When working with ENV variables, it’s important to recognize that Viper treats ENV variables as case sensitive._ @@ -217,6 +218,10 @@ keys to an extent. This is useful if you want to use `-` or something in your `Get()` calls, but want your environmental variables to use `_` delimiters. An example of using it can be found in `viper_test.go`. +By default empty environment variables are considered unset and will fall back to +the next configuration source. To treat empty environment variables as set, use +the `AllowEmptyEnv` method. + #### Env example ```go diff --git a/viper.go b/viper.go index bd9b8a0..85742ec 100644 --- a/viper.go +++ b/viper.go @@ -169,6 +169,7 @@ type Viper struct { automaticEnvApplied bool envKeyReplacer *strings.Replacer + allowEmptyEnv bool config map[string]interface{} override map[string]interface{} @@ -330,6 +331,14 @@ func (v *Viper) mergeWithEnvPrefix(in string) string { return strings.ToUpper(in) } +// AllowEmptyEnv tells Viper to consider set, +// but empty environment variables as valid values instead of falling back. +// For backward compatibility reasons this is false by default. +func AllowEmptyEnv(allowEmptyEnv bool) { v.AllowEmptyEnv(allowEmptyEnv) } +func (v *Viper) AllowEmptyEnv(allowEmptyEnv bool) { + v.allowEmptyEnv = allowEmptyEnv +} + // TODO: should getEnv logic be moved into find(). Can generalize the use of // rewriting keys many things, Ex: Get('someKey') -> some_key // (camel case to snake case for JSON keys perhaps) @@ -341,7 +350,10 @@ func (v *Viper) getEnv(key string) (string, bool) { if v.envKeyReplacer != nil { key = v.envKeyReplacer.Replace(key) } - return os.LookupEnv(key) + + val, ok := os.LookupEnv(key) + + return val, ok && (v.allowEmptyEnv || val != "") } // ConfigFileUsed returns the file used to populate the config registry. diff --git a/viper_test.go b/viper_test.go index 73ff024..9dc703b 100644 --- a/viper_test.go +++ b/viper_test.go @@ -391,6 +391,22 @@ func TestEmptyEnv(t *testing.T) { os.Setenv("TYPE", "") + assert.Equal(t, "donut", Get("type")) + assert.Equal(t, "Cake", Get("name")) +} + +func TestEmptyEnv_Allowed(t *testing.T) { + initJSON() + + AllowEmptyEnv(true) + + BindEnv("type") // Empty environment variable + BindEnv("name") // Bound, but not set environment variable + + os.Clearenv() + + os.Setenv("TYPE", "") + assert.Equal(t, "", Get("type")) assert.Equal(t, "Cake", Get("name")) }