Rework YAML setting unmarshling for more flexibility
Allow settings to use JSON values, use recursive value decoding for nested structures.
This commit is contained in:
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -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...)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user