Support rewriting env keys
diff --git a/README.md b/README.md
index 9f236b2..690228c 100644
--- a/README.md
+++ b/README.md
@@ -98,12 +98,13 @@
### Working with Environment Variables
Viper has full support for environment variables. This enables 12 factor
-applications out of the box. There are three methods that exist to aid
+applications out of the box. There are four methods that exist to aid
with working with ENV:
* AutomaticEnv()
* BindEnv(string...) : error
* SetEnvPrefix(string)
+ * SetEnvReplacer(string...) *strings.Replacer
_When working with ENV variables it’s important to recognize that Viper
treats ENV variables as case sensitive._
@@ -131,6 +132,11 @@
It will check for a environment variable with a name matching the key
uppercased and prefixed with the EnvPrefix if set.
+SetEnvReplacer allows you to use a `strings.Replacer` object to rewrite Env 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`
+
#### Env example
SetEnvPrefix("spf") // will be uppercased automatically
diff --git a/viper.go b/viper.go
index e808887..2d51b9b 100644
--- a/viper.go
+++ b/viper.go
@@ -77,6 +77,7 @@
envPrefix string
automaticEnvApplied bool
+ envKeyReplacer *strings.Replacer
config map[string]interface{}
override map[string]interface{}
@@ -153,6 +154,20 @@
return strings.ToUpper(in)
}
+// TODO: should getEnv logic be moved into find(). Can generalize the use of
+// rewriting keys many things, Ex: Get('someKey') -> some_key
+// (cammel case to snake case for JSON keys perhaps)
+
+// getEnv s a wrapper around os.Getenv which replaces characters in the original
+// key. This allows env vars which have different keys then the config object
+// keys
+func (v *viper) getEnv(key string) string {
+ if v.envKeyReplacer != nil {
+ key = v.envKeyReplacer.Replace(key)
+ }
+ return os.Getenv(key)
+}
+
// Return the config file used
func ConfigFileUsed() string { return v.ConfigFileUsed() }
func (v *viper) ConfigFileUsed() string { return v.configFile }
@@ -427,7 +442,7 @@
if v.automaticEnvApplied {
// even if it hasn't been registered, if automaticEnv is used,
// check any Get request
- if val = os.Getenv(v.mergeWithEnvPrefix(key)); val != "" {
+ if val = v.getEnv(v.mergeWithEnvPrefix(key)); val != "" {
jww.TRACE.Println(key, "found in environment with val:", val)
return val
}
@@ -436,7 +451,7 @@
envkey, exists := v.env[key]
if exists {
jww.TRACE.Println(key, "registered as env var", envkey)
- if val = os.Getenv(envkey); val != "" {
+ if val = v.getEnv(envkey); val != "" {
jww.TRACE.Println(envkey, "found in environment with val:", val)
return val
} else {
@@ -479,6 +494,12 @@
v.automaticEnvApplied = true
}
+// SetEnvKeyReplacer sets the strings.Replacer on the viper object
+func SetEnvKeyReplacer(r *strings.Replacer) { v.SetEnvKeyReplacer(r) }
+func (v *viper) SetEnvKeyReplacer(r *strings.Replacer) {
+ v.envKeyReplacer = r
+}
+
// Aliases provide another accessor for the same key.
// This enables one to change a name without breaking the application
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
diff --git a/viper_test.go b/viper_test.go
index 2c665ec..a9ba70f 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -10,6 +10,7 @@
"fmt"
"os"
"sort"
+ "strings"
"testing"
"time"
@@ -221,6 +222,7 @@
AutomaticEnv()
assert.Equal(t, "crunk", Get("name"))
+
}
func TestEnvPrefix(t *testing.T) {
@@ -260,6 +262,18 @@
assert.Equal(t, "13", Get("bar"))
}
+func TestSetEnvReplacer(t *testing.T) {
+ Reset()
+
+ AutomaticEnv()
+ os.Setenv("REFRESH_INTERVAL", "30s")
+
+ replacer := strings.NewReplacer("-", "_")
+ SetEnvKeyReplacer(replacer)
+
+ assert.Equal(t, "30s", Get("refresh-interval"))
+}
+
func TestAllKeys(t *testing.T) {
initConfigs()