fixing nested interface type parsing

pull/3364/head
Thomas Jungblut 8 years ago
parent 2b92431476
commit df274c2c7e

@ -24,6 +24,7 @@ import (
"strings"
"github.com/ghodss/yaml"
"reflect"
)
// ErrNotList indicates that a non-list was treated as a list.
@ -147,7 +148,24 @@ func (t *parser) key(data map[string]interface{}) error {
// First, create or find the target map.
inner := map[string]interface{}{}
if _, ok := data[string(k)]; ok {
inner = data[string(k)].(map[string]interface{})
// when reading nested object yamls, the unmarshal will create a map[interface{}]interface{})
// below logic tries to account for that and attempts to cast the key into a string again
if simpleStringMapCast, ok := data[string(k)].(map[string]interface{}); ok {
inner = simpleStringMapCast
} else {
if interfaceKeyCasted, ok := data[string(k)].(map[interface{}]interface{}); ok {
for key, val := range interfaceKeyCasted {
keyString, casted := key.(string)
if !casted {
return fmt.Errorf("couldn't cast map key %q to string for value key %q", key, string(k))
}
inner[keyString] = val
}
} else {
return fmt.Errorf("don't know how to handle map type %q for key %q",
reflect.TypeOf(data[string(k)]), string(k))
}
}
}
// Recurse

@ -19,6 +19,7 @@ import (
"testing"
"github.com/ghodss/yaml"
"io/ioutil"
)
func TestSetIndex(t *testing.T) {
@ -284,7 +285,7 @@ func TestParseSet(t *testing.T) {
}
}
func TestParseInto(t *testing.T) {
func TestParseIntoHappyPath(t *testing.T) {
got := map[string]interface{}{
"outer": map[string]interface{}{
"inner1": "overwrite",
@ -300,10 +301,45 @@ func TestParseInto(t *testing.T) {
},
}
if err := ParseInto(input, got); err != nil {
checkParserOutput(input, got, t, expect)
}
func TestParseIntoNestedInterface(t *testing.T) {
currentMap := map[string]interface{}{}
bytes, err := ioutil.ReadFile("testdata/parser_val_nested.yaml")
if err != nil {
t.Fatal(err)
}
if err := yaml.Unmarshal(bytes, &currentMap); err != nil {
t.Fatal(err)
}
input := "toplevel.flatlevel1=overwritefl1"
expect := map[string]interface{}{
"toplevel": map[string]interface{}{
"env": []interface{}{
map[string]interface{}{
"key": "abckey",
"value": "abcval",
}, map[string]interface{}{
"key": "defkey",
"value": "defval",
},
},
"flatlevel1": "overwritefl1",
"flatlevel2": "def",
},
}
checkParserOutput(input, currentMap, t, expect)
}
func checkParserOutput(input string, got map[string]interface{}, t *testing.T, expect map[string]interface{}) {
if err := ParseInto(input, got); err != nil {
t.Fatal(err)
}
y1, err := yaml.Marshal(expect)
if err != nil {
t.Fatal(err)
@ -312,7 +348,6 @@ func TestParseInto(t *testing.T) {
if err != nil {
t.Fatalf("Error serializing parsed value: %s", err)
}
if string(y1) != string(y2) {
t.Errorf("%s: Expected:\n%s\nGot:\n%s", input, y1, y2)
}

@ -0,0 +1,8 @@
toplevel:
env:
- key: abckey
value: abcval
- key: defkey
value: defval
flatlevel1: abc
flatlevel2: def
Loading…
Cancel
Save