Skip to content

Commit

Permalink
test: delete segments
Browse files Browse the repository at this point in the history
  • Loading branch information
jskelin committed Dec 13, 2024
1 parent cc877ba commit 27bae6b
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 1 deletion.
81 changes: 80 additions & 1 deletion pkg/delete/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients/automation"
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients/buckets"
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients/documents"
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients/grailfiltersegments"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/internal/featureflags"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/internal/idutils"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/internal/testutils/matcher"
Expand Down Expand Up @@ -1088,7 +1089,7 @@ func TestDelete_Documents(t *testing.T) {
assert.NoError(t, err)
})

t.Run("config declared via coordinate have multiple match - delete them all", func(t *testing.T) {
t.Run("config declared via coordinate have multiple match - no delete, no error", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "document",
Identifier: "monaco_identifier",
Expand Down Expand Up @@ -1149,3 +1150,81 @@ func TestDelete_Documents(t *testing.T) {
assert.Error(t, err)
})
}

type fakeSegmentsClient struct {
list func() (grailfiltersegments.Response, error)
getAll func() ([]grailfiltersegments.Response, error)
delete func() (grailfiltersegments.Response, error)
}

func (c fakeSegmentsClient) List(_ context.Context) (grailfiltersegments.Response, error) {
return c.list()
}

func (c fakeSegmentsClient) GetAll(_ context.Context) ([]grailfiltersegments.Response, error) {
return c.getAll()
}

func (c fakeSegmentsClient) Delete(_ context.Context, _ string) (grailfiltersegments.Response, error) {
return c.delete()
}

func TestDelete_SegmentsWithFakes(t *testing.T) {
t.Run("simple case", func(t *testing.T) {
t.Setenv(featureflags.Temporary[featureflags.GrailFilterSegment].EnvName(), "true")

fakeClient := fakeSegmentsClient{
delete: func() (grailfiltersegments.Response, error) {
return grailfiltersegments.Response{StatusCode: http.StatusOK}, nil
},
}

given := delete.DeleteEntries{
"filter-segment": {
{
Type: "filter-segment",
OriginObjectId: "originObjectID",
},
},
}
err := delete.Configs(context.TODO(), client.ClientSet{GrailFilterSegmentClient: fakeClient}, given)
assert.NoError(t, err)
})

}

func TestDelete_Segments(t *testing.T) {
t.Run("simple case", func(t *testing.T) {
t.Setenv(featureflags.Temporary[featureflags.GrailFilterSegment].EnvName(), "true")

c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().Delete(gomock.Any(), gomock.Eq("originObjectID")).Times(1)

given := delete.DeleteEntries{
"filter-segment": {
{
Type: "filter-segment",
OriginObjectId: "originObjectID",
},
},
}
err := delete.Configs(context.TODO(), client.ClientSet{GrailFilterSegmentClient: c}, given)
assert.NoError(t, err)
})

t.Run("FF is turned off", func(t *testing.T) {
c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
// no calls to client

entriesToDelete := delete.DeleteEntries{
"filter-segment": {
{
Type: "filter-segment",
OriginObjectId: "originObjectID",
},
},
}
err := delete.Configs(context.TODO(), client.ClientSet{GrailFilterSegmentClient: c}, entriesToDelete)
assert.NoError(t, err)
})
}
143 changes: 143 additions & 0 deletions pkg/delete/internal/grailfiltersegment/delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* @license
* Copyright 2024 Dynatrace LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package grailfiltersegment_test

import (
"context"
"errors"
"fmt"
"net/http"
"testing"

"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"

libAPI "github.com/dynatrace/dynatrace-configuration-as-code-core/api"
libSegment "github.com/dynatrace/dynatrace-configuration-as-code-core/clients/grailfiltersegments"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/internal/idutils"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/pkg/client"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/pkg/delete/internal/grailfiltersegment"
"github.com/dynatrace/dynatrace-configuration-as-code/v2/pkg/delete/pointer"
)

func TestDelete(t *testing.T) {

t.Run("delete via coordinate", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
Identifier: "monaco_identifier",
Project: "project",
}

externalID, _ := idutils.GenerateExternalIDForDocument(given.AsCoordinate())
c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().List(gomock.Any()).Times(1).
Return(libSegment.Response{Data: []byte(fmt.Sprintf(`[{"uid": "uid_1", "externalId":"%s"},{"uid": "uid_2", "externalId":"wrong"}]`, externalID))}, nil)
c.EXPECT().Delete(gomock.Any(), gomock.Eq("uid_1")).Times(1)

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given})
assert.NoError(t, err)
})

t.Run("config declared via coordinate doesn't exists - no error (wanted state achieved)", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
Identifier: "monaco_identifier",
Project: "project",
}

c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().List(gomock.Any()).Times(1).
Return(libSegment.Response{Data: []byte("[{\"uid\": \"uid_2\", \"externalId\":\"wrong\"}]")}, nil)

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given})
assert.NoError(t, err)
})

t.Run("config declared via coordinate have multiple match - an error", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
Identifier: "monaco_identifier",
Project: "project",
}

externalID, _ := idutils.GenerateExternalIDForDocument(given.AsCoordinate())
c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().List(gomock.Any()).Times(1).
Return(libSegment.Response{Data: []byte(fmt.Sprintf(`[{"uid": "uid_1", "externalId":"%s"},{"uid": "uid_2", "externalId":"%s"}]`, externalID, externalID))}, nil)

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given})
assert.Error(t, err)
})

t.Run("config declared via coordinate failed to get externalId (server error) - an error", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
Identifier: "monaco_identifier",
Project: "project",
}

c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().List(gomock.Any()).Times(1).
Return(libSegment.Response{}, errors.New("some unpredictable error"))

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given})
assert.Error(t, err)
})

t.Run("delete via originID", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
OriginObjectId: "originObjectID",
}

c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().Delete(gomock.Any(), gomock.Eq("originObjectID")).Times(1)

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given})
assert.NoError(t, err)
})

t.Run("config declared via originID doesn't exists - no error (wanted state achieved)", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
OriginObjectId: "originObjectID",
}

c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().Delete(gomock.Any(), gomock.Eq("originObjectID")).Times(1).Return(libAPI.Response{}, libAPI.APIError{StatusCode: http.StatusNotFound})

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given})
assert.NoError(t, err)
})

t.Run("error during delete - continue to delete, an error", func(t *testing.T) {
given := pointer.DeletePointer{
Type: "filter-segment",
OriginObjectId: "originObjectID",
Project: "project",
}

c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t))
c.EXPECT().Delete(gomock.Any(), gomock.Eq("originObjectID")).Times(1).Return(libAPI.Response{}, libAPI.APIError{StatusCode: http.StatusNotFound})
c.EXPECT().Delete(gomock.Any(), gomock.Eq("originObjectID")).Times(1).Return(libAPI.Response{}, libAPI.APIError{StatusCode: http.StatusInternalServerError}) // the error can be any kind except 404
c.EXPECT().Delete(gomock.Any(), gomock.Eq("originObjectID")).Times(1).Return(libAPI.Response{}, libAPI.APIError{StatusCode: http.StatusNotFound})

err := grailfiltersegment.Delete(context.TODO(), c, []pointer.DeletePointer{given, given, given})
assert.Error(t, err)
})
}

0 comments on commit 27bae6b

Please sign in to comment.