diff --git a/pkg/envoy/yaml/setting_unmarshal.go b/pkg/envoy/yaml/setting_unmarshal.go index bff85a446..b1bb18a15 100644 --- a/pkg/envoy/yaml/setting_unmarshal.go +++ b/pkg/envoy/yaml/setting_unmarshal.go @@ -23,67 +23,28 @@ func (wset *settingSet) UnmarshalYAML(n *yaml.Node) error { wrap.res = &types.SettingValue{} - switch v.Kind { - case yaml.MappingNode: + if y7s.IsKind(n, yaml.SequenceNode) { + if !y7s.IsKind(v, yaml.MappingNode) { + return y7s.NodeErr(n, "malformed setting definition: sequence of settings must be defined as maps") + } + if err = v.Decode(&wrap); err != nil { return } - - default: + } else { if err = y7s.DecodeScalar(k, "setting name", &wrap.res.Name); err != nil { return err } - if y7s.IsKind(v, yaml.SequenceNode) { - aux := make([]interface{}, 0, 10) - - y7s.EachSeq(v, func(n *yaml.Node) error { - var vx interface{} - err := y7s.DecodeScalar(n, "setting value", &vx) - if err != nil { - return err - } - - aux = append(aux, vx) - return nil - }) - - m, err := json.Marshal(aux) - if err != nil { - return err - } - wrap.res.Value = sqlt.JSONText(m) - } else if y7s.IsKind(v, yaml.MappingNode) { - aux := make(map[string]interface{}) - - y7s.EachMap(v, func(k, v *yaml.Node) error { - var vx interface{} - err := y7s.DecodeScalar(v, "setting value", &vx) - if err != nil { - return err - } - - aux[k.Value] = vx - return nil - }) - - m, err := json.Marshal(aux) - if err != nil { - return err - } - wrap.res.Value = sqlt.JSONText(m) - } else { - var aux interface{} - err = y7s.DecodeScalar(v, "setting value", &aux) - if err != nil { - return err - } - m, err := json.Marshal(aux) - if err != nil { - return err - } - wrap.res.Value = sqlt.JSONText(m) + value, err := wrap.unmarshalSettingValue(v) + if err != nil { + return err } + m, err := json.Marshal(value) + if err != nil { + return err + } + wrap.res.Value = sqlt.JSONText(m) } *wset = append(*wset, wrap) @@ -107,10 +68,11 @@ func (wrap *setting) UnmarshalYAML(n *yaml.Node) (err error) { case "value": var aux interface{} - err = y7s.DecodeScalar(v, "setting value", &aux) + aux, err = wrap.unmarshalSettingValue(v) if err != nil { return err } + m, err := json.Marshal(aux) if err != nil { return err @@ -140,6 +102,48 @@ func (wrap *setting) UnmarshalYAML(n *yaml.Node) (err error) { return nil } +func (wrap *setting) unmarshalSettingValue(n *yaml.Node) (v interface{}, err error) { + switch n.Kind { + case yaml.SequenceNode: + out := make([]interface{}, 0, 10) + + err = y7s.EachSeq(n, func(n *yaml.Node) error { + aux, err := wrap.unmarshalSettingValue(n) + if err != nil { + return err + } + out = append(out, aux) + return nil + }) + return out, err + + case yaml.MappingNode: + out := make(map[string]interface{}) + + err = y7s.EachMap(n, func(k, v *yaml.Node) error { + aux, err := wrap.unmarshalSettingValue(v) + if err != nil { + return err + } + + out[k.Value] = aux + return nil + }) + return out, err + + case yaml.ScalarNode: + var out interface{} + if err := y7s.DecodeScalar(n, "setting value", &out); err != nil { + return v, err + } + + return out, nil + + default: + return nil, y7s.NodeErr(n, "unknown node kind") + } +} + func (wset settingSet) MarshalEnvoy() ([]resource.Interface, error) { nn := make([]resource.Interface, 0, len(wset)) diff --git a/tests/envoy/store_yaml_base_test.go b/tests/envoy/store_yaml_base_test.go index 4430a18ac..e7ffe9d8b 100644 --- a/tests/envoy/store_yaml_base_test.go +++ b/tests/envoy/store_yaml_base_test.go @@ -2,6 +2,7 @@ package envoy import ( "context" + "encoding/json" "strconv" "testing" "time" @@ -570,7 +571,7 @@ func TestStoreYaml_base(t *testing.T) { ss, _, err := store.SearchSettings(ctx, s, stypes.SettingsFilter{}) req.NoError(err) - req.Len(ss, 2) + req.Len(ss, 3) sv := ss[0] req.Equal("base_setting_1", sv.Name) @@ -583,6 +584,17 @@ func TestStoreYaml_base(t *testing.T) { req.Equal("20", sv.Value.String()) req.Equal(updatedAt.Format(time.RFC3339), sv.UpdatedAt.Format(time.RFC3339)) req.Equal(usr.ID, sv.UpdatedBy) + + sv = ss[2] + req.Equal("base_setting_3.dot", sv.Name) + sValue := make(map[string]interface{}) + req.NoError(json.Unmarshal(sv.Value, &sValue)) + req.Contains(sValue, "someKey") + req.Equal("someValue", sValue["someKey"]) + req.Contains(sValue, "otherKey") + req.Equal(float64(10), sValue["otherKey"]) + req.Equal(updatedAt.Format(time.RFC3339), sv.UpdatedAt.Format(time.RFC3339)) + req.Equal(usr.ID, sv.UpdatedBy) }, }, diff --git a/tests/envoy/system.go b/tests/envoy/system.go index e1507744e..03f1bce54 100644 --- a/tests/envoy/system.go +++ b/tests/envoy/system.go @@ -117,6 +117,12 @@ func sTestSettings(ctx context.Context, t *testing.T, s store.Storer, usrID uint UpdatedAt: updatedAt, UpdatedBy: usrID, }, + { + Name: pfx + "_setting_3.dot", + Value: []byte(`{"someKey": "someValue","otherKey":10}`), + UpdatedAt: updatedAt, + UpdatedBy: usrID, + }, } err := store.CreateSetting(ctx, s, ss...) diff --git a/tests/envoy/testdata/base/settings/source1.yaml b/tests/envoy/testdata/base/settings/source1.yaml index 8e36334f0..bdcf5256b 100644 --- a/tests/envoy/testdata/base/settings/source1.yaml +++ b/tests/envoy/testdata/base/settings/source1.yaml @@ -1,3 +1,8 @@ settings: s1.opt.1: s1 opt1 s1.opt.2: s1 opt2 + + compose.ui.record-toolbar: { "hideBack": true } + compose.ui.record-otherbar: + hideBack: true + hideCreate: true diff --git a/tests/envoy/yaml_store_base_test.go b/tests/envoy/yaml_store_base_test.go index 6a7e19de4..c15d744f9 100644 --- a/tests/envoy/yaml_store_base_test.go +++ b/tests/envoy/yaml_store_base_test.go @@ -544,10 +544,13 @@ func TestYamlStore_base(t *testing.T) { ss, _, err := store.SearchSettings(ctx, s, systypes.SettingsFilter{}) req.NoError(err) req.NotNil(ss) - req.Len(ss, 4) + req.Len(ss, 6) - rs := []string{ss[0].Name, ss[1].Name, ss[2].Name, ss[3].Name} - req.Subset(rs, []string{"s1.opt.1", "s1.opt.2", "s2.opt.1", "s2.opt.2"}) + rs := []string{ss[0].Name, ss[1].Name, ss[2].Name, ss[3].Name, ss[4].Name, ss[5].Name} + req.Subset(rs, []string{"s1.opt.1", "s1.opt.2", "compose.ui.record-toolbar", "compose.ui.record-otherbar", "s2.opt.1", "s2.opt.2"}) + + req.Equal("{\"hideBack\":true}", ss[2].Value.String()) + req.Equal("{\"hideBack\":true,\"hideCreate\":true}", ss[3].Value.String()) }, }, }