Allow merging configs with different types of leaf values

This commit is contained in:
illarion Kovalchuk 2020-12-23 15:28:47 +02:00 committed by Márk Sági-Kazár
parent 788403a47c
commit 0353c6ea50
2 changed files with 48 additions and 13 deletions

View file

@ -1780,17 +1780,6 @@ func mergeMaps(
svType := reflect.TypeOf(sv) svType := reflect.TypeOf(sv)
tvType := reflect.TypeOf(tv) tvType := reflect.TypeOf(tv)
if tvType != nil && svType != tvType { // Allow for the target to be nil
v.logger.Error(
"svType != tvType",
"key", sk,
"st", svType,
"tt", tvType,
"sv", sv,
"tv", tv,
)
continue
}
v.logger.Trace( v.logger.Trace(
"processing", "processing",
@ -1804,13 +1793,27 @@ func mergeMaps(
switch ttv := tv.(type) { switch ttv := tv.(type) {
case map[interface{}]interface{}: case map[interface{}]interface{}:
v.logger.Trace("merging maps (must convert)") v.logger.Trace("merging maps (must convert)")
tsv := sv.(map[interface{}]interface{}) tsv, ok := sv.(map[interface{}]interface{})
if !ok {
v.logger.Error(
"Could not cast sv to map[interface{}]interface{}; key=%s, st=%v, tt=%v, sv=%v, tv=%v",
sk, svType, tvType, sv, tv)
continue
}
ssv := castToMapStringInterface(tsv) ssv := castToMapStringInterface(tsv)
stv := castToMapStringInterface(ttv) stv := castToMapStringInterface(ttv)
mergeMaps(ssv, stv, ttv) mergeMaps(ssv, stv, ttv)
case map[string]interface{}: case map[string]interface{}:
v.logger.Trace("merging maps") v.logger.Trace("merging maps")
mergeMaps(sv.(map[string]interface{}), ttv, nil) tsv, ok := sv.(map[string]interface{})
if !ok {
jww.ERROR.Printf(
"Could not cast sv to map[string]interface{}; key=%s, st=%v, tt=%v, sv=%v, tv=%v",
sk, svType, tvType, sv, tv)
continue
}
mergeMaps(tsv, ttv, nil)
default: default:
v.logger.Trace("setting value") v.logger.Trace("setting value")
tgt[tk] = sv tgt[tk] = sv

View file

@ -1912,6 +1912,22 @@ hello:
fu: bar fu: bar
`) `)
var jsonMergeExampleTgt = []byte(`
{
"hello": {
"pop": 123456
}
}
`)
var jsonMergeExampleSrc = []byte(`
{
"hello": {
"pop": "pop str"
}
}
`)
func TestMergeConfig(t *testing.T) { func TestMergeConfig(t *testing.T) {
v := New() v := New()
v.SetConfigType("yml") v.SetConfigType("yml")
@ -1984,6 +2000,22 @@ func TestMergeConfig(t *testing.T) {
} }
} }
func TestMergeConfigOverrideType(t *testing.T) {
v := New()
v.SetConfigType("json")
if err := v.ReadConfig(bytes.NewBuffer(jsonMergeExampleTgt)); err != nil {
t.Fatal(err)
}
if err := v.MergeConfig(bytes.NewBuffer(jsonMergeExampleSrc)); err != nil {
t.Fatal(err)
}
if pop := v.GetString("hello.pop"); pop != "pop str" {
t.Fatalf("pop != \"pop str\", = %s", pop)
}
}
func TestMergeConfigNoMerge(t *testing.T) { func TestMergeConfigNoMerge(t *testing.T) {
v := New() v := New()
v.SetConfigType("yml") v.SetConfigType("yml")