Skip to content

Commit

Permalink
feat: encrich namespace labels when sync runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdh committed Oct 21, 2023
1 parent e3f6e4c commit 56cb11b
Show file tree
Hide file tree
Showing 14 changed files with 415 additions and 154 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ NAME="github.com/goto/siren"
LAST_COMMIT := $(shell git rev-parse --short HEAD)
LAST_TAG := "$(shell git rev-list --tags --max-count=1)"
APP_VERSION := "$(shell git describe --tags ${LAST_TAG})-next"
PROTON_COMMIT := "534a703026bd70fa464c3bedc6a9aef3f8fcdd19"
PROTON_COMMIT := "f210b5a6d036c9c8288dc52af65ba4a09d88ee4d"

.PHONY: all build test clean dist vet proto install

Expand Down
43 changes: 28 additions & 15 deletions core/namespace/mocks/config_syncer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions core/namespace/mocks/namespace_repository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions core/namespace/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Repository interface {
Create(context.Context, *EncryptedNamespace) error
Get(context.Context, uint64) (*EncryptedNamespace, error)
Update(context.Context, *EncryptedNamespace) error
UpdateLabels(context.Context, uint64, map[string]string) error
Delete(context.Context, uint64) error
}

Expand Down
2 changes: 1 addition & 1 deletion core/namespace/provider_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import (

//go:generate mockery --name=ConfigSyncer -r --case underscore --with-expecter --structname ConfigSyncer --filename config_syncer.go --output=./mocks
type ConfigSyncer interface {
SyncRuntimeConfig(ctx context.Context, namespaceID uint64, namespaceURN string, prov provider.Provider) error
SyncRuntimeConfig(ctx context.Context, namespaceID uint64, namespaceURN string, namespaceLabels map[string]string, prov provider.Provider) (map[string]string, error)
}
45 changes: 41 additions & 4 deletions core/namespace/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,32 @@ func (s *Service) Create(ctx context.Context, ns *Namespace) error {
return err
}

if err := pluginService.SyncRuntimeConfig(ctx, encryptedNamespace.ID, ns.URN, *prov); err != nil {
labels, err := pluginService.SyncRuntimeConfig(ctx, encryptedNamespace.ID, ns.URN, ns.Labels, ns.Provider)
if err != nil {
if err := s.repository.Rollback(ctx, err); err != nil {
return err
}
return err
}

if encryptedNamespace.Labels == nil {
encryptedNamespace.Labels = make(map[string]string)
}

for k, v := range labels {
encryptedNamespace.Labels[k] = v
}

if err = s.repository.UpdateLabels(ctx, encryptedNamespace.ID, encryptedNamespace.Labels); err != nil {
if err := s.repository.Rollback(ctx, err); err != nil {
return err
}
if errors.As(err, new(NotFoundError)) {
return errors.ErrNotFound.WithMsgf(err.Error())
}
return err
}

if err := s.repository.Commit(ctx); err != nil {
return err
}
Expand Down Expand Up @@ -142,8 +161,7 @@ func (s *Service) Update(ctx context.Context, ns *Namespace) error {
}

ctx = s.repository.WithTransaction(ctx)
err = s.repository.Update(ctx, encryptedNamespace)
if err != nil {
if err = s.repository.Update(ctx, encryptedNamespace); err != nil {
if err := s.repository.Rollback(ctx, err); err != nil {
return err
}
Expand All @@ -159,10 +177,29 @@ func (s *Service) Update(ctx context.Context, ns *Namespace) error {
return err
}

if err := pluginService.SyncRuntimeConfig(ctx, encryptedNamespace.ID, ns.URN, ns.Provider); err != nil {
labels, err := pluginService.SyncRuntimeConfig(ctx, encryptedNamespace.ID, ns.URN, ns.Labels, ns.Provider)
if err != nil {
if err := s.repository.Rollback(ctx, err); err != nil {
return err
}
return err
}

if encryptedNamespace.Labels == nil {
encryptedNamespace.Labels = make(map[string]string)
}

for k, v := range labels {
encryptedNamespace.Labels[k] = v
}

if err = s.repository.UpdateLabels(ctx, encryptedNamespace.ID, encryptedNamespace.Labels); err != nil {
if err := s.repository.Rollback(ctx, err); err != nil {
return err
}
if errors.As(err, new(NotFoundError)) {
return errors.ErrNotFound.WithMsgf(err.Error())
}
return err
}

Expand Down
57 changes: 51 additions & 6 deletions core/namespace/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func TestService_CreateNamespace(t *testing.T) {
Namespace: tc.NSpace,
CredentialString: "some-ciphertext",
}).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("provider.Provider")).Return(errors.New("some error"))
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("map[string]string"), mock.AnythingOfType("provider.Provider")).Return(nil, errors.New("some error"))
rr.EXPECT().Rollback(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("*errors.errorString")).Return(nil)
},
NSpace: &namespace.Namespace{
Expand All @@ -324,7 +324,7 @@ func TestService_CreateNamespace(t *testing.T) {
Err: errors.New("some error"),
},
{
Description: "should return nil error if create repository success & sync config success",
Description: "should return error if create repository success & sync config success & update labels error",
Setup: func(rr *mocks.NamespaceRepository, e *mocks.Encryptor, ps *mocks.ProviderService, cs *mocks.ConfigSyncer, tc testCase) {
ps.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&provider.Provider{Type: testProviderType}, nil)
e.EXPECT().Encrypt(mock.AnythingOfType("secret.MaskableString")).Return("some-ciphertext", nil)
Expand All @@ -333,7 +333,29 @@ func TestService_CreateNamespace(t *testing.T) {
Namespace: tc.NSpace,
CredentialString: "some-ciphertext",
}).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("provider.Provider")).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("map[string]string"), mock.AnythingOfType("provider.Provider")).Return(map[string]string{"k": "v"}, nil)
rr.EXPECT().UpdateLabels(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("map[string]string")).Return(errors.New("some error"))
rr.EXPECT().Rollback(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("*errors.errorString")).Return(nil)
},
NSpace: &namespace.Namespace{
Credentials: map[string]any{
"credential": "value",
},
},
Err: errors.New("some error"),
},
{
Description: "should return nil error if create repository success & sync config success & update labels success",
Setup: func(rr *mocks.NamespaceRepository, e *mocks.Encryptor, ps *mocks.ProviderService, cs *mocks.ConfigSyncer, tc testCase) {
ps.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&provider.Provider{Type: testProviderType}, nil)
e.EXPECT().Encrypt(mock.AnythingOfType("secret.MaskableString")).Return("some-ciphertext", nil)
rr.EXPECT().WithTransaction(mock.AnythingOfType("context.todoCtx")).Return(ctx)
rr.EXPECT().Create(mock.AnythingOfType("context.todoCtx"), &namespace.EncryptedNamespace{
Namespace: tc.NSpace,
CredentialString: "some-ciphertext",
}).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("map[string]string"), mock.AnythingOfType("provider.Provider")).Return(map[string]string{"k": "v"}, nil)
rr.EXPECT().UpdateLabels(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("map[string]string")).Return(nil)
rr.EXPECT().Commit(mock.AnythingOfType("context.todoCtx")).Return(nil)
},
NSpace: &namespace.Namespace{
Expand Down Expand Up @@ -620,7 +642,29 @@ func TestService_UpdateNamespace(t *testing.T) {
Namespace: tc.NSpace,
CredentialString: "some-ciphertext",
}).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("provider.Provider")).Return(errors.New("some error"))
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("map[string]string"), mock.AnythingOfType("provider.Provider")).Return(nil, errors.New("some error"))
rr.EXPECT().Rollback(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("*errors.errorString")).Return(nil)
},
NSpace: &namespace.Namespace{
Credentials: map[string]any{
"credential": "value",
},
},
Err: errors.New("some error"),
},
{
Description: "should return error if update repository success, sync success, and update labels return error",
Setup: func(rr *mocks.NamespaceRepository, e *mocks.Encryptor, cs *mocks.ConfigSyncer, tc testCase) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&namespace.EncryptedNamespace{Namespace: &namespace.Namespace{Provider: provider.Provider{Type: testProviderType}}}, nil)
e.EXPECT().Decrypt(mock.AnythingOfType("secret.MaskableString")).Return("{ \"key\": \"value\" }", nil)
e.EXPECT().Encrypt(mock.AnythingOfType("secret.MaskableString")).Return("some-ciphertext", nil)
rr.EXPECT().WithTransaction(mock.AnythingOfType("context.todoCtx")).Return(ctx)
rr.EXPECT().Update(mock.AnythingOfType("context.todoCtx"), &namespace.EncryptedNamespace{
Namespace: tc.NSpace,
CredentialString: "some-ciphertext",
}).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("map[string]string"), mock.AnythingOfType("provider.Provider")).Return(map[string]string{"k": "v"}, nil)
rr.EXPECT().UpdateLabels(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("map[string]string")).Return(errors.New("some error"))
rr.EXPECT().Rollback(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("*errors.errorString")).Return(nil)
},
NSpace: &namespace.Namespace{
Expand All @@ -631,7 +675,7 @@ func TestService_UpdateNamespace(t *testing.T) {
Err: errors.New("some error"),
},
{
Description: "should return nil error if update repository success",
Description: "should return nil error if update repository success, sync, and update labels success",
Setup: func(rr *mocks.NamespaceRepository, e *mocks.Encryptor, cs *mocks.ConfigSyncer, tc testCase) {
rr.EXPECT().Get(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64")).Return(&namespace.EncryptedNamespace{Namespace: &namespace.Namespace{Provider: provider.Provider{Type: testProviderType}}}, nil)
e.EXPECT().Decrypt(mock.AnythingOfType("secret.MaskableString")).Return("{ \"key\": \"value\" }", nil)
Expand All @@ -641,7 +685,8 @@ func TestService_UpdateNamespace(t *testing.T) {
Namespace: tc.NSpace,
CredentialString: "some-ciphertext",
}).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("provider.Provider")).Return(nil)
cs.EXPECT().SyncRuntimeConfig(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("string"), mock.AnythingOfType("map[string]string"), mock.AnythingOfType("provider.Provider")).Return(map[string]string{"k": "v"}, nil)
rr.EXPECT().UpdateLabels(mock.AnythingOfType("context.todoCtx"), mock.AnythingOfType("uint64"), mock.AnythingOfType("map[string]string")).Return(nil)
rr.EXPECT().Commit(mock.AnythingOfType("context.todoCtx")).Return(nil)
},
NSpace: &namespace.Namespace{
Expand Down
24 changes: 23 additions & 1 deletion internal/store/postgres/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ WHERE id = $1
RETURNING *
`

const namespaceUpdateLabelQuery = `
UPDATE namespaces SET labels=$2, updated_at=now()
WHERE id = $1
RETURNING *
`

var namespaceListQueryBuilder = sq.Select(`
n.id as id,
n.urn as urn,
Expand Down Expand Up @@ -168,12 +174,28 @@ func (r NamespaceRepository) Update(ctx context.Context, ns *namespace.Encrypted
return nil
}

func (r NamespaceRepository) UpdateLabels(ctx context.Context, id uint64, labels map[string]string) error {
if len(labels) == 0 {
return nil
}
rows, err := r.client.QueryxContext(ctx, pgc.OpUpdate, r.tableName, namespaceUpdateLabelQuery, id, labels)
if err != nil {
err = pgc.CheckError(err)
if errors.Is(err, sql.ErrNoRows) {
return namespace.NotFoundError{ID: id}
}
return err
}
defer rows.Close()
return nil
}

func (r NamespaceRepository) Delete(ctx context.Context, id uint64) error {
rows, err := r.client.QueryxContext(ctx, pgc.OpDelete, r.tableName, namespaceDeleteQuery, id)
if err != nil {
return err
}
rows.Close()
defer rows.Close()
return nil
}

Expand Down
Loading

0 comments on commit 56cb11b

Please sign in to comment.