diff --git a/pkg/envoy/yaml/compose_record.go b/pkg/envoy/yaml/compose_record.go index 27ac8331b..7ba695080 100644 --- a/pkg/envoy/yaml/compose_record.go +++ b/pkg/envoy/yaml/compose_record.go @@ -82,17 +82,22 @@ func (wset composeRecordSet) MarshalEnvoy() ([]resource.Interface, error) { } ) - // moduleRef to values set - recMap := make(map[string]*rw) + // We'll do a list of wrappers & a map of wrappers to preserve order and keep + // optimal lookups + rww := make([]*rw, 0, len(wset)) + rrx := make(map[string]*rw) for _, res := range wset { - if recMap[res.refModule] == nil { - recMap[res.refModule] = &rw{ + // A bit stronger index just in case + ix := res.refNamespace + "/" + res.refModule + if _, ok := rrx[ix]; !ok { + rrx[ix] = &rw{ rr: make(resource.ComposeRecordRawSet, 0, 10), nsRef: res.refNamespace, modRef: res.refModule, refUser: make(resource.Identifiers), } + rww = append(rww, rrx[ix]) } r := &resource.ComposeRecordRaw{ @@ -104,19 +109,21 @@ func (wset composeRecordSet) MarshalEnvoy() ([]resource.Interface, error) { Us: res.us, } - recMap[res.refModule].refUser.Add( + rrx[ix].refUser.Add( res.us.CreatedBy, res.us.UpdatedBy, res.us.DeletedBy, res.us.OwnedBy, ) - recMap[res.refModule].rr = append(recMap[res.refModule].rr, r) + rrx[ix].rr = append(rrx[ix].rr, r) } - for _, w := range recMap { + for _, w := range rww { + cw := *w + walker := func(f func(r *resource.ComposeRecordRaw) error) error { - for _, r := range w.rr { + for _, r := range cw.rr { err := f(r) if err != nil { return err diff --git a/pkg/envoy/yaml/compose_record_test.go b/pkg/envoy/yaml/compose_record_test.go index 2cd46d59f..8c89728c6 100644 --- a/pkg/envoy/yaml/compose_record_test.go +++ b/pkg/envoy/yaml/compose_record_test.go @@ -1,8 +1,10 @@ package yaml import ( + "fmt" "testing" + "github.com/cortezaproject/corteza-server/pkg/envoy/resource" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" ) @@ -63,3 +65,26 @@ func TestComposeRecord_UnmarshalYAML(t *testing.T) { //req.NotEmpty(doc.compose.records[0].rbac.rules) }) } + +func TestComposeRecord_MarshalEnvoy(t *testing.T) { + t.Run("compose record file 2", func(t *testing.T) { + req := require.New(t) + + doc, err := parseDocument("compose_record_2") + rr, err := doc.compose.MarshalEnvoy() + req.NoError(err) + req.Len(rr, 3) + + for ri, r := range rr { + rec, ok := r.(*resource.ComposeRecord) + req.True(ok) + req.NotNil(rec) + + rec.Walker(func(r *resource.ComposeRecordRaw) error { + req.Equal(fmt.Sprintf("mod%d f1 v1", ri+1), r.Values["f1"]) + req.Equal(fmt.Sprintf("mod%d f2 v1", ri+1), r.Values["f2"]) + return nil + }) + } + }) +} diff --git a/pkg/envoy/yaml/testdata/compose_record_2.yaml b/pkg/envoy/yaml/testdata/compose_record_2.yaml new file mode 100644 index 000000000..438a0a487 --- /dev/null +++ b/pkg/envoy/yaml/testdata/compose_record_2.yaml @@ -0,0 +1,14 @@ +namespace: service-solution +records: + mod1: + - values: + f1: "mod1 f1 v1" + f2: "mod1 f2 v1" + mod2: + - values: + f1: "mod2 f1 v1" + f2: "mod2 f2 v1" + mod3: + - values: + f1: "mod3 f1 v1" + f2: "mod3 f2 v1" diff --git a/tests/envoy/simple_test.go b/tests/envoy/simple_test.go index a694f0d02..0b35cd363 100644 --- a/tests/envoy/simple_test.go +++ b/tests/envoy/simple_test.go @@ -552,6 +552,51 @@ func TestSimpleCases(t *testing.T) { }, }, + { + name: "simple records; multiple", + suite: "simple", + file: "records_multi", + pre: func() (err error) { + return ce( + s.TruncateComposeNamespaces(ctx), + s.TruncateComposeModules(ctx), + s.TruncateComposeModuleFields(ctx), + s.TruncateComposeRecords(ctx, nil), + + storeNamespace(ctx, s, 100, "ns1"), + storeModule(ctx, s, 100, 200, "mod1"), + storeModuleField(ctx, s, 200, 300, "f1"), + + storeModule(ctx, s, 100, 201, "mod2"), + storeModuleField(ctx, s, 201, 301, "f1"), + ) + }, + post: func(req *require.Assertions, err error) { + req.NoError(err) + }, + check: func(req *require.Assertions) { + mod1, err := store.LookupComposeModuleByID(ctx, s, 200) + req.NoError(err) + req.NotNil(mod1) + + mod2, err := store.LookupComposeModuleByID(ctx, s, 201) + req.NoError(err) + req.NotNil(mod2) + + rr, _, err := store.SearchComposeRecords(ctx, s, mod1, types.RecordFilter{ModuleID: mod1.ID, NamespaceID: mod1.NamespaceID}) + req.NoError(err) + req.NotNil(rr) + req.Len(rr, 1) + req.Equal("mod1 f1 v1", rr[0].Values[0].Value) + + rr, _, err = store.SearchComposeRecords(ctx, s, mod2, types.RecordFilter{ModuleID: mod2.ID, NamespaceID: mod2.NamespaceID}) + req.NoError(err) + req.NotNil(rr) + req.Len(rr, 1) + req.Equal("mod2 f1 v1", rr[0].Values[0].Value) + }, + }, + { name: "simple records; conditional", suite: "simple", diff --git a/tests/envoy/testdata/simple/records_multi.yaml b/tests/envoy/testdata/simple/records_multi.yaml new file mode 100644 index 000000000..5082c0f5b --- /dev/null +++ b/tests/envoy/testdata/simple/records_multi.yaml @@ -0,0 +1,8 @@ +namespace: ns1 +records: + mod1: + - values: + f1: "mod1 f1 v1" + mod2: + - values: + f1: "mod2 f1 v1"