diff --git a/viper.go b/viper.go index cee37b2..4451002 100644 --- a/viper.go +++ b/viper.go @@ -1278,6 +1278,23 @@ func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error { return nil } +// MergeConfigOverride merges a new configuration within the config at the +// highest lever of priority (similar to the 'Set' method). Key set here will +// always be retrieved before values from env, files... +func MergeConfigOverride(in io.Reader) error { return v.MergeConfigOverride(in) } +func (v *Viper) MergeConfigOverride(in io.Reader) error { + if v.override == nil { + v.override = make(map[string]interface{}) + } + cfg := make(map[string]interface{}) + if err := v.unmarshalReader(in, cfg); err != nil { + return err + } + insensitiviseMap(cfg) + mergeMaps(cfg, v.override, nil) + return nil +} + // WriteConfig writes the current configuration to a file. func WriteConfig() error { return v.WriteConfig() } func (v *Viper) WriteConfig() error { diff --git a/viper_test.go b/viper_test.go index f4263d3..f3dbee2 100644 --- a/viper_test.go +++ b/viper_test.go @@ -1190,6 +1190,75 @@ func TestMergeConfig(t *testing.T) { } } +func TestMergeConfigOverride(t *testing.T) { + v := New() + v.SetConfigType("yml") + + v.SetEnvPrefix("Baz") + v.BindEnv("fu") + os.Setenv("BAZ_FU", "test") + + if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt)); err != nil { + t.Fatal(err) + } + + if pop := v.GetInt("hello.pop"); pop != 37890 { + t.Fatalf("pop != 37890, = %d", pop) + } + + if pop := v.GetInt("hello.lagrenum"); pop != 765432101234567 { + t.Fatalf("lagrenum != 765432101234567, = %d", pop) + } + + if pop := v.GetInt32("hello.pop"); pop != int32(37890) { + t.Fatalf("pop != 37890, = %d", pop) + } + + if pop := v.GetInt64("hello.lagrenum"); pop != int64(765432101234567) { + t.Fatalf("int64 lagrenum != 765432101234567, = %d", pop) + } + + if world := v.GetStringSlice("hello.world"); len(world) != 4 { + t.Fatalf("len(world) != 4, = %d", len(world)) + } + + if fu := v.GetString("fu"); fu != "test" { + t.Fatalf("fu != \"test\", = %s", fu) + } + + if err := v.MergeConfigOverride(bytes.NewBuffer(yamlMergeExampleSrc)); err != nil { + t.Fatal(err) + } + + if pop := v.GetInt("hello.pop"); pop != 45000 { + t.Fatalf("pop != 45000, = %d", pop) + } + + if pop := v.GetInt("hello.lagrenum"); pop != 7654321001234567 { + t.Fatalf("lagrenum != 7654321001234567, = %d", pop) + } + + if pop := v.GetInt32("hello.pop"); pop != int32(45000) { + t.Fatalf("pop != 45000, = %d", pop) + } + + if pop := v.GetInt64("hello.lagrenum"); pop != int64(7654321001234567) { + t.Fatalf("int64 lagrenum != 7654321001234567, = %d", pop) + } + + if world := v.GetStringSlice("hello.world"); len(world) != 4 { + t.Fatalf("len(world) != 4, = %d", len(world)) + } + + if universe := v.GetStringSlice("hello.universe"); len(universe) != 2 { + t.Fatalf("len(universe) != 2, = %d", len(universe)) + } + + if fu := v.GetString("fu"); fu != "bar" { + t.Fatalf("fu != \"bar\", = %s", fu) + } +} + func TestMergeConfigNoMerge(t *testing.T) { v := New() v.SetConfigType("yml")