diff --git a/pkg/envoy/tests/main.go b/pkg/envoy/tests/main.go index b2f992fbb..f9b78b1ec 100644 --- a/pkg/envoy/tests/main.go +++ b/pkg/envoy/tests/main.go @@ -7,6 +7,7 @@ import ( "github.com/cortezaproject/corteza-server/compose/types" "github.com/cortezaproject/corteza-server/pkg/envoy" + "github.com/cortezaproject/corteza-server/pkg/envoy/directory" "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" @@ -64,6 +65,13 @@ func yd(ctx context.Context, suite, fname string) ([]resource.Interface, error) return d.Decode(ctx, f, info) } +func dd(ctx context.Context, suite string) ([]resource.Interface, error) { + fp := path.Join("testdata", suite) + d := yaml.Decoder(nil) + + return directory.Decode(ctx, fp, d) +} + func encode(ctx context.Context, s store.Storer, nn []resource.Interface) error { se := es.NewStoreEncoder(s, nil) bld := envoy.NewGraphBuilder(se) diff --git a/pkg/envoy/tests/provision_test.go b/pkg/envoy/tests/provision_test.go new file mode 100644 index 000000000..a62f1cc52 --- /dev/null +++ b/pkg/envoy/tests/provision_test.go @@ -0,0 +1,187 @@ +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/pkg/rbac" + "github.com/cortezaproject/corteza-server/store" + "github.com/stretchr/testify/require" +) + +func TestProvision(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) + + return req, encode(ctx, s, nn) + } + + fullModLoad := func(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 + } + + getOptSlice := func(req *require.Assertions, key string, f *types.ModuleField) []interface{} { + opt, _ := (f.Options[key]).([]interface{}) + req.NotNil(opt) + return opt + } + + cases := []*tc{ + { + name: "simple provision set", + suite: "provision", + pre: func() (err error) { + s, err = initStore(ctx) + return ce( + err, + storeRole(ctx, s, 1, "everyone"), + storeRole(ctx, s, 2, "admins"), + ) + }, + post: func(req *require.Assertions, err error) { + req.NoError(err) + }, + check: func(req *require.Assertions) { + // Checkup AC + rrls, _, err := store.SearchRbacRules(ctx, s, rbac.RuleFilter{}) + req.NoError(err) + req.NotNil(rrls) + req.Len(rrls, 14) + // ----------- + + // Checkup namespaces + ns, err := store.LookupComposeNamespaceBySlug(ctx, s, "ns1") + req.NoError(err) + req.NotNil(ns) + // ----------- + + // Checkup modules + m1, err := fullModLoad(ctx, s, req, ns.ID, "mod1") + m2, err := fullModLoad(ctx, s, req, ns.ID, "mod2") + m3, err := fullModLoad(ctx, s, req, ns.ID, "mod3") + + // mod1 + req.Len(m1.Fields, 4) + req.Equal("String", m1.Fields[0].Kind) + + req.Equal("Select", m1.Fields[1].Kind) + opt := getOptSlice(req, "options", m1.Fields[1]) + req.Equal([]interface{}{"f2 opt 1", "f2 opt 2", "f2 opt 3"}, opt) + + req.Equal("Select", m1.Fields[2].Kind) + opt = getOptSlice(req, "options", m1.Fields[2]) + req.Equal([]interface{}{"☆☆☆☆☆", "★☆☆☆☆"}, opt) + + req.Equal("Record", m1.Fields[3].Kind) + req.Equal(m2.ID, uint64(m1.Fields[3].Options.Int64("module"))) + opt = getOptSlice(req, "queryFields", m1.Fields[3]) + req.Equal([]interface{}{"f1"}, opt) + + // mod2 + req.Len(m1.Fields, 4) + + req.Equal("Record", m2.Fields[1].Kind) + req.Equal(m2.ID, uint64(m2.Fields[1].Options.Int64("module"))) + opt = getOptSlice(req, "queryFields", m2.Fields[1]) + req.Equal([]interface{}{"f1"}, opt) + + req.Equal("Record", m2.Fields[3].Kind) + req.Equal(m3.ID, uint64(m2.Fields[3].Options.Int64("module"))) + opt = getOptSlice(req, "queryFields", m2.Fields[3]) + req.Equal([]interface{}{"f1"}, opt) + // ----------- + + // Checkup charts + ch1, err := store.LookupComposeChartByNamespaceIDHandle(ctx, s, ns.ID, "chr1") + req.NoError(err) + req.NotNil(ch1) + + req.Len(ch1.Config.Reports, 1) + r := ch1.Config.Reports[0] + req.Len(r.Dimensions, 1) + req.Len(r.Metrics, 1) + req.Equal(m1.ID, r.ModuleID) + // ----------- + + // Checkup pages + pg1, err := store.LookupComposePageByNamespaceIDHandle(ctx, s, ns.ID, "pg1") + req.NoError(err) + req.NotNil(pg1) + pg2, err := store.LookupComposePageByNamespaceIDHandle(ctx, s, ns.ID, "rpg2") + req.NoError(err) + req.NotNil(pg2) + + // pg1 + req.Len(pg1.Blocks, 3) + + req.Equal("Content", pg1.Blocks[0].Kind) + req.Equal("pg1 b1 content body", pg1.Blocks[0].Options["body"]) + + req.Equal("RecordList", pg1.Blocks[1].Kind) + req.Equal(m1.ID, uint64((pg1.Blocks[1].Options["module"]).(float64))) + + req.Equal("Chart", pg1.Blocks[2].Kind) + req.Equal(ch1.ID, uint64((pg1.Blocks[2].Options["chart"]).(float64))) + + // pg2 + req.Equal(m1.ID, pg2.ModuleID) + req.Equal(pg1.ID, pg2.SelfID) + + req.Equal("Record", pg2.Blocks[0].Kind) + // ----------- + + // Checkup settings records + ms, err := fullModLoad(ctx, s, req, ns.ID, "settings") + rr, _, err := store.SearchComposeRecords(ctx, s, ms, types.RecordFilter{}) + req.NoError(err) + req.Len(rr, 1) + + sr := rr[0] + req.Equal("s1 value", sr.Values.Get("s1", 0).Value) + req.Equal("1", sr.Values.Get("s2", 0).Value) + // ----------- + }, + }, + } + + for _, c := range cases { + t.Run(fmt.Sprintf("%s; %s", c.name, c.suite), func(t *testing.T) { + err = c.pre() + if err != nil { + t.Fatal(err.Error()) + } + req, err := prepare(ctx, s, t, c.suite) + c.post(req, err) + c.check(req) + }) + + ni = 0 + } +} diff --git a/pkg/envoy/tests/testdata/provision/0000_access_control.yaml b/pkg/envoy/tests/testdata/provision/0000_access_control.yaml new file mode 100644 index 000000000..80b4c0b9e --- /dev/null +++ b/pkg/envoy/tests/testdata/provision/0000_access_control.yaml @@ -0,0 +1,33 @@ +allow: + everyone: + compose: + - op1 + + compose:namespace: + - op1 + + admins: + compose: + - op1 + - op1.sub + + compose:namespace: + - op1 + - op1.sub + +deny: + everyone: + compose: + - op2 + + compose:namespace: + - op2 + + admins: + compose: + - op2 + - op2.sub + + compose:namespace: + - op2 + - op2.sub diff --git a/pkg/envoy/tests/testdata/provision/1000_namespace.yaml b/pkg/envoy/tests/testdata/provision/1000_namespace.yaml new file mode 100644 index 000000000..5ab104d1f --- /dev/null +++ b/pkg/envoy/tests/testdata/provision/1000_namespace.yaml @@ -0,0 +1,10 @@ +namespaces: + ns1: + name: ns1 name + + allow: + everyone: + - op1 + deny: + everyone: + - op2 diff --git a/pkg/envoy/tests/testdata/provision/1100_modules.yaml b/pkg/envoy/tests/testdata/provision/1100_modules.yaml new file mode 100644 index 000000000..9ad381d38 --- /dev/null +++ b/pkg/envoy/tests/testdata/provision/1100_modules.yaml @@ -0,0 +1,80 @@ +# Provides a complete set of things to cover regarding modules and module fields. +# mod1: defines more complicated fields, relates to mod2 +# mod2: defines a self-ref, relates to mod3 +# mod3: just a placeholder + +namespace: ns1 +modules: + mod1: + name: mod1 name + fields: + f1: + label: f1 label + kind: String + required: true + f2: + label: f2 label + kind: Select + options: + options: + - f2 opt 1 + - f2 opt 2 + - f2 opt 3 + f3: + label: f3 label + kind: Select + options: + options: + - ☆☆☆☆☆ + - ★☆☆☆☆ + f4: + label: f4 label + kind: Record + options: + labelField: f_label + module: mod2 + queryFields: + - f1 + + mod2: + name: mod2 name + fields: + f_label: + label: f_label record label + f_ref_self: + label: f_ref_self label + kind: Record + options: + labelField: f_label + module: mod2 + queryFields: + - f1 + f1: + label: f1 label + kind: String + required: true + f2: + label: f2 label + kind: Record + options: + labelField: f_label + module: mod3 + queryFields: + - f1 + + mod3: + name: mod3 name + fields: + f_label: + label: f_label record label + + settings: + name: settings + fields: + s1: + label: s1 label + kind: String + + s2: + label: s2 label + kind: Bool diff --git a/pkg/envoy/tests/testdata/provision/1200_pages.yaml b/pkg/envoy/tests/testdata/provision/1200_pages.yaml new file mode 100644 index 000000000..477d0a67f --- /dev/null +++ b/pkg/envoy/tests/testdata/provision/1200_pages.yaml @@ -0,0 +1,48 @@ +namespace: ns1 +pages: + pg1: + title: pg1 title + blocks: + - title: pg1 b1 + kind: Content + xywh: [0, 0, 1, 1] + options: + body: pg1 b1 content body + + - title: pg1 b2 + kind: RecordList + xywh: [0, 1, 1, 1] + options: + module: mod1 + fields: + - name: f1 + - name: f2 + variants: + bodyBg: white + border: primary + headerBg: white + headerText: primary + + - title: pg1 b3 + kind: Chart + xywh: [0, 2, 1, 1] + options: + chart: chr1 + variants: + bodyBg: white + border: primary + headerBg: white + headerText: primary + + children: + rpg2: + handle: rpg2 + module: mod1 + title: Record page for module "mod1" + blocks: + - title: rpg2 b1 title + kind: Record + options: + fields: + - name: f1 + - name: f2 diff --git a/pkg/envoy/tests/testdata/provision/1300_charts.yaml b/pkg/envoy/tests/testdata/provision/1300_charts.yaml new file mode 100644 index 000000000..f08bbe9ba --- /dev/null +++ b/pkg/envoy/tests/testdata/provision/1300_charts.yaml @@ -0,0 +1,18 @@ +namespace: ns1 +charts: + chr1: + name: chr1 name + config: + reports: + - dimensions: + - field: Status + modifier: (no grouping / buckets) + filter: "" + metrics: + - backgroundColor: '#11ff57' + field: count + fixTooltips: true + type: pie + module: mod1 + renderer: {} + colorScheme: tableau.Tableau10 diff --git a/pkg/envoy/tests/testdata/provision/1400_record_settings.yaml b/pkg/envoy/tests/testdata/provision/1400_record_settings.yaml new file mode 100644 index 000000000..a0cd4bb55 --- /dev/null +++ b/pkg/envoy/tests/testdata/provision/1400_record_settings.yaml @@ -0,0 +1,6 @@ +namespace: ns1 +records: + settings: + - values: + s1: s1 value + s2: true