Skip to content

Commit

Permalink
feat: check for protected or flags existing when deleting a namespace (
Browse files Browse the repository at this point in the history
…#1422)

* feat: add namespaces server impl

* chore: spacing

* chore: rm ability to set protected

* feat: check for protected or flags existing when deleting a namespace

* chore: fix test

* chore: add test for non-existing delete
  • Loading branch information
markphelps authored Mar 21, 2023
1 parent bdbe9be commit 1f9b339
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 3 deletions.
25 changes: 25 additions & 0 deletions internal/server/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,33 @@ func (s *Server) UpdateNamespace(ctx context.Context, r *flipt.UpdateNamespaceRe
// DeleteNamespace deletes a namespace
func (s *Server) DeleteNamespace(ctx context.Context, r *flipt.DeleteNamespaceRequest) (*empty.Empty, error) {
s.logger.Debug("delete namespace", zap.Stringer("request", r))
namespace, err := s.store.GetNamespace(ctx, r.Key)
if err != nil {
return nil, err
}

// if namespace is not found then nothing to do
if namespace == nil {
return &empty.Empty{}, nil
}

if namespace.Protected {
return nil, errors.ErrInvalidf("namespace %q is protected", r.Key)
}

// if any flags exist under the namespace then it cannot be deleted
count, err := s.store.CountFlags(ctx, r.Key)
if err != nil {
return nil, err
}

if count > 0 {
return nil, errors.ErrInvalidf("namespace %q cannot be deleted; flags must be deleted first", r.Key)
}

if err := s.store.DeleteNamespace(ctx, r); err != nil {
return nil, err
}

return &empty.Empty{}, nil
}
90 changes: 87 additions & 3 deletions internal/server/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func TestCreateNamespace(t *testing.T) {
store: store,
}
req = &flipt.CreateNamespaceRequest{
Key: "key",
Key: "foo",
Name: "name",
Description: "desc",
}
Expand All @@ -180,7 +180,7 @@ func TestUpdateNamespace(t *testing.T) {
store: store,
}
req = &flipt.UpdateNamespaceRequest{
Key: "key",
Key: "foo",
Name: "name",
Description: "desc",
}
Expand All @@ -207,14 +207,98 @@ func TestDeleteNamespace(t *testing.T) {
store: store,
}
req = &flipt.DeleteNamespaceRequest{
Key: "key",
Key: "foo",
}
)

store.On("GetNamespace", mock.Anything, "foo").Return(&flipt.Namespace{
Key: req.Key,
}, nil)

store.On("CountFlags", mock.Anything, "foo").Return(uint64(0), nil)

store.On("DeleteNamespace", mock.Anything, req).Return(nil)

got, err := s.DeleteNamespace(context.TODO(), req)
require.NoError(t, err)

assert.NotNil(t, got)
}

func TestDeleteNamespace_NonExistent(t *testing.T) {
var (
store = &storeMock{}
logger = zaptest.NewLogger(t)
s = &Server{
logger: logger,
store: store,
}
req = &flipt.DeleteNamespaceRequest{
Key: "foo",
}
)

var ns *flipt.Namespace
store.On("GetNamespace", mock.Anything, "foo").Return(ns, nil) // mock library does not like nil

store.AssertNotCalled(t, "CountFlags")
store.AssertNotCalled(t, "DeleteNamespace")

got, err := s.DeleteNamespace(context.TODO(), req)
require.NoError(t, err)

assert.NotNil(t, got)
}

func TestDeleteNamespace_Protected(t *testing.T) {
var (
store = &storeMock{}
logger = zaptest.NewLogger(t)
s = &Server{
logger: logger,
store: store,
}
req = &flipt.DeleteNamespaceRequest{
Key: "foo",
}
)

store.On("GetNamespace", mock.Anything, "foo").Return(&flipt.Namespace{
Key: req.Key,
Protected: true,
}, nil)

store.On("CountFlags", mock.Anything, "foo").Return(uint64(0), nil)

store.AssertNotCalled(t, "DeleteNamespace")

got, err := s.DeleteNamespace(context.TODO(), req)
assert.EqualError(t, err, "namespace \"foo\" is protected")
assert.Nil(t, got)
}

func TestDeleteNamespace_HasFlags(t *testing.T) {
var (
store = &storeMock{}
logger = zaptest.NewLogger(t)
s = &Server{
logger: logger,
store: store,
}
req = &flipt.DeleteNamespaceRequest{
Key: "foo",
}
)

store.On("GetNamespace", mock.Anything, "foo").Return(&flipt.Namespace{
Key: req.Key,
}, nil)

store.On("CountFlags", mock.Anything, "foo").Return(uint64(1), nil)

store.AssertNotCalled(t, "DeleteNamespace")

got, err := s.DeleteNamespace(context.TODO(), req)
assert.EqualError(t, err, "namespace \"foo\" cannot be deleted; flags must be deleted first")
assert.Nil(t, got)
}

0 comments on commit 1f9b339

Please sign in to comment.