Skip to content

Commit

Permalink
FLI Issue 3222: Import issue when --address and --drop is used (#3530)
Browse files Browse the repository at this point in the history
* feat(storage): introducing new force flag for delete namespaces

Signed-off-by: devumesh <[email protected]>

* feat(ext): drop namespaces during import with address

Signed-off-by: devumesh <[email protected]>

* feat(ext): unit test for the force delete on the namespaces

Signed-off-by: devumesh <[email protected]>

* feat(ext): dont count flags incase of force namespace delete

Signed-off-by: devumesh <[email protected]>

---------

Signed-off-by: devumesh <[email protected]>
Co-authored-by: Roman Dmytrenko <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 27, 2024
1 parent 3223ce4 commit 8d72418
Show file tree
Hide file tree
Showing 14 changed files with 1,468 additions and 2,825 deletions.
32 changes: 32 additions & 0 deletions cmd/flipt/import.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"errors"
"fmt"
"io"
Expand All @@ -10,6 +11,8 @@ import (
"github.com/spf13/cobra"
"go.flipt.io/flipt/internal/ext"
"go.flipt.io/flipt/internal/storage/sql"
"go.flipt.io/flipt/rpc/flipt"
sdk "go.flipt.io/flipt/sdk/go"
)

type importCommand struct {
Expand Down Expand Up @@ -107,6 +110,11 @@ func (c *importCommand) run(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
if c.dropBeforeImport {
if err := dropNamespaces(ctx, client); err != nil {
return fmt.Errorf("dropping namespaces: %w", err)
}
}
return ext.NewImporter(client).Import(ctx, enc, in, c.skipExisting)
}

Expand Down Expand Up @@ -161,3 +169,27 @@ func (c *importCommand) run(cmd *cobra.Command, args []string) error {
server,
).Import(ctx, enc, in, c.skipExisting)
}

func dropNamespaces(ctx context.Context, client *sdk.Flipt) error {
namespaces, err := client.ListNamespaces(ctx, &flipt.ListNamespaceRequest{})
if err != nil {
return err
}

for _, ns := range namespaces.Namespaces {
if err := client.DeleteNamespace(ctx, &flipt.DeleteNamespaceRequest{
Key: ns.Key,
Force: true,
}); err != nil {
return err
}
}

_, err = client.CreateNamespace(ctx, &flipt.CreateNamespaceRequest{
Key: "default",
Name: "Default",
Description: "Default namespace",
})

return err
}
18 changes: 10 additions & 8 deletions internal/server/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,20 @@ func (s *Server) DeleteNamespace(ctx context.Context, r *flipt.DeleteNamespaceRe
return &empty.Empty{}, nil
}

if namespace.Protected {
if !r.GetForce() && 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, storage.NewNamespace(r.Key))
if err != nil {
return nil, err
}
if !r.GetForce() {
// if any flags exist under the namespace then it cannot be deleted
count, err := s.store.CountFlags(ctx, storage.NewNamespace(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 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 {
Expand Down
58 changes: 58 additions & 0 deletions internal/server/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,61 @@ func TestDeleteNamespace_HasFlags(t *testing.T) {
require.EqualError(t, err, "namespace \"foo\" cannot be deleted; flags must be deleted first")
assert.Nil(t, got)
}


func TestDeleteNamespace_ProtectedWithForce(t *testing.T) {
var (
store = &common.StoreMock{}
logger = zaptest.NewLogger(t)
s = &Server{
logger: logger,
store: store,
}
req = &flipt.DeleteNamespaceRequest{
Key: "foo",
Force: true,
}
)

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

store.AssertNotCalled(t, "CountFlags")

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_HasFlagsWithForce(t *testing.T) {
var (
store = &common.StoreMock{}
logger = zaptest.NewLogger(t)
s = &Server{
logger: logger,
store: store,
}
req = &flipt.DeleteNamespaceRequest{
Key: "foo",
Force: true,
}
)

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

store.AssertNotCalled(t, "CountFlags")

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

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

assert.NotNil(t, got)
}
4 changes: 4 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ paths:
required: true
schema:
type: string
- name: force
in: query
schema:
type: boolean
responses:
"200":
description: OK
Expand Down
48 changes: 9 additions & 39 deletions rpc/flipt/analytics/analytics.pb.go

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

70 changes: 13 additions & 57 deletions rpc/flipt/audit/event.pb.go

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

Loading

0 comments on commit 8d72418

Please sign in to comment.