diff --git a/pkg/collaborators/events.go b/pkg/collaborators/events.go new file mode 100644 index 0000000000000000000000000000000000000000..a9a46eb0ac1b8b98cdadbb3ab8b721154c03c838 --- /dev/null +++ b/pkg/collaborators/events.go @@ -0,0 +1,9 @@ +package collaborators + +const ( + EventSet = "collaborators.set" + EventGet = "collaborators.get" + EventRemove = "collaborators.remove" + EventListCollaborators = "collaborators.list_collaborators" + EventListSpaces = "collaborators.list_Spaces" +) diff --git a/pkg/collaborators/middleware/logging_middleware.go b/pkg/collaborators/middleware/logging_middleware.go new file mode 100644 index 0000000000000000000000000000000000000000..7bbdca3e1414f03c23838280e25aaec9425877bb --- /dev/null +++ b/pkg/collaborators/middleware/logging_middleware.go @@ -0,0 +1,103 @@ +package middleware + +import ( + "context" + "fmt" + + "git.perx.ru/perxis/perxis-go/id" + "git.perx.ru/perxis/perxis-go/pkg/collaborators" + logzap "git.perx.ru/perxis/perxis-go/zap" + "go.uber.org/zap" +) + +type loggingMiddleware struct { + logger *zap.Logger + next collaborators.Collaborators +} + +func LoggingMiddleware(logger *zap.Logger) Middleware { + return func(next collaborators.Collaborators) collaborators.Collaborators { + return &loggingMiddleware{ + next: next, + logger: logger.With(logzap.Component("Collaborators")), + } + } +} + +func (m *loggingMiddleware) Set(ctx context.Context, spaceId, subject, role string) (err error) { + logger := m.logger.With( + logzap.Caller(ctx), + logzap.Event(collaborators.EventSet), + logzap.Object(id.NewSpaceId(spaceId)), + ) + + err = m.next.Set(ctx, spaceId, subject, role) + if err != nil { + logger.Error(fmt.Sprintf("Failed to set user '%s' as a member with role '%s'", subject, role), zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return + } + + logger.Info(fmt.Sprintf("User '%s' assigned to role '%s'", subject, spaceId), logzap.Channels(logzap.Userlog)) + + return err +} + +func (m *loggingMiddleware) Get(ctx context.Context, spaceId, subject string) (role string, err error) { + logger := m.logger.With( + logzap.Caller(ctx), + ) + + role, err = m.next.Get(ctx, spaceId, subject) + if err != nil { + logger.Error("Failed to get", zap.Error(err)) + return + } + + return role, err +} + +func (m *loggingMiddleware) Remove(ctx context.Context, spaceId, subject string) (err error) { + logger := m.logger.With( + logzap.Caller(ctx), + logzap.Event(collaborators.EventRemove), + logzap.Object(id.NewSpaceId(spaceId)), + ) + + err = m.next.Remove(ctx, spaceId, subject) + if err != nil { + logger.Error(fmt.Sprintf("Failed to remove user '%s' from space '%s'", subject, spaceId), zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return + } + + logger.Info(fmt.Sprintf("User '%s' removed from space '%s'", subject, spaceId), logzap.Channels(logzap.Userlog)) + + return err +} + +func (m *loggingMiddleware) ListCollaborators(ctx context.Context, spaceId string) (collaborators []*collaborators.Collaborator, err error) { + logger := m.logger.With( + logzap.Caller(ctx), + ) + + collaborators, err = m.next.ListCollaborators(ctx, spaceId) + if err != nil { + logger.Error("Failed to list collaborators", zap.Error(err)) + return + } + + return collaborators, err +} + +func (m *loggingMiddleware) ListSpaces(ctx context.Context, subject string) (spaces []*collaborators.Collaborator, err error) { + logger := m.logger.With( + logzap.Caller(ctx), + ) + + spaces, err = m.next.ListSpaces(ctx, subject) + if err != nil { + logger.Error("Failed to list spaces", zap.Error(err)) + return + } + + return spaces, err +} diff --git a/pkg/collaborators/middleware/middleware.go b/pkg/collaborators/middleware/middleware.go index 28f0bc687c5ee66f2395303efa502149f8394644..a336e089fc00e9984ba4ddb1c9d656a46d98c493 100644 --- a/pkg/collaborators/middleware/middleware.go +++ b/pkg/collaborators/middleware/middleware.go @@ -21,7 +21,7 @@ func WithLog(s collaborators.Collaborators, logger *zap.Logger, log_access bool) if log_access { s = AccessLoggingMiddleware(logger)(s) } - s = ErrorLoggingMiddleware(logger)(s) + s = LoggingMiddleware(logger)(s) s = RecoveringMiddleware(logger)(s) return s diff --git a/pkg/collections/events.go b/pkg/collections/events.go index bdc92e7769a7cd7ffc880825caaf3098fb5495fb..516d5c5cbf8ece7bd338e02a9919f4411a10c2fa 100644 --- a/pkg/collections/events.go +++ b/pkg/collections/events.go @@ -1,8 +1,8 @@ package collections const ( - EventCollectionCreate = "collection_create" - EventCollectionUpdate = "collection_update" - EventCollectionDelete = "collection_delete" - EventCollectionSetSchema = "collection_set_schema" + EventCreate = "collection.create" + EventUpdate = "collection.update" + EventDelete = "collection.delete" + EventSetSchema = "collection.set_schema" ) diff --git a/pkg/extension/service/registrar.go b/pkg/extension/service/registrar.go index dc58f97d69ebdfd17d2d7a7bbc972652cdb0d339..8a096ef2047058e70f355ece9136069b7d94d3af 100644 --- a/pkg/extension/service/registrar.go +++ b/pkg/extension/service/registrar.go @@ -25,11 +25,16 @@ type Registrar struct { } func NewRegistrar(addr string, man extension.Manager, exts []extension.Extension, logger *zap.Logger) *Registrar { + extNames := make([]string, 0, len(exts)) + for _, ext := range exts { + extNames = append(extNames, ext.GetDescriptor().GetExtension()) + } + return &Registrar{ addr: addr, manager: man, exts: exts, - logger: logger, + logger: logger.Named("Registrar").With(zap.Strings("extensions", extNames)), } } @@ -75,7 +80,7 @@ func (reg *Registrar) Start() error { extList = append(extList, &extension.ExtensionConnector{Descriptor: &desc}) } - reg.logger.Info("Start registration process") + reg.logger.Debug("Start registration process") go func() { for { @@ -84,7 +89,7 @@ func (reg *Registrar) Start() error { reg.register(regCtx, reg.manager, extList) registrationDelay = RegistrationDelay case <-regCtx.Done(): - reg.logger.Info("Stop registration process") + reg.logger.Debug("Stop registration process") return } } diff --git a/pkg/template/builder.go b/pkg/template/builder.go index 9a4ddcdb73e6b5c585d77088630096351d19b2bd..b1414df21adc6373a4dcd75460991f782e7eaab9 100644 --- a/pkg/template/builder.go +++ b/pkg/template/builder.go @@ -5,25 +5,38 @@ import ( "context" "text/template" + "git.perx.ru/perxis/perxis-go/pkg/account" + "git.perx.ru/perxis/perxis-go/pkg/collections" "git.perx.ru/perxis/perxis-go/pkg/content" + "git.perx.ru/perxis/perxis-go/pkg/environments" + "git.perx.ru/perxis/perxis-go/pkg/organizations" + "git.perx.ru/perxis/perxis-go/pkg/spaces" ) type Builder struct { ctx context.Context + acc *account.Account cnt *content.Content SpaceID string EnvID string - funcs template.FuncMap + CollID string data map[string]interface{} + + // Для кеширования запросов + space *spaces.Space + environment *environments.Environment + collection *collections.Collection + organization *organizations.Organization } -func NewBuilder(cnt *content.Content, space, env string) *Builder { +func NewBuilder(acc *account.Account, cnt *content.Content, space, env, col string) *Builder { return &Builder{ ctx: context.Background(), + acc: acc, cnt: cnt, SpaceID: space, EnvID: env, - funcs: make(template.FuncMap), + CollID: col, } } diff --git a/pkg/template/builder_test.go b/pkg/template/builder_test.go index f8e2b34440dd73259a6ccd3ce9202a556caa5298..f9e7b0a66b7b4ec54f9151136ed0e60d7f386cb9 100644 --- a/pkg/template/builder_test.go +++ b/pkg/template/builder_test.go @@ -4,36 +4,44 @@ import ( "context" "errors" "testing" - "text/template" + "git.perx.ru/perxis/perxis-go/pkg/account" + "git.perx.ru/perxis/perxis-go/pkg/collections" + colsmocks "git.perx.ru/perxis/perxis-go/pkg/collections/mocks" "git.perx.ru/perxis/perxis-go/pkg/content" + "git.perx.ru/perxis/perxis-go/pkg/environments" + envsmocks "git.perx.ru/perxis/perxis-go/pkg/environments/mocks" "git.perx.ru/perxis/perxis-go/pkg/items" mocksitems "git.perx.ru/perxis/perxis-go/pkg/items/mocks" + "git.perx.ru/perxis/perxis-go/pkg/organizations" + orgsmocks "git.perx.ru/perxis/perxis-go/pkg/organizations/mocks" + "git.perx.ru/perxis/perxis-go/pkg/spaces" + spsmocks "git.perx.ru/perxis/perxis-go/pkg/spaces/mocks" "github.com/stretchr/testify/assert" ) func TestBuilder_Execute(t *testing.T) { tests := []struct { name string - ctx context.Context - cnt *content.Content SpaceID string EnvID string - funcs template.FuncMap + CollID string str string data any want any wantErr bool - itemsCall func(itemsSvc *mocksitems.Items) + getAcc func() (acc *account.Account, assertExpectations func(t *testing.T)) + getCnt func() (cnt *content.Content, assertExpectations func(t *testing.T)) }{ - {name: "error", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello {{ .a }}", data: "world", want: "", wantErr: true}, - {name: "empty", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "", data: "", want: "", wantErr: false}, - {name: "#1", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello {{ . }}", data: "world", want: "hello world", wantErr: false}, - {name: "#2", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "{{ . }}", data: "world", want: "world", wantErr: false}, - {name: "#3 ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "", data: "world", want: "", wantErr: false}, - {name: "#4 ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello", data: "world", want: "hello", wantErr: false}, - {name: "lookup", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello, {{ lookup \"secrets.dev.key\" }}", data: "", want: "hello, Luk", wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "error", str: "hello {{ .a }}", data: "world", want: "", wantErr: true}, + {name: "empty", str: "", data: "", want: "", wantErr: false}, + {name: "#1", str: "hello {{ . }}", data: "world", want: "hello world", wantErr: false}, + {name: "#2", str: "{{ . }}", data: "world", want: "world", wantErr: false}, + {name: "#3 ", str: "", data: "world", want: "", wantErr: false}, + {name: "#4 ", str: "hello", data: "world", want: "hello", wantErr: false}, + {name: "lookup", SpaceID: "space", EnvID: "env", str: "hello, {{ lookup \"secrets.dev.key\" }}", data: "", want: "hello, Luk", wantErr: false, getCnt: func() (*content.Content, func(t *testing.T)) { + itemsSvc := &mocksitems.Items{} itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -44,8 +52,10 @@ func TestBuilder_Execute(t *testing.T) { "key": "Luk", }, }, nil).Once() + return &content.Content{Items: itemsSvc}, func(t *testing.T) { itemsSvc.AssertExpectations(t) } }}, - {name: "lookup with slice", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "numbers {{ lookup \"secrets.dev.slice\" }}", data: "", want: "numbers [1 2 3]", wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "lookup with slice", SpaceID: "space", EnvID: "env", str: "numbers {{ lookup \"secrets.dev.slice\" }}", data: "", want: "numbers [1 2 3]", wantErr: false, getCnt: func() (*content.Content, func(t *testing.T)) { + itemsSvc := &mocksitems.Items{} itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -56,8 +66,10 @@ func TestBuilder_Execute(t *testing.T) { "slice": []int{1, 2, 3}, }, }, nil).Once() + return &content.Content{Items: itemsSvc}, func(t *testing.T) { itemsSvc.AssertExpectations(t) } }}, - {name: "lookup with empty Data", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "numbers {{ lookup \"secrets.dev.slice\" }}", data: "", want: "numbers <no value>", wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "lookup with empty Data", SpaceID: "space", EnvID: "env", str: "numbers {{ lookup \"secrets.dev.slice\" }}", data: "", want: "numbers <no value>", wantErr: false, getCnt: func() (*content.Content, func(t *testing.T)) { + itemsSvc := &mocksitems.Items{} itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -65,8 +77,10 @@ func TestBuilder_Execute(t *testing.T) { CollectionID: "secrets", Data: map[string]interface{}{}, }, nil).Once() + return &content.Content{Items: itemsSvc}, func(t *testing.T) { itemsSvc.AssertExpectations(t) } }}, - {name: "lookup with incorrect field", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello {{ lookup \"secrets.dev.incorrect\" }}", data: "", want: "hello <no value>", wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "lookup with incorrect field", SpaceID: "space", EnvID: "env", str: "hello {{ lookup \"secrets.dev.incorrect\" }}", data: "", want: "hello <no value>", wantErr: false, getCnt: func() (*content.Content, func(t *testing.T)) { + itemsSvc := &mocksitems.Items{} itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -77,28 +91,64 @@ func TestBuilder_Execute(t *testing.T) { "key": "1234", }, }, nil).Once() + return &content.Content{Items: itemsSvc}, func(t *testing.T) { itemsSvc.AssertExpectations(t) } }}, - {name: "lookup not found", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello {{ lookup \"secrets.prod.pass\" }}", data: "", want: "", wantErr: true, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "lookup not found", SpaceID: "space", EnvID: "env", str: "hello {{ lookup \"secrets.prod.pass\" }}", data: "", want: "", wantErr: true, getCnt: func() (*content.Content, func(t *testing.T)) { + itemsSvc := &mocksitems.Items{} itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "prod").Return(nil, errors.New("not found")).Once() + return &content.Content{Items: itemsSvc}, func(t *testing.T) { itemsSvc.AssertExpectations(t) } }}, - {name: "lookup without itemID", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello {{ lookup \"secrets.pass\" }}", data: "", want: "", wantErr: true}, - {name: "system ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: "hello {{ system.SpaceID }}", data: "", want: "hello space", wantErr: false}, + {name: "lookup without itemID", SpaceID: "space", EnvID: "env", str: "hello {{ lookup \"secrets.pass\" }}", data: "", want: "", wantErr: true}, + {name: "system#1", SpaceID: "space", str: "hello {{ system.SpaceID }}", data: "", want: "hello space", wantErr: false}, + {name: "system organization", SpaceID: "space", EnvID: "env", getCnt: func() (cnt *content.Content, assertExpectations func(t *testing.T)) { + spsSvc := &spsmocks.Spaces{} + spsSvc.On("Get", context.Background(), "space").Return(&spaces.Space{OrgID: "orgid"}, nil).Once() + return &content.Content{Spaces: spsSvc}, func(t *testing.T) { spsSvc.AssertExpectations(t) } + }, getAcc: func() (acc *account.Account, assertExpectations func(t *testing.T)) { + orgsSvc := &orgsmocks.Organizations{} + orgsSvc.On("Get", context.Background(), "orgid").Return(&organizations.Organization{Name: "Org"}, nil).Once() + return &account.Account{Organizations: orgsSvc}, func(t *testing.T) { orgsSvc.AssertExpectations(t) } + }, str: "hello {{ system.Organization.Name }}", want: "hello Org", wantErr: false}, + {name: "system space", SpaceID: "space", getCnt: func() (cnt *content.Content, assertExpectations func(t *testing.T)) { + spsSvc := &spsmocks.Spaces{} + spsSvc.On("Get", context.Background(), "space").Return(&spaces.Space{Description: "description"}, nil).Once() + return &content.Content{Spaces: spsSvc}, func(t *testing.T) { spsSvc.AssertExpectations(t) } + }, str: "{{ system.Space.Description }}", want: "description", wantErr: false}, + {name: "system environment", SpaceID: "space", EnvID: "env", getCnt: func() (cnt *content.Content, assertExpectations func(t *testing.T)) { + envsSvc := &envsmocks.Environments{} + envsSvc.On("Get", context.Background(), "space", "env").Return(&environments.Environment{Aliases: []string{"master"}}, nil).Once() + return &content.Content{Environments: envsSvc}, func(t *testing.T) { envsSvc.AssertExpectations(t) } + }, str: "{{ system.Environment.Aliases }}", want: "[master]", wantErr: false}, + {name: "system collection", SpaceID: "space", EnvID: "env", CollID: "col", getCnt: func() (cnt *content.Content, assertExpectations func(t *testing.T)) { + collsSvc := &colsmocks.Collections{} + collsSvc.On("Get", context.Background(), "space", "env", "col").Return(&collections.Collection{Name: "cars"}, nil).Once() + return &content.Content{Collections: collsSvc}, func(t *testing.T) { collsSvc.AssertExpectations(t) } + }, str: "{{ system.Collection.Name }}", want: "cars", wantErr: false}, + {name: "system without account", SpaceID: "space", str: "hello {{ system.Organization.Name }}", want: "", wantErr: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - itemsSvc := &mocksitems.Items{} - if tt.itemsCall != nil { - tt.itemsCall(itemsSvc) + var acc *account.Account + var cnt *content.Content + + if tt.getAcc != nil { + var checkFn func(*testing.T) + acc, checkFn = tt.getAcc() + defer checkFn(t) } - tt.cnt = &content.Content{ - Items: itemsSvc, + if tt.getCnt != nil { + var checkFn func(*testing.T) + cnt, checkFn = tt.getCnt() + defer checkFn(t) } + b := &Builder{ - ctx: tt.ctx, - cnt: tt.cnt, + ctx: context.Background(), + acc: acc, + cnt: cnt, SpaceID: tt.SpaceID, EnvID: tt.EnvID, - funcs: tt.funcs, + CollID: tt.CollID, } got, err := b.Execute(tt.str, tt.data) @@ -108,9 +158,6 @@ func TestBuilder_Execute(t *testing.T) { assert.NoError(t, err) } assert.Equal(t, tt.want, got) - if tt.itemsCall != nil { - itemsSvc.AssertExpectations(t) - } }) } } @@ -118,11 +165,8 @@ func TestBuilder_Execute(t *testing.T) { func TestBuilder_ExecuteList(t *testing.T) { tests := []struct { name string - ctx context.Context - cnt *content.Content SpaceID string EnvID string - funcs template.FuncMap str []string data any want []string @@ -130,13 +174,13 @@ func TestBuilder_ExecuteList(t *testing.T) { itemsCall func(itemsSvc *mocksitems.Items) }{ - {name: "error", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"hello { . }}", "go {{ . }"}, data: "world", want: []string{}, wantErr: true}, - {name: "empty", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{""}, data: "world", want: []string{""}, wantErr: false}, - {name: "#1", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"hello {{ . }}", "go {{ . }}"}, data: "world", want: []string{"hello world", "go world"}, wantErr: false}, - {name: "#2", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"{{ . }}"}, data: "world", want: []string{"world"}, wantErr: false}, - {name: "#3 ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{""}, data: "world", want: []string{""}, wantErr: false}, - {name: "#4 ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"hello"}, data: "world", want: []string{"hello"}, wantErr: false}, - {name: "lookup", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"hello {{ lookup \"secrets.dev.key\" }}"}, data: "", want: []string{"hello 1234"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "error", SpaceID: "space", EnvID: "env", str: []string{"hello { . }}", "go {{ . }"}, data: "world", want: []string{}, wantErr: true}, + {name: "empty", SpaceID: "space", EnvID: "env", str: []string{""}, data: "world", want: []string{""}, wantErr: false}, + {name: "#1", SpaceID: "space", EnvID: "env", str: []string{"hello {{ . }}", "go {{ . }}"}, data: "world", want: []string{"hello world", "go world"}, wantErr: false}, + {name: "#2", SpaceID: "space", EnvID: "env", str: []string{"{{ . }}"}, data: "world", want: []string{"world"}, wantErr: false}, + {name: "#3 ", SpaceID: "space", EnvID: "env", str: []string{""}, data: "world", want: []string{""}, wantErr: false}, + {name: "#4 ", SpaceID: "space", EnvID: "env", str: []string{"hello"}, data: "world", want: []string{"hello"}, wantErr: false}, + {name: "lookup", SpaceID: "space", EnvID: "env", str: []string{"hello {{ lookup \"secrets.dev.key\" }}"}, data: "", want: []string{"hello 1234"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -148,7 +192,7 @@ func TestBuilder_ExecuteList(t *testing.T) { }, }, nil).Once() }}, - {name: "lookup with incorrect field", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"hello {{ lookup \"secrets.dev.incorrect\" }}"}, data: "", want: []string{"hello <no value>"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "lookup with incorrect field", SpaceID: "space", EnvID: "env", str: []string{"hello {{ lookup \"secrets.dev.incorrect\" }}"}, data: "", want: []string{"hello <no value>"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -160,7 +204,7 @@ func TestBuilder_ExecuteList(t *testing.T) { }, }, nil).Once() }}, - {name: "system ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: []string{"hello {{ system.SpaceID }}"}, data: "", want: []string{"hello space"}, wantErr: false}, + {name: "system ", SpaceID: "space", EnvID: "env", str: []string{"hello {{ system.SpaceID }}"}, data: "", want: []string{"hello space"}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -168,15 +212,11 @@ func TestBuilder_ExecuteList(t *testing.T) { if tt.itemsCall != nil { tt.itemsCall(itemsSvc) } - tt.cnt = &content.Content{ - Items: itemsSvc, - } b := &Builder{ - ctx: tt.ctx, - cnt: tt.cnt, + ctx: context.Background(), + cnt: &content.Content{Items: itemsSvc}, SpaceID: tt.SpaceID, EnvID: tt.EnvID, - funcs: tt.funcs, } got, err := b.ExecuteList(tt.str, tt.data) @@ -186,9 +226,7 @@ func TestBuilder_ExecuteList(t *testing.T) { assert.NoError(t, err) } assert.Equal(t, tt.want, got) - if tt.itemsCall != nil { - itemsSvc.AssertExpectations(t) - } + itemsSvc.AssertExpectations(t) }) } } @@ -196,11 +234,8 @@ func TestBuilder_ExecuteList(t *testing.T) { func TestBuilder_ExecuteMap(t *testing.T) { tests := []struct { name string - ctx context.Context - cnt *content.Content SpaceID string EnvID string - funcs template.FuncMap str map[string]interface{} data any want map[string]interface{} @@ -208,13 +243,13 @@ func TestBuilder_ExecuteMap(t *testing.T) { itemsCall func(itemsSvc *mocksitems.Items) }{ - {name: "error", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"hello": "{{ . }"}, data: "world", want: nil, wantErr: true}, - {name: "empty", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{}, data: "", want: map[string]interface{}{}, wantErr: false}, - {name: "#1", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"hello": "{{ . }}"}, data: "world", want: map[string]interface{}{"hello": "world"}, wantErr: false}, - {name: "#2", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"hello": "{{ . }}", "go": "{{ . }}"}, data: "world", want: map[string]interface{}{"hello": "world", "go": "world"}, wantErr: false}, - {name: "#3 ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{}, data: "world", want: map[string]interface{}{}, wantErr: false}, - {name: "#4 ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"a": "b"}, data: "world", want: map[string]interface{}{"a": "b"}, wantErr: false}, - {name: "lookup ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"hello": "{{ lookup \"secrets.dev.key\" }}"}, data: "", want: map[string]interface{}{"hello": "1234"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "error", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"hello": "{{ . }"}, data: "world", want: nil, wantErr: true}, + {name: "empty", SpaceID: "space", EnvID: "env", str: map[string]interface{}{}, data: "", want: map[string]interface{}{}, wantErr: false}, + {name: "#1", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"hello": "{{ . }}"}, data: "world", want: map[string]interface{}{"hello": "world"}, wantErr: false}, + {name: "#2", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"hello": "{{ . }}", "go": "{{ . }}"}, data: "world", want: map[string]interface{}{"hello": "world", "go": "world"}, wantErr: false}, + {name: "#3 ", SpaceID: "space", EnvID: "env", str: map[string]interface{}{}, data: "world", want: map[string]interface{}{}, wantErr: false}, + {name: "#4 ", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"a": "b"}, data: "world", want: map[string]interface{}{"a": "b"}, wantErr: false}, + {name: "lookup ", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"hello": "{{ lookup \"secrets.dev.key\" }}"}, data: "", want: map[string]interface{}{"hello": "1234"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -226,7 +261,7 @@ func TestBuilder_ExecuteMap(t *testing.T) { }, }, nil).Once() }}, - {name: "lookup with incorrect field", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"hello": "{{ lookup \"secrets.dev.incorrect\" }}"}, data: "", want: map[string]interface{}{"hello": "<no value>"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { + {name: "lookup with incorrect field", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"hello": "{{ lookup \"secrets.dev.incorrect\" }}"}, data: "", want: map[string]interface{}{"hello": "<no value>"}, wantErr: false, itemsCall: func(itemsSvc *mocksitems.Items) { itemsSvc.On("Get", context.Background(), "space", "env", "secrets", "dev").Return(&items.Item{ ID: "dev", SpaceID: "space", @@ -238,7 +273,7 @@ func TestBuilder_ExecuteMap(t *testing.T) { }, }, nil).Once() }}, - {name: "system ", ctx: context.Background(), cnt: &content.Content{}, SpaceID: "space", EnvID: "env", funcs: template.FuncMap{}, str: map[string]interface{}{"hello": "{{ system.SpaceID }}"}, data: "", want: map[string]interface{}{"hello": "space"}, wantErr: false}, + {name: "system ", SpaceID: "space", EnvID: "env", str: map[string]interface{}{"hello": "{{ system.SpaceID }}"}, data: "", want: map[string]interface{}{"hello": "space"}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -246,15 +281,11 @@ func TestBuilder_ExecuteMap(t *testing.T) { if tt.itemsCall != nil { tt.itemsCall(itemsSvc) } - tt.cnt = &content.Content{ - Items: itemsSvc, - } b := &Builder{ - ctx: tt.ctx, - cnt: tt.cnt, + ctx: context.Background(), + cnt: &content.Content{Items: itemsSvc}, SpaceID: tt.SpaceID, EnvID: tt.EnvID, - funcs: tt.funcs, } got, err := b.ExecuteMap(tt.str, tt.data) @@ -264,9 +295,7 @@ func TestBuilder_ExecuteMap(t *testing.T) { assert.NoError(t, err) } assert.Equal(t, tt.want, got) - if tt.itemsCall != nil { - itemsSvc.AssertExpectations(t) - } + itemsSvc.AssertExpectations(t) }) } } diff --git a/pkg/template/system.go b/pkg/template/system.go index 8f8548eb11444e72ad4f003b9225f4d4a38e4e2a..48b464e4cf106f5e90dfc622764391080646ec10 100644 --- a/pkg/template/system.go +++ b/pkg/template/system.go @@ -1,5 +1,12 @@ package template +import ( + "git.perx.ru/perxis/perxis-go/pkg/collections" + "git.perx.ru/perxis/perxis-go/pkg/environments" + "git.perx.ru/perxis/perxis-go/pkg/organizations" + "git.perx.ru/perxis/perxis-go/pkg/spaces" +) + type System struct { builder *Builder } @@ -11,3 +18,60 @@ func (s *System) SpaceID() string { func (s *System) EnvID() string { return s.builder.EnvID } + +func (s *System) CollectionID() string { + return s.builder.CollID +} + +func (s *System) OrganizationID() (string, error) { + org, err := s.Organization() + if err != nil { + return "", err + } + return org.ID, nil +} + +func (s *System) Space() (*spaces.Space, error) { + if s.builder.space != nil { + return s.builder.space, nil + } + + space, err := s.builder.cnt.Spaces.Get(s.builder.ctx, s.builder.SpaceID) + s.builder.space = space + return s.builder.space, err +} + +func (s *System) Environment() (*environments.Environment, error) { + if s.builder.environment != nil { + return s.builder.environment, nil + } + + env, err := s.builder.cnt.Environments.Get(s.builder.ctx, s.builder.SpaceID, s.builder.EnvID) + s.builder.environment = env + return s.builder.environment, err +} + +func (s *System) Collection() (*collections.Collection, error) { + if s.builder.collection != nil { + return s.builder.collection, nil + } + + coll, err := s.builder.cnt.Collections.Get(s.builder.ctx, s.builder.SpaceID, s.builder.EnvID, s.builder.CollID) + s.builder.collection = coll + return s.builder.collection, err +} + +func (s *System) Organization() (*organizations.Organization, error) { + if s.builder.organization != nil { + return s.builder.organization, nil + } + + sp, err := s.Space() + if err != nil { + return nil, err + } + + org, err := s.builder.acc.Organizations.Get(s.builder.ctx, sp.OrgID) + s.builder.organization = org + return s.builder.organization, err +}