mirror of
https://github.com/spf13/viper
synced 2025-05-07 12:47:18 +00:00
Merge fb72938b55
into 15738813a0
This commit is contained in:
commit
52aa246076
2 changed files with 159 additions and 6 deletions
56
viper.go
56
viper.go
|
@ -164,6 +164,7 @@ type Viper struct {
|
||||||
// Name of file to look for inside the path
|
// Name of file to look for inside the path
|
||||||
configName string
|
configName string
|
||||||
configFile string
|
configFile string
|
||||||
|
configFileChain []string
|
||||||
configType string
|
configType string
|
||||||
envPrefix string
|
envPrefix string
|
||||||
|
|
||||||
|
@ -312,6 +313,15 @@ func (v *Viper) SetConfigFile(in string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetConfigFileChain explicitly defines slice of the path, name and extension of the config files
|
||||||
|
// Viper will use these and not check any of the config paths
|
||||||
|
func SetConfigChain(in []string) { v.SetConfigFileChain(in) }
|
||||||
|
func (v *Viper) SetConfigFileChain(in []string) {
|
||||||
|
if len(in) > 0 {
|
||||||
|
v.configFileChain = in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
|
// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use.
|
||||||
// E.g. if your prefix is "spf", the env registry will look for env
|
// E.g. if your prefix is "spf", the env registry will look for env
|
||||||
// variables that start with "SPF_".
|
// variables that start with "SPF_".
|
||||||
|
@ -1184,8 +1194,34 @@ func (v *Viper) MergeInConfig() error {
|
||||||
return v.MergeConfig(bytes.NewReader(file))
|
return v.MergeConfig(bytes.NewReader(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadConfig will read a configuration file, setting existing keys to nil if the
|
// MergeConfigFileChain repeatedly merge with configFileChain
|
||||||
// key does not exist in the file.
|
func MergeConfigFileChain() error { return v.MergeConfigFileChain() }
|
||||||
|
func (v *Viper) MergeConfigFileChain() error {
|
||||||
|
jww.INFO.Println("Attempting to chain merge with configFileChain")
|
||||||
|
|
||||||
|
configFileChain, err := v.getConfigFileChain()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, filename := range configFileChain {
|
||||||
|
if i == 0 {
|
||||||
|
v.SetConfigFile(filename)
|
||||||
|
err := v.ReadInConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v.SetConfigFile(filename)
|
||||||
|
err := v.MergeInConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
|
func ReadConfig(in io.Reader) error { return v.ReadConfig(in) }
|
||||||
func (v *Viper) ReadConfig(in io.Reader) error {
|
func (v *Viper) ReadConfig(in io.Reader) error {
|
||||||
v.config = make(map[string]interface{})
|
v.config = make(map[string]interface{})
|
||||||
|
@ -1736,6 +1772,22 @@ func (v *Viper) getConfigFile() (string, error) {
|
||||||
return v.configFile, nil
|
return v.configFile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Viper) getConfigFileChain() ([]string, error) {
|
||||||
|
// if explicitly set, then use it
|
||||||
|
// else search config file and return as slice
|
||||||
|
if len(v.configFileChain) > 0 {
|
||||||
|
return v.configFileChain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cf, err := v.findConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v.configFileChain = []string{cf}
|
||||||
|
return v.getConfigFileChain()
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Viper) searchInPath(in string) (filename string) {
|
func (v *Viper) searchInPath(in string) (filename string) {
|
||||||
jww.DEBUG.Println("Searching for config in ", in)
|
jww.DEBUG.Println("Searching for config in ", in)
|
||||||
for _, ext := range SupportedExts {
|
for _, ext := range SupportedExts {
|
||||||
|
|
101
viper_test.go
101
viper_test.go
|
@ -1412,3 +1412,104 @@ func BenchmarkGetBoolFromMap(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initConfigsForMerge(t *testing.T) (string, string, func()) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
testDirs = []string{`a`, `b`, `c`}
|
||||||
|
configName = `config.toml`
|
||||||
|
)
|
||||||
|
|
||||||
|
root, err := ioutil.TempDir("", "")
|
||||||
|
|
||||||
|
cleanup := true
|
||||||
|
defer func() {
|
||||||
|
if cleanup {
|
||||||
|
os.Chdir("..")
|
||||||
|
os.RemoveAll(root)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
err = os.Chdir(root)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
for _, dir := range testDirs {
|
||||||
|
err = os.Mkdir(dir, 0750)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(
|
||||||
|
path.Join(dir, configName),
|
||||||
|
[]byte("key = \"value is "+dir+"\"\n"+dir+" = \""+dir+"\"\n"),
|
||||||
|
0640)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup = false
|
||||||
|
return root, configName, func() {
|
||||||
|
os.Chdir("..")
|
||||||
|
os.RemoveAll(root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeConfigChain(t *testing.T) {
|
||||||
|
|
||||||
|
root, config, cleanup := initConfigsForMerge(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
v := New()
|
||||||
|
v.SetDefault(`key`, `default`)
|
||||||
|
|
||||||
|
entries, err := ioutil.ReadDir(root)
|
||||||
|
|
||||||
|
var configfiles []string
|
||||||
|
for i, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
configfile := path.Join(root, e.Name(), config)
|
||||||
|
configfiles = append(configfiles, configfile)
|
||||||
|
|
||||||
|
v.SetConfigFileChain(configfiles[:i+1])
|
||||||
|
err = v.MergeConfigFileChain()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, `value is `+e.Name(), v.GetString(`key`))
|
||||||
|
assert.Equal(t, `a`, v.GetString(`a`))
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
assert.Equal(t, ``, v.GetString(`b`))
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, `b`, v.GetString(`b`))
|
||||||
|
}
|
||||||
|
|
||||||
|
if i < 2 {
|
||||||
|
assert.Equal(t, ``, v.GetString(`c`))
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, `c`, v.GetString(`c`))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotSetConfigFileChainMerge(t *testing.T) {
|
||||||
|
// If not set, behavior is identical to ReadInConfig
|
||||||
|
|
||||||
|
root, config, cleanup := initDirs(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
v := New()
|
||||||
|
v.SetConfigName(config)
|
||||||
|
v.SetDefault(`key`, `default`)
|
||||||
|
|
||||||
|
entries, err := ioutil.ReadDir(root)
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
v.AddConfigPath(e.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
err = v.MergeConfigFileChain()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, `value is `+path.Base(v.configPaths[0]), v.GetString(`key`))
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue