3
0

Fix compose module field unmarshling; fix directory decoding

This commit is contained in:
Tomaž Jerman
2020-12-01 10:27:58 +01:00
parent aa2d930b0d
commit 3a9891431d
6 changed files with 165 additions and 33 deletions
+5
View File
@@ -53,6 +53,11 @@ func Decode(ctx context.Context, p string, decoders ...decoder) ([]resource.Inte
for _, d := range decoders {
if !d.CanDecodeFile(f) {
// decoder can not handle this file
// Make sure to reset it, as the above check consumes the reader
if _, err = f.Seek(0, 0); err != nil {
return err
}
continue
}
+36 -22
View File
@@ -2,6 +2,7 @@ package yaml
import (
"fmt"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/pkg/envoy"
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
@@ -32,18 +33,11 @@ type (
composeModuleSet []*composeModule
composeModuleField struct {
res *types.ModuleField `yaml:",inline"`
res *types.ModuleField
rbac rbacRuleSet
}
composeModuleFieldSet []*composeModuleField
// aux struct to help us with decoding of module field
composeModuleFieldAux struct {
*types.ModuleField
Expressions *composeModuleFieldExprAux
}
// aux struct for decoding module field expressions
composeModuleFieldExprAux types.ModuleFieldExpr
)
@@ -273,23 +267,10 @@ func (set composeModuleFieldSet) set() (out types.ModuleFieldSet) {
func (wrap *composeModuleField) UnmarshalYAML(n *yaml.Node) (err error) {
if wrap.res == nil {
wrap.rbac = make(rbacRuleSet, 0, 10)
wrap.res = &types.ModuleField{}
}
// cast existing field expressions struct to aux struct
exprAux := composeModuleFieldExprAux(wrap.res.Expressions)
// construct field aux struct from resource and aux expr struct
// this way yaml pkg can help us with field unmarshalling but
// we catch expressions and do our own magic
aux := &composeModuleFieldAux{ModuleField: wrap.res, Expressions: &exprAux}
if err = n.Decode(aux); err != nil {
return
}
// cast unmarshalled expressions back to original type
wrap.res.Expressions = types.ModuleFieldExpr(exprAux)
if wrap.rbac, err = decodeRbac(n); err != nil {
return
}
@@ -299,6 +280,39 @@ func (wrap *composeModuleField) UnmarshalYAML(n *yaml.Node) (err error) {
case "name":
return fmt.Errorf("name should be encoded as field definition key")
case "place":
return decodeScalar(v, "module place", &wrap.res.Place)
case "kind":
return decodeScalar(v, "module kind", &wrap.res.Kind)
case "label":
return decodeScalar(v, "module label", &wrap.res.Label)
case "private":
return decodeScalar(v, "module private", &wrap.res.Private)
case "required":
return decodeScalar(v, "module required", &wrap.res.Required)
case "visible":
return decodeScalar(v, "module visible", &wrap.res.Visible)
case "multi":
return decodeScalar(v, "module multi", &wrap.res.Multi)
case "options":
if err = v.Decode(&wrap.res.Options); err != nil {
return err
}
case "expressions":
ea := composeModuleFieldExprAux{}
if err = v.Decode(&ea); err != nil {
return err
}
wrap.res.Expressions = types.ModuleFieldExpr(ea)
case "default":
var rvs = types.RecordValueSet{}
switch v.Kind {
+11
View File
@@ -149,3 +149,14 @@ func ce(ee ...error) error {
}
return nil
}
func fullModLoad(ctx context.Context, s store.Storer, req *require.Assertions, nsID uint64, handle string) (*types.Module, error) {
mod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, nsID, handle)
req.NoError(err)
req.NotNil(mod)
mod.Fields, _, err = store.SearchComposeModuleFields(ctx, s, types.ModuleFieldFilter{ModuleID: []uint64{mod.ID}})
req.NoError(err)
req.NotNil(mod.Fields)
return mod, err
}
+91
View File
@@ -0,0 +1,91 @@
package envoy
import (
"context"
"testing"
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
su "github.com/cortezaproject/corteza-server/pkg/envoy/store"
"github.com/cortezaproject/corteza-server/store"
"github.com/stretchr/testify/require"
)
func TestModuleExpr(t *testing.T) {
var (
ctx = context.Background()
s, err = initStore(ctx)
)
if err != nil {
t.Fatalf("failed to init sqlite in-memory db: %v", err)
}
ni := uint64(0)
su.NextID = func() uint64 {
ni++
return ni
}
prepare := func(ctx context.Context, s store.Storer, t *testing.T, suite string) (*require.Assertions, error) {
req := require.New(t)
nn, err := dd(ctx, suite)
req.NoError(err)
crs := resource.ComposeRecordShaper()
nn, err = resource.Shape(nn, crs)
req.NoError(err)
return req, encode(ctx, s, nn)
}
// Prepare
s, err = initStore(ctx)
err = ce(
err,
s.TruncateRbacRules(ctx),
s.TruncateRoles(ctx),
s.TruncateActionlogs(ctx),
s.TruncateApplications(ctx),
s.TruncateAttachments(ctx),
s.TruncateComposeAttachments(ctx),
s.TruncateComposeCharts(ctx),
s.TruncateComposeNamespaces(ctx),
s.TruncateComposeModules(ctx),
s.TruncateComposeModuleFields(ctx),
s.TruncateComposePages(ctx),
storeRole(ctx, s, 1, "everyone"),
storeRole(ctx, s, 2, "admins"),
)
if err != nil {
t.Fatal(err.Error())
}
req, err := prepare(ctx, s, t, "mod_expr")
req.NoError(err)
t.Run("module field expressions", func(t *testing.T) {
ns, err := store.LookupComposeNamespaceBySlug(ctx, s, "crm")
req.NoError(err)
req.NotNil(ns)
mod, err := fullModLoad(ctx, s, req, ns.ID, "Account")
req.NotNil(mod)
req.NoError(err)
req.Len(mod.Fields, 2)
// Check the full thing
mfF := mod.Fields[0]
req.Equal("a > b", mfF.Expressions.ValueExpr)
req.Subset(mfF.Expressions.Sanitizers, []string{"trim(value)"})
v := mfF.Expressions.Validators[0]
req.Equal("a == \"\"", v.Test)
req.Equal("Value should not be empty", v.Error)
// Check the other validator form
mfV := mod.Fields[1]
v = mfV.Expressions.Validators[0]
req.Equal("value == \"\"", v.Test)
req.Equal("Value should be filled", v.Error)
})
}
+2 -11
View File
@@ -44,6 +44,8 @@ func TestProvision_batch(t *testing.T) {
err = ce(
err,
s.TruncateRoles(ctx),
s.TruncateRbacRules(ctx),
s.TruncateActionlogs(ctx),
s.TruncateApplications(ctx),
s.TruncateAttachments(ctx),
@@ -188,14 +190,3 @@ func checkBatchProvision(ctx context.Context, t *testing.T, req *require.Asserti
req.Equal(fmt.Sprintf("%s value", slug), v.Value)
})
}
func fullModLoad(ctx context.Context, s store.Storer, req *require.Assertions, nsID uint64, handle string) (*types.Module, error) {
mod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, nsID, handle)
req.NoError(err)
req.NotNil(mod)
mod.Fields, _, err = store.SearchComposeModuleFields(ctx, s, types.ModuleFieldFilter{ModuleID: []uint64{mod.ID}})
req.NoError(err)
req.NotNil(mod.Fields)
return mod, err
}
+20
View File
@@ -0,0 +1,20 @@
namespaces:
crm:
name: CRM
modules:
Account:
name: Expressions
fields:
full:
expressions:
valueExpr: "a > b"
sanitizers: [ "trim(value)" ]
validators:
- test: 'a == ""'
error: Value should not be empty
disableDefaultValidators: true
validatorKV:
expressions:
validators:
'value == ""': Value should be filled