From d76678a55032731670294a652d9f06f9bdaaacb1 Mon Sep 17 00:00:00 2001 From: Ginny Guan Date: Mon, 7 Oct 2024 09:51:53 +0800 Subject: [PATCH] fix: Delete device profile in use should return 409 close #4937 Signed-off-by: Ginny Guan --- .../core/metadata/application/deviceprofile.go | 16 ++++++++++++++++ .../core/metadata/application/deviceservice.go | 16 ++++++++++++++++ .../controller/http/deviceprofile_test.go | 18 ++++++++++-------- .../controller/http/deviceservice_test.go | 18 ++++++++++-------- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/internal/core/metadata/application/deviceprofile.go b/internal/core/metadata/application/deviceprofile.go index 1cbd405411..061d509736 100644 --- a/internal/core/metadata/application/deviceprofile.go +++ b/internal/core/metadata/application/deviceprofile.go @@ -112,6 +112,22 @@ func DeleteDeviceProfileByName(name string, ctx context.Context, dic *di.Contain if err != nil { return errors.NewCommonEdgeXWrapper(err) } + // Check the associated Device and ProvisionWatcher existence + devices, edgeXErr := dbClient.DevicesByProfileName(0, 1, name) + if edgeXErr != nil { + return errors.NewCommonEdgeXWrapper(edgeXErr) + } + if len(devices) > 0 { + return errors.NewCommonEdgeX(errors.KindStatusConflict, "fail to delete the device profile when associated device exists", nil) + } + provisionWatchers, edgeXErr := dbClient.ProvisionWatchersByProfileName(0, 1, name) + if edgeXErr != nil { + return errors.NewCommonEdgeXWrapper(edgeXErr) + } + if len(provisionWatchers) > 0 { + return errors.NewCommonEdgeX(errors.KindStatusConflict, "fail to delete the device profile when associated provisionWatcher exists", nil) + } + err = dbClient.DeleteDeviceProfileByName(name) if err != nil { return errors.NewCommonEdgeXWrapper(err) diff --git a/internal/core/metadata/application/deviceservice.go b/internal/core/metadata/application/deviceservice.go index e445a51a80..7bd3a48f7e 100644 --- a/internal/core/metadata/application/deviceservice.go +++ b/internal/core/metadata/application/deviceservice.go @@ -112,6 +112,22 @@ func DeleteDeviceServiceByName(name string, ctx context.Context, dic *di.Contain if err != nil { return errors.NewCommonEdgeXWrapper(err) } + // Check the associated Device and ProvisionWatcher existence + devices, edgeXErr := dbClient.DevicesByServiceName(0, 1, name) + if edgeXErr != nil { + return errors.NewCommonEdgeXWrapper(edgeXErr) + } + if len(devices) > 0 { + return errors.NewCommonEdgeX(errors.KindStatusConflict, "fail to delete the device service when associated device exists", nil) + } + provisionWatchers, edgeXErr := dbClient.ProvisionWatchersByServiceName(0, 1, name) + if edgeXErr != nil { + return errors.NewCommonEdgeXWrapper(edgeXErr) + } + if len(provisionWatchers) > 0 { + return errors.NewCommonEdgeX(errors.KindStatusConflict, "fail to delete the device service when associated provisionWatcher exists", nil) + } + err = dbClient.DeleteDeviceServiceByName(name) if err != nil { return errors.NewCommonEdgeXWrapper(err) diff --git a/internal/core/metadata/controller/http/deviceprofile_test.go b/internal/core/metadata/controller/http/deviceprofile_test.go index 9d077d5766..f1d2fa5e6a 100644 --- a/internal/core/metadata/controller/http/deviceprofile_test.go +++ b/internal/core/metadata/controller/http/deviceprofile_test.go @@ -1113,18 +1113,20 @@ func TestDeleteDeviceProfileByName(t *testing.T) { dic := mockDic() dbClientMock := &mocks.DBClient{} + dbClientMock.On("DeviceProfileByName", deviceProfile.Name).Return(models.DeviceProfile{}, nil) dbClientMock.On("DevicesByProfileName", 0, 1, deviceProfile.Name).Return([]models.Device{}, nil) dbClientMock.On("ProvisionWatchersByProfileName", 0, 1, deviceProfile.Name).Return([]models.ProvisionWatcher{}, nil) dbClientMock.On("DeleteDeviceProfileByName", deviceProfile.Name).Return(nil) - dbClientMock.On("DevicesByProfileName", 0, 1, notFoundName).Return([]models.Device{}, nil) - dbClientMock.On("ProvisionWatchersByProfileName", 0, 1, notFoundName).Return([]models.ProvisionWatcher{}, nil) - dbClientMock.On("DeleteDeviceProfileByName", notFoundName).Return(errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, "device profile doesn't exist in the database", nil)) - dbClientMock.On("DeleteDeviceProfileByName", deviceExists).Return(errors.NewCommonEdgeX( - errors.KindStatusConflict, "fail to delete the device profile when associated device exists", nil)) - dbClientMock.On("DeleteDeviceProfileByName", provisionWatcherExists).Return(errors.NewCommonEdgeX( - errors.KindStatusConflict, "fail to delete the device profile when associated provisionWatcher exists", nil)) + + dbClientMock.On("DeviceProfileByName", notFoundName).Return(models.DeviceProfile{}, errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, "not found", nil)) + + dbClientMock.On("DeviceProfileByName", deviceExists).Return(models.DeviceProfile{}, nil) + dbClientMock.On("DevicesByProfileName", 0, 1, deviceExists).Return([]models.Device{{ServiceName: testDeviceServiceName}}, nil) + + dbClientMock.On("DeviceProfileByName", provisionWatcherExists).Return(models.DeviceProfile{}, nil) + dbClientMock.On("DevicesByProfileName", 0, 1, provisionWatcherExists).Return([]models.Device{}, nil) dbClientMock.On("ProvisionWatchersByProfileName", 0, 1, provisionWatcherExists).Return([]models.ProvisionWatcher{models.ProvisionWatcher{}}, nil) - dbClientMock.On("DeviceProfileByName", mock.Anything).Return(models.DeviceProfile{}, nil) + dic.Update(di.ServiceConstructorMap{ container.DBClientInterfaceName: func(get di.Get) interface{} { return dbClientMock diff --git a/internal/core/metadata/controller/http/deviceservice_test.go b/internal/core/metadata/controller/http/deviceservice_test.go index ca458f4a20..8188a171cb 100644 --- a/internal/core/metadata/controller/http/deviceservice_test.go +++ b/internal/core/metadata/controller/http/deviceservice_test.go @@ -489,18 +489,20 @@ func TestDeleteDeviceServiceByName(t *testing.T) { dic := mockDic() dbClientMock := &dbMock.DBClient{} + dbClientMock.On("DeviceServiceByName", deviceService.Name).Return(models.DeviceService{}, nil) dbClientMock.On("DevicesByServiceName", 0, 1, deviceService.Name).Return([]models.Device{}, nil) dbClientMock.On("ProvisionWatchersByServiceName", 0, 1, deviceService.Name).Return([]models.ProvisionWatcher{}, nil) dbClientMock.On("DeleteDeviceServiceByName", deviceService.Name).Return(nil) - dbClientMock.On("DevicesByServiceName", 0, 1, notFoundName).Return([]models.Device{}, nil) - dbClientMock.On("ProvisionWatchersByServiceName", 0, 1, notFoundName).Return([]models.ProvisionWatcher{}, nil) - dbClientMock.On("DeleteDeviceServiceByName", notFoundName).Return(errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, "device service doesn't exist in the database", nil)) - dbClientMock.On("DeleteDeviceServiceByName", deviceExists).Return(errors.NewCommonEdgeX( - errors.KindStatusConflict, "fail to delete the device service when associated device exists", nil)) - dbClientMock.On("DeleteDeviceServiceByName", provisionWatcherExists).Return(errors.NewCommonEdgeX( - errors.KindStatusConflict, "fail to delete the device service when associated provisionWatcher exists", nil)) + + dbClientMock.On("DeviceServiceByName", notFoundName).Return(models.DeviceService{}, errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, "device service doesn't exist in the database", nil)) + + dbClientMock.On("DeviceServiceByName", deviceExists).Return(models.DeviceService{}, nil) + dbClientMock.On("DevicesByServiceName", 0, 1, deviceExists).Return([]models.Device{{ServiceName: testDeviceServiceName}}, nil) + + dbClientMock.On("DeviceServiceByName", provisionWatcherExists).Return(models.DeviceService{}, nil) + dbClientMock.On("DevicesByServiceName", 0, 1, provisionWatcherExists).Return([]models.Device{}, nil) dbClientMock.On("ProvisionWatchersByServiceName", 0, 1, provisionWatcherExists).Return([]models.ProvisionWatcher{models.ProvisionWatcher{}}, nil) - dbClientMock.On("DeviceServiceByName", mock.Anything).Return(models.DeviceService{}, nil) + dic.Update(di.ServiceConstructorMap{ container.DBClientInterfaceName: func(get di.Get) interface{} { return dbClientMock