0d5e917ae0
Both 'consul config write' and server bootstrap config entries take a decoding detour through mapstructure on the way from HCL to an actual struct. They both may take in snake_case or CamelCase (for consistency) so need very similar handling. Unfortunately since they are operating on mirror universes of structs (api.* vs structs.*) the code cannot be identitical, so try to share the kind-configuration and duplicate the rest for now.
124 lines
1.9 KiB
Go
124 lines
1.9 KiB
Go
package lib
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func parse(s string) map[string]interface{} {
|
|
var m map[string]interface{}
|
|
if err := json.Unmarshal([]byte(s), &m); err != nil {
|
|
panic(s + ":" + err.Error())
|
|
}
|
|
return m
|
|
}
|
|
|
|
func TestPatchSliceOfMaps(t *testing.T) {
|
|
tests := []struct {
|
|
in, out string
|
|
skip []string
|
|
skipTree []string
|
|
}{
|
|
{
|
|
in: `{"a":{"b":"c"}}`,
|
|
out: `{"a":{"b":"c"}}`,
|
|
},
|
|
{
|
|
in: `{"a":[{"b":"c"}]}`,
|
|
out: `{"a":{"b":"c"}}`,
|
|
},
|
|
{
|
|
in: `{"a":[{"b":[{"c":"d"}]}]}`,
|
|
out: `{"a":{"b":{"c":"d"}}}`,
|
|
},
|
|
{
|
|
in: `{"a":[{"b":"c"}]}`,
|
|
out: `{"a":[{"b":"c"}]}`,
|
|
skip: []string{"a"},
|
|
},
|
|
{
|
|
in: `{
|
|
"services": [
|
|
{
|
|
"checks": [
|
|
{
|
|
"header": [
|
|
{"a":"b"}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}`,
|
|
out: `{
|
|
"services": [
|
|
{
|
|
"checks": [
|
|
{
|
|
"header": {"a":"b"}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}`,
|
|
skip: []string{"services", "services.checks"},
|
|
},
|
|
{
|
|
// inspired by the 'config_entries.bootstrap.*' structure for configs
|
|
in: `
|
|
{
|
|
"a": [
|
|
{
|
|
"b": [
|
|
{
|
|
"c": "val1",
|
|
"d": {
|
|
"foo": "bar"
|
|
},
|
|
"e": [
|
|
{
|
|
"super": "duper"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
`,
|
|
out: `
|
|
{
|
|
"a": {
|
|
"b": [
|
|
{
|
|
"c": "val1",
|
|
"d": {
|
|
"foo": "bar"
|
|
},
|
|
"e": [
|
|
{
|
|
"super": "duper"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`,
|
|
skipTree: []string{"a.b"},
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
desc := fmt.Sprintf("%02d: %s -> %s skip: %v", i, tt.in, tt.out, tt.skip)
|
|
t.Run(desc, func(t *testing.T) {
|
|
out := PatchSliceOfMaps(parse(tt.in), tt.skip, tt.skipTree)
|
|
if got, want := out, parse(tt.out); !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("\ngot %#v\nwant %#v", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|