Add base tests & post test tweaks
This commit is contained in:
@@ -22,7 +22,7 @@ type (
|
||||
//
|
||||
// Encoding errors are passed via Ec.
|
||||
Encoder interface {
|
||||
Encode(ctx context.Context, c Rc) error
|
||||
Encode(ctx context.Context, p Provider) error
|
||||
}
|
||||
|
||||
PrepareEncoder interface {
|
||||
|
||||
+4
-37
@@ -2,7 +2,6 @@ package envoy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -12,40 +11,8 @@ type (
|
||||
)
|
||||
|
||||
// @todo errors!
|
||||
func Encode(ctx context.Context, p Provider, ee ...Encoder) error {
|
||||
var err error
|
||||
rcc := make([]Rc, len(ee))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(ee))
|
||||
|
||||
for i, e := range ee {
|
||||
rcc[i] = make(Rc)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
eErr := e.Encode(ctx, rcc[i])
|
||||
if err != nil {
|
||||
err = eErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for {
|
||||
rs, err := p.Next(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rc := range rcc {
|
||||
rc <- rs
|
||||
}
|
||||
if rs == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
func Encode(ctx context.Context, p Provider, e Encoder) error {
|
||||
// @todo add support for multiple encoders at the same time.
|
||||
// The issue occurs with routines and error handling...
|
||||
return e.Encode(ctx, p)
|
||||
}
|
||||
|
||||
@@ -10,13 +10,21 @@ type (
|
||||
*base
|
||||
Res *types.Page
|
||||
|
||||
NsRef *Ref
|
||||
ModRef *Ref
|
||||
NsRef *Ref
|
||||
ModRef *Ref
|
||||
ParentRef *Ref
|
||||
|
||||
ModRefs RefSet
|
||||
ChartRefs RefSet
|
||||
}
|
||||
)
|
||||
|
||||
func NewComposePage(pg *types.Page, nsRef, modRef string) *ComposePage {
|
||||
r := &ComposePage{base: &base{}}
|
||||
func NewComposePage(pg *types.Page, nsRef, modRef, parentRef string) *ComposePage {
|
||||
r := &ComposePage{
|
||||
base: &base{},
|
||||
ModRefs: make(RefSet, 0, 10),
|
||||
ChartRefs: make(RefSet, 0, 10),
|
||||
}
|
||||
r.SetResourceType(COMPOSE_PAGE_RESOURCE_TYPE)
|
||||
r.Res = pg
|
||||
|
||||
@@ -27,6 +35,36 @@ func NewComposePage(pg *types.Page, nsRef, modRef string) *ComposePage {
|
||||
r.ModRef = r.AddRef(COMPOSE_MODULE_RESOURCE_TYPE, modRef)
|
||||
}
|
||||
|
||||
if parentRef != "" {
|
||||
r.ParentRef = r.AddRef(COMPOSE_PAGE_RESOURCE_TYPE, parentRef)
|
||||
}
|
||||
|
||||
for _, b := range pg.Blocks {
|
||||
switch b.Kind {
|
||||
case "RecordList":
|
||||
id, _ := b.Options["module"].(string)
|
||||
if id != "" {
|
||||
r.ModRefs = append(r.ModRefs, r.AddRef(COMPOSE_MODULE_RESOURCE_TYPE, id))
|
||||
}
|
||||
|
||||
case "Chart":
|
||||
id, _ := b.Options["chart"].(string)
|
||||
if id != "" {
|
||||
r.ChartRefs = append(r.ChartRefs, r.AddRef(COMPOSE_CHART_RESOURCE_TYPE, id))
|
||||
}
|
||||
|
||||
case "Metric":
|
||||
mm, _ := b.Options["metrics"].([]interface{})
|
||||
for _, m := range mm {
|
||||
mops, _ := m.(map[string]interface{})
|
||||
id, _ := mops["module"].(string)
|
||||
if id != "" {
|
||||
r.ModRefs = append(r.ModRefs, r.AddRef(COMPOSE_MODULE_RESOURCE_TYPE, id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func (n *applicationState) Encode(ctx context.Context, s store.Storer, state *en
|
||||
res.ID = n.app.ID
|
||||
}
|
||||
if res.ID <= 0 {
|
||||
res.ID = nextID()
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
|
||||
@@ -2,6 +2,7 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
@@ -45,11 +46,6 @@ func (n *composeChartState) Prepare(ctx context.Context, s store.Storer, state *
|
||||
return composeNamespaceErrUnresolved(n.res.NsRef.Identifiers)
|
||||
}
|
||||
|
||||
// Can't do anything else, since the NS doesn't yet exist
|
||||
if n.relNS.ID <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get related modules
|
||||
n.relMods = make(types.ModuleSet, len(n.res.ModRef))
|
||||
for i, mRef := range n.res.ModRef {
|
||||
@@ -83,7 +79,7 @@ func (n *composeChartState) Encode(ctx context.Context, s store.Storer, state *e
|
||||
res.ID = n.chr.ID
|
||||
}
|
||||
if res.ID <= 0 {
|
||||
res.ID = nextID()
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
@@ -170,6 +166,10 @@ func findComposeChartRS(ctx context.Context, s store.Storer, nsID uint64, rr res
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
if nsID <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Go in the store
|
||||
return findComposeChartS(ctx, s, nsID, makeGenericFilter(ii))
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func findComposeChartR(rr resource.InterfaceSet, ii resource.Identifiers) (ch *t
|
||||
return nil
|
||||
}
|
||||
|
||||
if chRes.Identifiers().HasAny(ii) {
|
||||
if cr.Identifiers().HasAny(ii) {
|
||||
chRes = cr
|
||||
}
|
||||
return nil
|
||||
@@ -224,3 +224,7 @@ func findComposeChartR(rr resource.InterfaceSet, ii resource.Identifiers) (ch *t
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func composeChartErrUnresolved(ii resource.Identifiers) error {
|
||||
return fmt.Errorf("compose chart unresolved %v", ii.StringSlice())
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ func (n *composeModuleState) Encode(ctx context.Context, s store.Storer, state *
|
||||
res.ID = n.mod.ID
|
||||
}
|
||||
if res.ID <= 0 {
|
||||
res.ID = nextID()
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
if state.Conflicting {
|
||||
@@ -126,8 +126,17 @@ func (n *composeModuleState) Encode(ctx context.Context, s store.Storer, state *
|
||||
}
|
||||
|
||||
// Fields
|
||||
off := make(types.ModuleFieldSet, 0)
|
||||
if n.mod != nil && n.mod.Fields != nil {
|
||||
off = n.mod.Fields
|
||||
}
|
||||
for i, f := range res.Fields {
|
||||
f.ID = res.ID
|
||||
of := off.FindByName(f.Name)
|
||||
if of != nil {
|
||||
f.ID = of.ID
|
||||
} else {
|
||||
f.ID = NextID()
|
||||
}
|
||||
f.ModuleID = res.ID
|
||||
f.Place = i
|
||||
f.DeletedAt = nil
|
||||
@@ -262,6 +271,10 @@ func findComposeModuleRS(ctx context.Context, s store.Storer, nsID uint64, rr re
|
||||
return mod, nil
|
||||
}
|
||||
|
||||
if nsID <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Go in the store
|
||||
return findComposeModuleS(ctx, s, nsID, makeGenericFilter(ii))
|
||||
}
|
||||
@@ -303,7 +316,7 @@ func findComposeModuleR(rr resource.InterfaceSet, ii resource.Identifiers) (ns *
|
||||
return nil
|
||||
}
|
||||
|
||||
if modRes.Identifiers().HasAny(ii) {
|
||||
if mr.Identifiers().HasAny(ii) {
|
||||
modRes = mr
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -55,7 +55,7 @@ func (n *composeNamespaceState) Encode(ctx context.Context, s store.Storer, stat
|
||||
res.ID = n.ns.ID
|
||||
}
|
||||
if res.ID <= 0 {
|
||||
res.ID = nextID()
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
|
||||
+127
-10
@@ -2,6 +2,7 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
@@ -17,8 +18,12 @@ type (
|
||||
res *resource.ComposePage
|
||||
pg *types.Page
|
||||
|
||||
relNS *types.Namespace
|
||||
relMod *types.Module
|
||||
relNS *types.Namespace
|
||||
relMod *types.Module
|
||||
relParent *types.Page
|
||||
|
||||
relMods map[string]*types.Module
|
||||
relCharts map[string]*types.Chart
|
||||
}
|
||||
)
|
||||
|
||||
@@ -27,6 +32,9 @@ func NewComposePageState(res *resource.ComposePage, cfg *EncoderConfig) resource
|
||||
cfg: cfg,
|
||||
|
||||
res: res,
|
||||
|
||||
relMods: make(map[string]*types.Module),
|
||||
relCharts: make(map[string]*types.Chart),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +53,6 @@ func (n *composePageState) Prepare(ctx context.Context, s store.Storer, state *e
|
||||
return composeNamespaceErrUnresolved(n.res.NsRef.Identifiers)
|
||||
}
|
||||
|
||||
// Can't do anything else, since the NS doesn't yet exist
|
||||
if n.relNS.ID <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get related module
|
||||
// If this isn't a record page, there is no related module
|
||||
if n.res.ModRef != nil {
|
||||
@@ -62,6 +65,45 @@ func (n *composePageState) Prepare(ctx context.Context, s store.Storer, state *e
|
||||
}
|
||||
}
|
||||
|
||||
// Get parent page
|
||||
if n.res.ParentRef != nil {
|
||||
n.relParent, err = findComposePageRS(ctx, s, n.relNS.ID, state.ParentResources, n.res.ParentRef.Identifiers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n.relParent == nil {
|
||||
return composePageErrUnresolved(n.res.ParentRef.Identifiers)
|
||||
}
|
||||
}
|
||||
|
||||
// Get other related modules
|
||||
for _, mr := range n.res.ModRefs {
|
||||
mod, err := findComposeModuleRS(ctx, s, n.relNS.ID, state.ParentResources, mr.Identifiers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mod == nil {
|
||||
return composeModuleErrUnresolved(mr.Identifiers)
|
||||
}
|
||||
for id := range mr.Identifiers {
|
||||
n.relMods[id] = mod
|
||||
}
|
||||
}
|
||||
|
||||
// Get related charts
|
||||
for _, cr := range n.res.ChartRefs {
|
||||
chr, err := findComposeChartRS(ctx, s, n.relNS.ID, state.ParentResources, cr.Identifiers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if chr == nil {
|
||||
return composeChartErrUnresolved(cr.Identifiers)
|
||||
}
|
||||
for id := range cr.Identifiers {
|
||||
n.relCharts[id] = chr
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get the original page
|
||||
n.pg, err = findComposePageS(ctx, s, n.relNS.ID, makeGenericFilter(n.res.Identifiers()))
|
||||
if err != nil {
|
||||
@@ -83,7 +125,7 @@ func (n *composePageState) Encode(ctx context.Context, s store.Storer, state *en
|
||||
res.ID = n.pg.ID
|
||||
}
|
||||
if res.ID <= 0 {
|
||||
res.ID = nextID()
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
@@ -111,6 +153,73 @@ func (n *composePageState) Encode(ctx context.Context, s store.Storer, state *en
|
||||
}
|
||||
}
|
||||
|
||||
// Parent?
|
||||
if n.res.ParentRef != nil {
|
||||
res.SelfID = n.relParent.ID
|
||||
if res.SelfID <= 0 {
|
||||
mod := findComposePageR(state.ParentResources, n.res.ParentRef.Identifiers)
|
||||
res.SelfID = mod.ID
|
||||
}
|
||||
}
|
||||
|
||||
// Blocks
|
||||
getModID := func(id string) uint64 {
|
||||
mod := n.relMods[id]
|
||||
if mod == nil || mod.ID <= 0 {
|
||||
mod = findComposeModuleR(state.ParentResources, resource.MakeIdentifiers(id))
|
||||
if mod == nil || mod.ID <= 0 {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return mod.ID
|
||||
}
|
||||
|
||||
for _, b := range res.Blocks {
|
||||
switch b.Kind {
|
||||
case "RecordList":
|
||||
id, _ := b.Options["module"].(string)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
mID := getModID(id)
|
||||
if mID <= 0 {
|
||||
return composeModuleErrUnresolved(resource.MakeIdentifiers(id))
|
||||
}
|
||||
b.Options["module"] = mID
|
||||
|
||||
case "Chart":
|
||||
id, _ := b.Options["chart"].(string)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
chr := n.relCharts[id]
|
||||
if chr == nil || chr.ID <= 0 {
|
||||
ii := resource.MakeIdentifiers(id)
|
||||
chr = findComposeChartR(state.ParentResources, ii)
|
||||
if chr == nil || chr.ID <= 0 {
|
||||
return composeChartErrUnresolved(ii)
|
||||
}
|
||||
}
|
||||
b.Options["chart"] = chr.ID
|
||||
|
||||
case "Metric":
|
||||
mm, _ := b.Options["metrics"].([]interface{})
|
||||
for _, m := range mm {
|
||||
mops, _ := m.(map[string]interface{})
|
||||
id, _ := mops["module"].(string)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
mID := getModID(id)
|
||||
if mID <= 0 {
|
||||
return composeModuleErrUnresolved(resource.MakeIdentifiers(id))
|
||||
}
|
||||
mops["module"] = mID
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a fresh page
|
||||
if !exists {
|
||||
return store.CreateComposePage(ctx, s, res)
|
||||
@@ -167,11 +276,15 @@ func mergeComposePage(a, b *types.Page) *types.Page {
|
||||
//
|
||||
// Provided resources are prioritized.
|
||||
func findComposePageRS(ctx context.Context, s store.Storer, nsID uint64, rr resource.InterfaceSet, ii resource.Identifiers) (pg *types.Page, err error) {
|
||||
pg = findComposePageR(ctx, rr, ii)
|
||||
pg = findComposePageR(rr, ii)
|
||||
if pg != nil {
|
||||
return pg, nil
|
||||
}
|
||||
|
||||
if nsID <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Go in the store
|
||||
return findComposePageS(ctx, s, nsID, makeGenericFilter(ii))
|
||||
}
|
||||
@@ -204,7 +317,7 @@ func findComposePageS(ctx context.Context, s store.Storer, nsID uint64, gf gener
|
||||
}
|
||||
|
||||
// findComposePageR looks for the page in the resources
|
||||
func findComposePageR(ctx context.Context, rr resource.InterfaceSet, ii resource.Identifiers) (pg *types.Page) {
|
||||
func findComposePageR(rr resource.InterfaceSet, ii resource.Identifiers) (pg *types.Page) {
|
||||
var pgRes *resource.ComposePage
|
||||
|
||||
rr.Walk(func(r resource.Interface) error {
|
||||
@@ -225,3 +338,7 @@ func findComposePageR(ctx context.Context, rr resource.InterfaceSet, ii resource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func composePageErrUnresolved(ii resource.Identifiers) error {
|
||||
return fmt.Errorf("compose page unresolved %v", ii.StringSlice())
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func (n *composeRecordState) Encode(ctx context.Context, s store.Storer, state *
|
||||
if rec.ID <= 0 && exists {
|
||||
rec.ID = rm[r.ID].ID
|
||||
} else {
|
||||
rec.ID = nextID()
|
||||
rec.ID = NextID()
|
||||
}
|
||||
|
||||
im[r.ID] = rec.ID
|
||||
|
||||
@@ -124,11 +124,14 @@ func (se *storeEncoder) Prepare(ctx context.Context, ee ...*envoy.ResourceState)
|
||||
}
|
||||
|
||||
// Encode encodes available resource states using the given store encoder
|
||||
func (se *storeEncoder) Encode(ctx context.Context, rc envoy.Rc) error {
|
||||
func (se *storeEncoder) Encode(ctx context.Context, p envoy.Provider) error {
|
||||
var e *envoy.ResourceState
|
||||
return store.Tx(ctx, se.s, func(ctx context.Context, s store.Storer) (err error) {
|
||||
for {
|
||||
e = <-rc
|
||||
e, err = p.Next(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -142,7 +145,6 @@ func (se *storeEncoder) Encode(ctx context.Context, rc envoy.Rc) error {
|
||||
|
||||
if err != nil {
|
||||
return se.WrapError("encode", e.Res, err)
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -87,19 +87,25 @@ func (n *rbacRuleState) Encode(ctx context.Context, s store.Storer, state *envoy
|
||||
rule.Resource = rule.Resource.AppendWildcard()
|
||||
}
|
||||
|
||||
// There isn't anything to merge really, so Skip & MergeLeft skip it;
|
||||
// Replace & MergeRight replace it.
|
||||
//
|
||||
// Replacing is handled after
|
||||
switch n.cfg.OnExisting {
|
||||
case Skip,
|
||||
MergeLeft:
|
||||
return nil
|
||||
ee, _ := rbacRules.Filter(func(r *rbac.Rule) (bool, error) {
|
||||
return (r.RoleID == rule.RoleID && r.Resource == rule.Resource && r.Operation == rule.Operation), nil
|
||||
})
|
||||
|
||||
if len(ee) <= 0 {
|
||||
rbacRules = rbacRules.Merge(rule)
|
||||
} else {
|
||||
// There isn't anything to merge really, so Skip & MergeLeft skip it;
|
||||
// Replace & MergeRight replace it.
|
||||
switch n.cfg.OnExisting {
|
||||
case Skip,
|
||||
MergeLeft:
|
||||
return nil
|
||||
}
|
||||
|
||||
rbacRules = rbacRules.Merge(rule)
|
||||
}
|
||||
|
||||
nrr := rbacRules.Merge(rule)
|
||||
d, u := nrr.Dirty()
|
||||
|
||||
d, u := rbacRules.Dirty()
|
||||
err = store.DeleteRbacRule(ctx, s, d...)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -110,8 +116,7 @@ func (n *rbacRuleState) Encode(ctx context.Context, s store.Storer, state *envoy
|
||||
return
|
||||
}
|
||||
|
||||
nrr.Clear()
|
||||
rbacRules = nrr
|
||||
rbacRules.Clear()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ func (n *roleState) Encode(ctx context.Context, s store.Storer, state *envoy.Res
|
||||
rl.ID = n.rl.ID
|
||||
}
|
||||
if rl.ID <= 0 {
|
||||
rl.ID = nextID()
|
||||
rl.ID = NextID()
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
|
||||
@@ -74,8 +74,11 @@ func (n *settingsState) Encode(ctx context.Context, s store.Storer, state *envoy
|
||||
ss = append(ss, ns)
|
||||
}
|
||||
}
|
||||
|
||||
return store.UpsertSetting(ctx, s, ss...)
|
||||
err = store.TruncateSettings(ctx, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return store.CreateSetting(ctx, s, ss...)
|
||||
}
|
||||
|
||||
// mergeSettings merges b into a, prioritising a
|
||||
|
||||
@@ -55,7 +55,7 @@ func (n *userState) Encode(ctx context.Context, s store.Storer, state *envoy.Res
|
||||
res.ID = n.u.ID
|
||||
}
|
||||
if res.ID <= 0 {
|
||||
res.ID = nextID()
|
||||
res.ID = NextID()
|
||||
}
|
||||
|
||||
// This is not possible, but let's do it anyway
|
||||
|
||||
@@ -22,8 +22,8 @@ var (
|
||||
// we'll use the pkg/handle to check for handles.
|
||||
refy = regexp.MustCompile(`^[1-9](\d*)$`)
|
||||
|
||||
// wrapper around nextID that will aid service testing
|
||||
nextID = func() uint64 {
|
||||
// wrapper around NextID that will aid service testing
|
||||
NextID = func() uint64 {
|
||||
return id.Next()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy"
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy/resource"
|
||||
es "github.com/cortezaproject/corteza-server/pkg/envoy/store"
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy/yaml"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/store/sqlite3"
|
||||
stypes "github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type (
|
||||
tc struct {
|
||||
name string
|
||||
suite string
|
||||
file string
|
||||
|
||||
// Before the data gets processed
|
||||
pre func() error
|
||||
// After the data gets processed
|
||||
post func(req *require.Assertions, err error)
|
||||
// Data assertions
|
||||
check func(req *require.Assertions)
|
||||
}
|
||||
)
|
||||
|
||||
func initStore(ctx context.Context) (store.Storer, error) {
|
||||
s, err := sqlite3.ConnectInMemoryWithDebug(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = store.Upgrade(ctx, zap.NewNop(), s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func yd(ctx context.Context, suite, fname string) ([]resource.Interface, error) {
|
||||
fp := path.Join("testdata", suite, fname)
|
||||
|
||||
f, err := os.Open(fp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
info, err := os.Stat(fp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := yaml.Decoder(nil)
|
||||
return d.Decode(ctx, f, info)
|
||||
}
|
||||
|
||||
func encode(ctx context.Context, s store.Storer, nn []resource.Interface) error {
|
||||
se := es.NewStoreEncoder(s, nil)
|
||||
bld := envoy.NewGraphBuilder(se)
|
||||
g, err := bld.Build(ctx, nn...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return envoy.Encode(ctx, g, se)
|
||||
}
|
||||
|
||||
func storeNamespace(ctx context.Context, s store.Storer, nsID uint64, ss ...string) error {
|
||||
ns := &types.Namespace{
|
||||
ID: nsID,
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
ns.Slug = ss[0]
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
ns.Name = ss[1]
|
||||
}
|
||||
return store.CreateComposeNamespace(ctx, s, ns)
|
||||
}
|
||||
|
||||
func storeModule(ctx context.Context, s store.Storer, nsID, modID uint64, ss ...string) error {
|
||||
mod := &types.Module{
|
||||
ID: modID,
|
||||
NamespaceID: nsID,
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
mod.Handle = ss[0]
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
mod.Name = ss[1]
|
||||
}
|
||||
return store.CreateComposeModule(ctx, s, mod)
|
||||
}
|
||||
|
||||
func storeRole(ctx context.Context, s store.Storer, rID uint64, ss ...string) error {
|
||||
r := &stypes.Role{
|
||||
ID: rID,
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
r.Handle = ss[0]
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
r.Name = ss[1]
|
||||
}
|
||||
return store.CreateRole(ctx, s, r)
|
||||
}
|
||||
|
||||
// Helper to collect resulting errors, returning the first one
|
||||
func ce(ee ...error) error {
|
||||
for _, e := range ee {
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
su "github.com/cortezaproject/corteza-server/pkg/envoy/store"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestModuleRels(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, file string) (*require.Assertions, error) {
|
||||
req := require.New(t)
|
||||
|
||||
nn, err := yd(ctx, suite, file)
|
||||
req.NoError(err)
|
||||
|
||||
return req, encode(ctx, s, nn)
|
||||
}
|
||||
|
||||
cases := []*tc{
|
||||
{
|
||||
name: "simple mods; self ref",
|
||||
suite: "mod_rel",
|
||||
file: "modules_self_ref",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 10, "ns1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
mod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, 10, "mod1")
|
||||
req.NoError(err)
|
||||
req.NotNil(mod)
|
||||
|
||||
mod.Fields, _, err = store.SearchComposeModuleFields(ctx, s, types.ModuleFieldFilter{ModuleID: []uint64{mod.ID}})
|
||||
req.NoError(err)
|
||||
|
||||
ff := mod.Fields
|
||||
req.Len(ff, 1)
|
||||
req.Equal("Record", ff[0].Kind)
|
||||
req.Equal(mod.ID, uint64(ff[0].Options.Int64("module")))
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple mods; ref to peer",
|
||||
suite: "mod_rel",
|
||||
file: "modules_peer_ref",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeModuleFields(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
pmod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, 100, "mod2")
|
||||
req.NoError(err)
|
||||
req.NotNil(pmod)
|
||||
|
||||
mod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, 100, "mod1")
|
||||
req.NoError(err)
|
||||
req.NotNil(mod)
|
||||
|
||||
mod.Fields, _, err = store.SearchComposeModuleFields(ctx, s, types.ModuleFieldFilter{ModuleID: []uint64{mod.ID}})
|
||||
req.NoError(err)
|
||||
|
||||
ff := mod.Fields
|
||||
req.Len(ff, 1)
|
||||
req.Equal("Record", ff[0].Kind)
|
||||
req.Equal(pmod.ID, uint64(ff[0].Options.Int64("module")))
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple mods; ref to store",
|
||||
suite: "mod_rel",
|
||||
file: "modules_store_ref",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeModuleFields(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
storeModule(ctx, s, 100, 200, "mod2"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
smod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, 100, "mod2")
|
||||
req.NoError(err)
|
||||
req.NotNil(smod)
|
||||
|
||||
mod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, 100, "mod1")
|
||||
req.NoError(err)
|
||||
req.NotNil(mod)
|
||||
|
||||
mod.Fields, _, err = store.SearchComposeModuleFields(ctx, s, types.ModuleFieldFilter{ModuleID: []uint64{mod.ID}})
|
||||
req.NoError(err)
|
||||
|
||||
ff := mod.Fields
|
||||
req.Len(ff, 1)
|
||||
req.Equal("Record", ff[0].Kind)
|
||||
req.Equal(smod.ID, uint64(ff[0].Options.Int64("module")))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(fmt.Sprintf("%s; %s/%s", c.name, c.suite, c.file), func(t *testing.T) {
|
||||
err = c.pre()
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
req, err := prepare(ctx, s, t, c.suite, c.file+".yaml")
|
||||
c.post(req, err)
|
||||
c.check(req)
|
||||
})
|
||||
|
||||
ni = 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
su "github.com/cortezaproject/corteza-server/pkg/envoy/store"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
st "github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSimpleCases(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, file string) (*require.Assertions, error) {
|
||||
req := require.New(t)
|
||||
|
||||
nn, err := yd(ctx, suite, file)
|
||||
req.NoError(err)
|
||||
|
||||
return req, encode(ctx, s, nn)
|
||||
}
|
||||
|
||||
cases := []*tc{
|
||||
{
|
||||
name: "simple namespaces",
|
||||
suite: "simple",
|
||||
file: "namespaces",
|
||||
pre: func() (err error) {
|
||||
return s.TruncateComposeNamespaces(ctx)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
ns, err := store.LookupComposeNamespaceBySlug(ctx, s, "ns1")
|
||||
req.NoError(err)
|
||||
req.NotNil(ns)
|
||||
req.Equal("ns1", ns.Slug)
|
||||
req.Equal("ns1 name", ns.Name)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple mods; no namespace",
|
||||
suite: "simple",
|
||||
file: "modules_no_ns",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeModuleFields(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.Error(err)
|
||||
req.True(strings.Contains(err.Error(), "prepare compose module"))
|
||||
req.True(strings.Contains(err.Error(), "compose namespace unresolved"))
|
||||
},
|
||||
check: func(req *require.Assertions) {},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple mods",
|
||||
suite: "simple",
|
||||
file: "modules",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeModuleFields(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
mod, err := store.LookupComposeModuleByNamespaceIDHandle(ctx, s, 100, "mod1")
|
||||
req.NoError(err)
|
||||
req.NotNil(mod)
|
||||
|
||||
mod.Fields, _, err = store.SearchComposeModuleFields(ctx, s, types.ModuleFieldFilter{ModuleID: []uint64{mod.ID}})
|
||||
req.NoError(err)
|
||||
|
||||
req.Equal("mod1", mod.Handle)
|
||||
req.Equal("mod1 name", mod.Name)
|
||||
req.Equal(uint64(100), mod.NamespaceID)
|
||||
|
||||
ff := mod.Fields
|
||||
req.Len(ff, 1)
|
||||
req.Equal("f1", ff[0].Name)
|
||||
req.Equal("f1 label", ff[0].Label)
|
||||
req.Equal("String", ff[0].Kind)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple charts; no ns",
|
||||
suite: "simple",
|
||||
file: "charts_no_ns",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.Error(err)
|
||||
|
||||
req.True(strings.Contains(err.Error(), "prepare compose chart"))
|
||||
req.True(strings.Contains(err.Error(), "compose namespace unresolved"))
|
||||
},
|
||||
check: func(req *require.Assertions) {},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple charts; no mod",
|
||||
suite: "simple",
|
||||
file: "charts_no_mod",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.Error(err)
|
||||
|
||||
req.True(strings.Contains(err.Error(), "prepare compose chart"))
|
||||
req.True(strings.Contains(err.Error(), "compose module unresolved"))
|
||||
},
|
||||
check: func(req *require.Assertions) {},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple charts",
|
||||
suite: "simple",
|
||||
file: "charts",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
storeModule(ctx, s, 100, 200, "mod1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
chr, err := store.LookupComposeChartByNamespaceIDHandle(ctx, s, 100, "c1")
|
||||
req.NoError(err)
|
||||
req.NotNil(chr)
|
||||
|
||||
req.Equal("c1", chr.Handle)
|
||||
req.Equal("c1 name", chr.Name)
|
||||
|
||||
req.Len(chr.Config.Reports, 1)
|
||||
|
||||
req.Equal(uint64(200), chr.Config.Reports[0].ModuleID)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple pages; no ns",
|
||||
suite: "simple",
|
||||
file: "pages_no_ns",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
s.TruncateComposePages(ctx),
|
||||
)
|
||||
},
|
||||
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.Error(err)
|
||||
|
||||
req.True(strings.Contains(err.Error(), "prepare compose page"))
|
||||
req.True(strings.Contains(err.Error(), "compose namespace unresolved"))
|
||||
},
|
||||
check: func(req *require.Assertions) {},
|
||||
},
|
||||
|
||||
{
|
||||
name: "record pages; no mod",
|
||||
suite: "simple",
|
||||
file: "pages_r_no_mod",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
s.TruncateComposePages(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
)
|
||||
},
|
||||
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.Error(err)
|
||||
|
||||
req.True(strings.Contains(err.Error(), "prepare compose page"))
|
||||
req.True(strings.Contains(err.Error(), "compose module unresolved"))
|
||||
},
|
||||
check: func(req *require.Assertions) {},
|
||||
},
|
||||
|
||||
{
|
||||
name: "simple pages",
|
||||
suite: "simple",
|
||||
file: "pages",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
|
||||
check: func(req *require.Assertions) {
|
||||
pg, err := store.LookupComposePageByNamespaceIDHandle(ctx, s, 100, "pg1")
|
||||
req.NoError(err)
|
||||
req.NotNil(pg)
|
||||
|
||||
req.Equal("pg1", pg.Handle)
|
||||
req.Equal("pg1 name", pg.Title)
|
||||
req.Equal(uint64(0), pg.ModuleID)
|
||||
req.Equal(uint64(100), pg.NamespaceID)
|
||||
|
||||
req.Len(pg.Blocks, 1)
|
||||
req.Equal("block1", pg.Blocks[0].Title)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "record page",
|
||||
suite: "simple",
|
||||
file: "pages_r",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeCharts(ctx),
|
||||
s.TruncateComposePages(ctx),
|
||||
|
||||
storeNamespace(ctx, s, 100, "ns1"),
|
||||
storeModule(ctx, s, 100, 200, "mod1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
|
||||
check: func(req *require.Assertions) {
|
||||
pg, err := store.LookupComposePageByNamespaceIDHandle(ctx, s, 100, "pg1")
|
||||
req.NoError(err)
|
||||
req.NotNil(pg)
|
||||
|
||||
req.Equal("pg1", pg.Handle)
|
||||
req.Equal("pg1 name", pg.Title)
|
||||
req.Equal(uint64(100), pg.NamespaceID)
|
||||
req.Equal(uint64(200), pg.ModuleID)
|
||||
|
||||
req.Len(pg.Blocks, 1)
|
||||
req.Equal("block1", pg.Blocks[0].Title)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "applications",
|
||||
suite: "simple",
|
||||
file: "applications",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateApplications(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
|
||||
check: func(req *require.Assertions) {
|
||||
apps, _, err := store.SearchApplications(ctx, s, st.ApplicationFilter{
|
||||
Name: "app1",
|
||||
})
|
||||
req.NoError(err)
|
||||
req.NotNil(apps)
|
||||
req.Len(apps, 1)
|
||||
app := apps[0]
|
||||
|
||||
req.Equal("app1", app.Name)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "users",
|
||||
suite: "simple",
|
||||
file: "users",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateUsers(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
u, err := store.LookupUserByHandle(ctx, s, "u1")
|
||||
req.NoError(err)
|
||||
req.NotNil(u)
|
||||
|
||||
req.Equal("u1", u.Handle)
|
||||
req.Equal("u1 name", u.Name)
|
||||
req.Equal("u1@example.tld", u.Email)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "roles",
|
||||
suite: "simple",
|
||||
file: "roles",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateRoles(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
r, err := store.LookupRoleByHandle(ctx, s, "r1")
|
||||
req.NoError(err)
|
||||
req.NotNil(r)
|
||||
|
||||
req.Equal("r1", r.Handle)
|
||||
req.Equal("r1 name", r.Name)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "settings",
|
||||
suite: "simple",
|
||||
file: "settings",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateSettings(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
ss, _, err := store.SearchSettings(ctx, s, st.SettingsFilter{})
|
||||
req.NoError(err)
|
||||
req.NotNil(ss)
|
||||
req.Len(ss, 3)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "rbac rules; no role",
|
||||
suite: "simple",
|
||||
file: "rbac_rules_no_role",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateRoles(ctx),
|
||||
s.TruncateRbacRules(ctx),
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeModuleFields(ctx),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.Error(err)
|
||||
req.True(strings.Contains(err.Error(), "prepare rbac rule"))
|
||||
req.True(strings.Contains(err.Error(), "role unresolved"))
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "rbac rules",
|
||||
suite: "simple",
|
||||
file: "rbac_rules",
|
||||
pre: func() (err error) {
|
||||
return ce(
|
||||
s.TruncateRoles(ctx),
|
||||
s.TruncateRbacRules(ctx),
|
||||
s.TruncateComposeNamespaces(ctx),
|
||||
s.TruncateComposeModules(ctx),
|
||||
s.TruncateComposeModuleFields(ctx),
|
||||
|
||||
storeRole(ctx, s, 100, "r1"),
|
||||
)
|
||||
},
|
||||
post: func(req *require.Assertions, err error) {
|
||||
req.NoError(err)
|
||||
},
|
||||
check: func(req *require.Assertions) {
|
||||
rr, _, err := store.SearchRbacRules(ctx, s, rbac.RuleFilter{})
|
||||
req.NoError(err)
|
||||
req.NotNil(rr)
|
||||
req.Len(rr, 3)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(fmt.Sprintf("%s; %s/%s", c.name, c.suite, c.file), func(t *testing.T) {
|
||||
err = c.pre()
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
req, err := prepare(ctx, s, t, c.suite, c.file+".yaml")
|
||||
c.post(req, err)
|
||||
c.check(req)
|
||||
})
|
||||
ni = 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace: ns1
|
||||
modules:
|
||||
mod1:
|
||||
name: mod1 name
|
||||
fields:
|
||||
f1:
|
||||
label: f1 label
|
||||
kind: Record
|
||||
required: true
|
||||
options:
|
||||
module: mod2
|
||||
mod2:
|
||||
name: mod2 name
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace: ns1
|
||||
modules:
|
||||
mod1:
|
||||
name: mod1 name
|
||||
fields:
|
||||
f1:
|
||||
label: f1 label
|
||||
kind: Record
|
||||
required: true
|
||||
options:
|
||||
module: mod1
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace: ns1
|
||||
modules:
|
||||
mod1:
|
||||
name: mod1 name
|
||||
fields:
|
||||
f1:
|
||||
label: f1 label
|
||||
kind: Record
|
||||
required: true
|
||||
options:
|
||||
module: mod2
|
||||
@@ -0,0 +1,2 @@
|
||||
applications:
|
||||
- app1
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
namespace: ns1
|
||||
charts:
|
||||
c1:
|
||||
name: c1 name
|
||||
config:
|
||||
reports:
|
||||
- dimensions:
|
||||
- conditions: {}
|
||||
field: Rating
|
||||
meta: {}
|
||||
modifier: (no grouping / buckets)
|
||||
skipMissing: true
|
||||
filter: ""
|
||||
metrics:
|
||||
- aggregate: AVG
|
||||
field: count
|
||||
fill: true
|
||||
fixTooltips: false
|
||||
label: Number of Accounts
|
||||
lineTension: 0.4
|
||||
type: line
|
||||
module: mod1
|
||||
renderer: {}
|
||||
yAxis:
|
||||
label: Accounts
|
||||
colorScheme: tableau.Tableau10
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace: ns1
|
||||
charts:
|
||||
c1:
|
||||
name: c1 name
|
||||
config:
|
||||
reports:
|
||||
- dimensions:
|
||||
- conditions: {}
|
||||
field: Rating
|
||||
meta: {}
|
||||
modifier: (no grouping / buckets)
|
||||
skipMissing: true
|
||||
filter: ""
|
||||
metrics:
|
||||
- aggregate: AVG
|
||||
field: count
|
||||
fill: true
|
||||
fixTooltips: false
|
||||
label: Number of Accounts
|
||||
lineTension: 0.4
|
||||
type: line
|
||||
module: notThere
|
||||
renderer: {}
|
||||
yAxis:
|
||||
label: Accounts
|
||||
colorScheme: tableau.Tableau10
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace: notThere
|
||||
charts:
|
||||
c1:
|
||||
name: c1 name
|
||||
config:
|
||||
reports:
|
||||
- dimensions:
|
||||
- conditions: {}
|
||||
field: Rating
|
||||
meta: {}
|
||||
modifier: (no grouping / buckets)
|
||||
skipMissing: true
|
||||
filter: ""
|
||||
metrics:
|
||||
- aggregate: AVG
|
||||
field: count
|
||||
fill: true
|
||||
fixTooltips: false
|
||||
label: Number of Accounts
|
||||
lineTension: 0.4
|
||||
type: line
|
||||
module: mod1
|
||||
renderer: {}
|
||||
yAxis:
|
||||
label: Accounts
|
||||
colorScheme: tableau.Tableau10
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace: ns1
|
||||
modules:
|
||||
mod1:
|
||||
name: mod1 name
|
||||
fields:
|
||||
f1:
|
||||
label: f1 label
|
||||
kind: String
|
||||
required: true
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace: notThere
|
||||
modules:
|
||||
mod1:
|
||||
name: mod1 name
|
||||
fields:
|
||||
AccountName:
|
||||
label: REP
|
||||
kind: String
|
||||
required: true
|
||||
@@ -0,0 +1,3 @@
|
||||
namespaces:
|
||||
ns1:
|
||||
name: ns1 name
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
namespace: ns1
|
||||
pages:
|
||||
pg1:
|
||||
title: pg1 name
|
||||
blocks:
|
||||
- title: block1
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace: notThere
|
||||
|
||||
pages:
|
||||
pg1:
|
||||
title: pg1 name
|
||||
blocks:
|
||||
- title: block1
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace: ns1
|
||||
pages:
|
||||
pg1:
|
||||
title: pg1 name
|
||||
module: mod1
|
||||
blocks:
|
||||
- title: block1
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace: ns1
|
||||
|
||||
pages:
|
||||
pg1:
|
||||
title: pg1 name
|
||||
module: notThere
|
||||
blocks:
|
||||
- title: block1
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
allow:
|
||||
r1:
|
||||
compose:
|
||||
- access
|
||||
|
||||
deny:
|
||||
r1:
|
||||
compose:namespace:
|
||||
- access
|
||||
messaging:
|
||||
- access
|
||||
@@ -0,0 +1,11 @@
|
||||
allow:
|
||||
r1:
|
||||
compose:
|
||||
- access
|
||||
|
||||
deny:
|
||||
r1:
|
||||
compose:namespace:
|
||||
- access
|
||||
messaging:
|
||||
- access
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
roles:
|
||||
r1:
|
||||
name: r1 name
|
||||
@@ -0,0 +1,4 @@
|
||||
settings:
|
||||
privacy.mask.email: true
|
||||
privacy.mask.name: true
|
||||
auth.mail.email-confirmation.subject.en: Test
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
users:
|
||||
u1:
|
||||
name: u1 name
|
||||
email: u1@example.tld
|
||||
@@ -11,11 +11,14 @@ import (
|
||||
|
||||
type (
|
||||
composePage struct {
|
||||
res *types.Page
|
||||
children composePageSet
|
||||
res *types.Page
|
||||
children composePageSet
|
||||
|
||||
refNamespace string
|
||||
refModule string
|
||||
rbac rbacRuleSet
|
||||
refParent string
|
||||
|
||||
rbac rbacRuleSet
|
||||
}
|
||||
composePageSet []*composePage
|
||||
|
||||
@@ -59,6 +62,9 @@ func (wset composePageSet) setNamespaceRef(ref string) error {
|
||||
}
|
||||
|
||||
res.refNamespace = ref
|
||||
if res.children != nil {
|
||||
res.children.setNamespaceRef(ref)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -131,11 +137,27 @@ func (wrap *composePage) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
}
|
||||
|
||||
func (wrap composePage) MarshalEnvoy() ([]resource.Interface, error) {
|
||||
rs := resource.NewComposePage(wrap.res, wrap.refNamespace, wrap.refModule)
|
||||
rs := resource.NewComposePage(wrap.res, wrap.refNamespace, wrap.refModule, wrap.refParent)
|
||||
|
||||
return envoy.CollectNodes(
|
||||
rs,
|
||||
wrap.children.bindParent(rs),
|
||||
wrap.rbac.bindResource(rs),
|
||||
|
||||
// @todo Not sure yet
|
||||
// wrap.children,
|
||||
)
|
||||
}
|
||||
|
||||
func (rr composePageSet) bindParent(res resource.Interface) composePageSet {
|
||||
rtr := make(composePageSet, 0, len(rr))
|
||||
for _, r := range rr {
|
||||
idd := res.Identifiers().StringSlice()
|
||||
if len(idd) > 0 {
|
||||
r.refParent = idd[0]
|
||||
}
|
||||
rtr = append(rtr, r)
|
||||
}
|
||||
|
||||
return rtr
|
||||
}
|
||||
|
||||
@@ -72,9 +72,6 @@ func (doc *Document) Decode(ctx context.Context, l loader) ([]resource.Interface
|
||||
if doc.rbac != nil {
|
||||
mm = append(mm, doc.rbac)
|
||||
}
|
||||
if doc.users != nil {
|
||||
mm = append(mm, doc.users)
|
||||
}
|
||||
|
||||
for _, m := range mm {
|
||||
if tmp, err := m.MarshalEnvoy(); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user