Skip to content

Commit 22b5111

Browse files
committed
feat: migrate DeleteProjectResource API to Connect RPC
1 parent d17c358 commit 22b5111

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

internal/api/v1beta1connect/resource.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,36 @@ func (h *ConnectHandler) UpdateProjectResource(ctx context.Context, request *con
209209
}), nil
210210
}
211211

212+
func (h *ConnectHandler) DeleteProjectResource(ctx context.Context, request *connect.Request[frontierv1beta1.DeleteProjectResourceRequest]) (*connect.Response[frontierv1beta1.DeleteProjectResourceResponse], error) {
213+
resourceToDel, err := h.resourceService.Get(ctx, request.Msg.GetId())
214+
if err != nil {
215+
switch {
216+
case errors.Is(err, resource.ErrNotExist),
217+
errors.Is(err, resource.ErrInvalidID),
218+
errors.Is(err, resource.ErrInvalidUUID):
219+
return nil, connect.NewError(connect.CodeNotFound, ErrResourceNotFound)
220+
default:
221+
return nil, connect.NewError(connect.CodeInternal, ErrInternalServerError)
222+
}
223+
}
224+
225+
parentProject, err := h.projectService.Get(ctx, resourceToDel.ProjectID)
226+
if err != nil {
227+
return nil, connect.NewError(connect.CodeInternal, ErrInternalServerError)
228+
}
229+
230+
err = h.resourceService.Delete(ctx, resourceToDel.NamespaceID, resourceToDel.ID)
231+
if err != nil {
232+
return nil, connect.NewError(connect.CodeInternal, ErrInternalServerError)
233+
}
234+
235+
audit.GetAuditor(ctx, parentProject.Organization.ID).Log(audit.ResourceDeletedEvent, audit.Target{
236+
ID: request.Msg.GetId(),
237+
Type: resourceToDel.NamespaceID,
238+
})
239+
return connect.NewResponse(&frontierv1beta1.DeleteProjectResourceResponse{}), nil
240+
}
241+
212242
func transformResourceToPB(from resource.Resource) (*frontierv1beta1.Resource, error) {
213243
var metadata *structpb.Struct
214244
var err error

internal/api/v1beta1connect/resource_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,3 +724,144 @@ func TestConnectHandler_UpdateProjectResource(t *testing.T) {
724724
})
725725
}
726726
}
727+
728+
func TestConnectHandler_DeleteProjectResource(t *testing.T) {
729+
tests := []struct {
730+
name string
731+
setup func(rs *mocks.ResourceService, ps *mocks.ProjectService)
732+
request *connect.Request[frontierv1beta1.DeleteProjectResourceRequest]
733+
want *connect.Response[frontierv1beta1.DeleteProjectResourceResponse]
734+
wantErr error
735+
}{
736+
{
737+
name: "should return internal error if resource service Get returns error",
738+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
739+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(resource.Resource{}, errors.New("test error"))
740+
},
741+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
742+
Id: testResource.ID,
743+
}),
744+
want: nil,
745+
wantErr: connect.NewError(connect.CodeInternal, ErrInternalServerError),
746+
},
747+
{
748+
name: "should return not found error if resource not exist",
749+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
750+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(resource.Resource{}, resource.ErrNotExist)
751+
},
752+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
753+
Id: testResource.ID,
754+
}),
755+
want: nil,
756+
wantErr: connect.NewError(connect.CodeNotFound, ErrResourceNotFound),
757+
},
758+
{
759+
name: "should return not found error if id is invalid",
760+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
761+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), "some-id").Return(resource.Resource{}, resource.ErrInvalidUUID)
762+
},
763+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
764+
Id: "some-id",
765+
}),
766+
want: nil,
767+
wantErr: connect.NewError(connect.CodeNotFound, ErrResourceNotFound),
768+
},
769+
{
770+
name: "should return not found error if id is empty",
771+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
772+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), "").Return(resource.Resource{}, resource.ErrInvalidID)
773+
},
774+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{}),
775+
want: nil,
776+
wantErr: connect.NewError(connect.CodeNotFound, ErrResourceNotFound),
777+
},
778+
{
779+
name: "should return internal error if project service returns error",
780+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
781+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(testResource, nil)
782+
ps.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ProjectID).Return(project.Project{}, errors.New("test error"))
783+
},
784+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
785+
Id: testResource.ID,
786+
}),
787+
want: nil,
788+
wantErr: connect.NewError(connect.CodeInternal, ErrInternalServerError),
789+
},
790+
{
791+
name: "should return internal error if resource service Delete returns error",
792+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
793+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(testResource, nil)
794+
ps.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ProjectID).Return(project.Project{
795+
ID: testResource.ProjectID,
796+
Organization: organization.Organization{
797+
ID: "test-org-id",
798+
},
799+
}, nil)
800+
rs.EXPECT().Delete(mock.AnythingOfType("context.backgroundCtx"), testResource.NamespaceID, testResource.ID).Return(errors.New("delete error"))
801+
},
802+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
803+
Id: testResource.ID,
804+
}),
805+
want: nil,
806+
wantErr: connect.NewError(connect.CodeInternal, ErrInternalServerError),
807+
},
808+
{
809+
name: "should return success if resource is deleted successfully",
810+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
811+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(testResource, nil)
812+
ps.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ProjectID).Return(project.Project{
813+
ID: testResource.ProjectID,
814+
Organization: organization.Organization{
815+
ID: "test-org-id",
816+
},
817+
}, nil)
818+
rs.EXPECT().Delete(mock.AnythingOfType("context.backgroundCtx"), testResource.NamespaceID, testResource.ID).Return(nil)
819+
},
820+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
821+
Id: testResource.ID,
822+
}),
823+
want: connect.NewResponse(&frontierv1beta1.DeleteProjectResourceResponse{}),
824+
wantErr: nil,
825+
},
826+
{
827+
name: "should handle deletion with different namespace correctly",
828+
setup: func(rs *mocks.ResourceService, ps *mocks.ProjectService) {
829+
resourceWithDiffNS := testResource
830+
resourceWithDiffNS.NamespaceID = "different-namespace"
831+
rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(resourceWithDiffNS, nil)
832+
ps.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ProjectID).Return(project.Project{
833+
ID: testResource.ProjectID,
834+
Organization: organization.Organization{
835+
ID: "test-org-id",
836+
},
837+
}, nil)
838+
rs.EXPECT().Delete(mock.AnythingOfType("context.backgroundCtx"), "different-namespace", testResource.ID).Return(nil)
839+
},
840+
request: connect.NewRequest(&frontierv1beta1.DeleteProjectResourceRequest{
841+
Id: testResource.ID,
842+
}),
843+
want: connect.NewResponse(&frontierv1beta1.DeleteProjectResourceResponse{}),
844+
wantErr: nil,
845+
},
846+
}
847+
848+
for _, tt := range tests {
849+
t.Run(tt.name, func(t *testing.T) {
850+
mockResourceSrv := new(mocks.ResourceService)
851+
mockProjectSrv := new(mocks.ProjectService)
852+
if tt.setup != nil {
853+
tt.setup(mockResourceSrv, mockProjectSrv)
854+
}
855+
h := ConnectHandler{resourceService: mockResourceSrv, projectService: mockProjectSrv}
856+
resp, err := h.DeleteProjectResource(context.Background(), tt.request)
857+
if tt.wantErr != nil {
858+
assert.Error(t, err)
859+
assert.Equal(t, tt.wantErr.(*connect.Error).Code(), err.(*connect.Error).Code())
860+
assert.Equal(t, tt.wantErr.(*connect.Error).Message(), err.(*connect.Error).Message())
861+
} else {
862+
assert.NoError(t, err)
863+
assert.EqualValues(t, tt.want, resp)
864+
}
865+
})
866+
}
867+
}

0 commit comments

Comments
 (0)