diff --git a/pkg/delete/delete.go b/pkg/delete/delete.go index 15b878d66..e288c1c5b 100644 --- a/pkg/delete/delete.go +++ b/pkg/delete/delete.go @@ -165,6 +165,15 @@ func All(ctx context.Context, clients client.ClientSet, apis api.APIs) error { } } + if featureflags.Temporary[featureflags.GrailFilterSegment].Enabled() { + if clients.GrailFilterSegmentClient == nil { + log.Warn("Skipped deletion of %s configurations as appropriate client was unavailable.", config.GrailFilterSegmentID) + } else if err := grailfiltersegment.DeleteAll(ctx, clients.GrailFilterSegmentClient); err != nil { + log.Error("Failed to delete all %s configurations: %v", config.GrailFilterSegmentID, err) + errCount++ + } + } + if errCount > 0 { return fmt.Errorf("failed to delete all configurations for %d types", errCount) } diff --git a/pkg/delete/delete_test.go b/pkg/delete/delete_test.go index 4a1b1bb49..8b4e50441 100644 --- a/pkg/delete/delete_test.go +++ b/pkg/delete/delete_test.go @@ -1228,3 +1228,24 @@ func TestDelete_Segments(t *testing.T) { assert.NoError(t, err) }) } + +func TestDeleteAll_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().List(gomock.Any()).Return(grailfiltersegments.Response{StatusCode: http.StatusOK, Data: []byte(`[{"uid": "uid_1"},{"uid": "uid_2"},{"uid": "uid_3"}]`)}, nil).Times(1) + c.EXPECT().Delete(gomock.Any(), gomock.Any()).Times(3) + + err := delete.All(context.TODO(), client.ClientSet{GrailFilterSegmentClient: c}, api.APIs{}) + assert.NoError(t, err) + }) + + t.Run("FF is turned off", func(t *testing.T) { + c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t)) + // no calls to client + + err := delete.All(context.TODO(), client.ClientSet{GrailFilterSegmentClient: c}, api.APIs{}) + assert.NoError(t, err) + }) +} diff --git a/pkg/delete/internal/grailfiltersegment/delete.go b/pkg/delete/internal/grailfiltersegment/delete.go index b4746a2a3..6575e1abd 100644 --- a/pkg/delete/internal/grailfiltersegment/delete.go +++ b/pkg/delete/internal/grailfiltersegment/delete.go @@ -79,28 +79,20 @@ func deleteSingle(ctx context.Context, c client, dp pointer.DeletePointer) error } func findEntryWithExternalID(ctx context.Context, c client, dp pointer.DeletePointer) (string, error) { - listResp, err := c.List(ctx) + items, err := list(c, ctx) if err != nil { return "", err } - var items []struct { - Uid string `json:"uid"` - ExternalId string `json:"externalId"` - } - if err = json.Unmarshal(listResp.Data, &items); err != nil { - return "", fmt.Errorf("problem with reading recieved data: %w", err) - } - extID, err := idutils.GenerateExternalIDForDocument(dp.AsCoordinate()) if err != nil { return "", fmt.Errorf("unable to generate externalID: %w", err) } var foundUid []string - for _, item := range items { - if item.ExternalId == extID { - foundUid = append(foundUid, item.Uid) + for _, i := range items { + if i.ExternalId == extID { + foundUid = append(foundUid, i.Uid) } } @@ -122,3 +114,38 @@ func isAPIErrorStatusNotFound(err error) bool { return apiErr.StatusCode == http.StatusNotFound } + +func DeleteAll(ctx context.Context, c client) error { + items, err := list(c, ctx) + if err != nil { + return err + } + + var retErr error + for _, i := range items { + err := deleteSingle(ctx, c, pointer.DeletePointer{Type: string(config.GrailFilterSegmentID), OriginObjectId: i.Uid}) + if err != nil { + retErr = errors.Join(retErr, err) + } + } + return retErr +} + +type items []struct { + Uid string `json:"uid"` + ExternalId string `json:"externalId"` +} + +func list(c client, ctx context.Context) (items, error) { + listResp, err := c.List(ctx) + if err != nil { + return nil, err + } + + var items items + if err = json.Unmarshal(listResp.Data, &items); err != nil { + return nil, fmt.Errorf("problem with reading recieved data: %w", err) + } + + return items, nil +} diff --git a/pkg/delete/internal/grailfiltersegment/delete_test.go b/pkg/delete/internal/grailfiltersegment/delete_test.go index 16586938a..a1ff8b034 100644 --- a/pkg/delete/internal/grailfiltersegment/delete_test.go +++ b/pkg/delete/internal/grailfiltersegment/delete_test.go @@ -141,3 +141,29 @@ func TestDelete(t *testing.T) { assert.Error(t, err) }) } + +func TestDeleteAll(t *testing.T) { + t.Run("simple case", func(t *testing.T) { + c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t)) + c.EXPECT().List(gomock.Any()).Times(1). + Return(libSegment.Response{Data: []byte(`[{"uid": "uid_1"},{"uid": "uid_2"},{"uid": "uid_3"}]`)}, nil) + c.EXPECT().Delete(gomock.Any(), gomock.Eq("uid_1")).Times(1) + c.EXPECT().Delete(gomock.Any(), gomock.Eq("uid_2")).Times(1) + c.EXPECT().Delete(gomock.Any(), gomock.Eq("uid_3")).Times(1) + + err := grailfiltersegment.DeleteAll(context.TODO(), c) + assert.NoError(t, err) + }) + + t.Run("error during delete - continue to delete, an error", func(t *testing.T) { + c := client.NewMockGrailFilterSegmentClient(gomock.NewController(t)) + c.EXPECT().List(gomock.Any()).Times(1). + Return(libSegment.Response{Data: []byte(`[{"uid": "uid_1"},{"uid": "uid_2"},{"uid": "uid_3"}]`)}, nil) + c.EXPECT().Delete(gomock.Any(), gomock.Eq("uid_1")).Times(1) + c.EXPECT().Delete(gomock.Any(), gomock.Eq("uid_2")).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("uid_3")).Times(1) + + err := grailfiltersegment.DeleteAll(context.TODO(), c) + assert.Error(t, err) + }) +}