Support rewriting env keys

This commit is contained in:
Chance Zibolski 2015-03-06 11:21:17 -08:00
parent ededa04e0b
commit 03fb74b5d7
3 changed files with 44 additions and 3 deletions

View file

@ -98,12 +98,13 @@ Aliases permit a single value to be referenced by multiple keys
### 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 its important to recognize that Viper
treats ENV variables as case sensitive._
@ -131,6 +132,11 @@ any time a viper.Get request is made. It will apply the following rules.
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

View file

@ -77,6 +77,7 @@ type viper struct {
envPrefix string
automaticEnvApplied bool
envKeyReplacer *strings.Replacer
config map[string]interface{}
override map[string]interface{}
@ -153,6 +154,20 @@ func (v *viper) mergeWithEnvPrefix(in string) string {
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 @@ func (v *viper) find(key string) interface{} {
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 @@ func (v *viper) find(key string) interface{} {
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 @@ func (v *viper) AutomaticEnv() {
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) }

View file

@ -10,6 +10,7 @@ import (
"fmt"
"os"
"sort"
"strings"
"testing"
"time"
@ -221,6 +222,7 @@ func TestEnv(t *testing.T) {
AutomaticEnv()
assert.Equal(t, "crunk", Get("name"))
}
func TestEnvPrefix(t *testing.T) {
@ -260,6 +262,18 @@ func TestAutoEnvWithPrefix(t *testing.T) {
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()