diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index f2c6acf9f46..46c192323f9 100644 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -457,11 +457,18 @@ class RgwBucket(RgwRESTController): self._set_acl(bucket_name, canned_acl, uid, daemon_name) return self._append_bid(result) - def delete(self, bucket, purge_objects='true', daemon_name=None): - return self.proxy(daemon_name, 'DELETE', 'bucket', { - 'bucket': bucket, - 'purge-objects': purge_objects - }, json_response=False) + def delete(self, bucket, daemon_name=None): + try: + bucket_info = self.proxy(daemon_name, 'GET', 'bucket', {'bucket': bucket}) + num_objects = bucket_info.get('usage', {}).get('rgw.main', {}).get('num_objects', 0) + if num_objects > 0: + raise DashboardException(msg='Unable to delete bucket"{}" - Bucket is not empty. ' + 'Remove all objects before deletion.'.format(bucket)) + return self.proxy(daemon_name, 'DELETE', 'bucket', { + 'bucket': bucket + }, json_response=False) + except (DashboardException, RequestException) as e: # pragma: no cover + raise DashboardException(e, component='rgw') @RESTController.Collection(method='PUT', path='/setEncryptionConfig') @allow_empty_body diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts index 23f77001ecb..3ecb85316c0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts @@ -117,12 +117,22 @@ export class RgwBucketListComponent extends ListWithDetails implements OnInit, O permission: 'delete', icon: Icons.destroy, click: () => this.deleteAction(), + disable: () => this.isDeleteDisabled(), name: this.actionLabels.DELETE }; this.tableActions = [addAction, editAction, deleteAction]; this.setTableRefreshTimeout(); } + isDeleteDisabled(): boolean | string { + if (!this.selection.first()) { + return true; + } + return this.selection.first()?.num_objects > 0 + ? $localize`Bucket is not empty. Remove all objects before deletion.` + : false; + } + getBucketList(context: CdTableFetchDataContext) { this.setTableRefreshTimeout(); this.subs.add( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts index eaed2c4abac..6481bb2041d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts @@ -97,19 +97,9 @@ describe('RgwBucketService', () => { expect(req.request.method).toBe('PUT'); }); - it('should call delete, with purgeObjects = true', () => { + it('should call delete', () => { service.delete('foo').subscribe(); - const req = httpTesting.expectOne( - `api/rgw/bucket/foo?${RgwHelper.DAEMON_QUERY_PARAM}&purge_objects=true` - ); - expect(req.request.method).toBe('DELETE'); - }); - - it('should call delete, with purgeObjects = false', () => { - service.delete('foo', false).subscribe(); - const req = httpTesting.expectOne( - `api/rgw/bucket/foo?${RgwHelper.DAEMON_QUERY_PARAM}&purge_objects=false` - ); + const req = httpTesting.expectOne(`api/rgw/bucket/foo?${RgwHelper.DAEMON_QUERY_PARAM}`); expect(req.request.method).toBe('DELETE'); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts index 8dbebff1f61..0d17c7abdd4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts @@ -184,9 +184,8 @@ export class RgwBucketService extends ApiClient { }); } - delete(bucket: string, purgeObjects = true) { + delete(bucket: string) { return this.rgwDaemonService.request((params: HttpParams) => { - params = params.append('purge_objects', purgeObjects ? 'true' : 'false'); return this.http.delete(`${this.url}/${bucket}`, { params: params }); }); } diff --git a/src/pybind/mgr/dashboard/openapi.yaml b/src/pybind/mgr/dashboard/openapi.yaml index 560ed870e6f..14ad6c9e306 100644 --- a/src/pybind/mgr/dashboard/openapi.yaml +++ b/src/pybind/mgr/dashboard/openapi.yaml @@ -9759,11 +9759,6 @@ paths: required: true schema: type: string - - default: 'true' - in: query - name: purge_objects - schema: - type: string - allowEmptyValue: true in: query name: daemon_name