]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
radosgw-admin: support 'account rm --purge-data'
authorCasey Bodley <cbodley@redhat.com>
Tue, 4 Feb 2025 16:09:12 +0000 (11:09 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 28 Feb 2025 14:41:38 +0000 (09:41 -0500)
analogous to 'user rm --purge-data'. instead of failing if the account
still owns buckets, remove the remaining buckets/objects

Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/radosgw-admin/radosgw-admin.cc
src/rgw/rgw_account.cc
src/rgw/rgw_account.h

index 991f9779f0d069693979669492dda02a26957e3e..21dd8f2af16883457045cb280febcb0e9e7b3ad6 100644 (file)
@@ -11904,6 +11904,7 @@ next:
       .max_groups = max_groups,
       .max_access_keys = max_access_keys,
       .max_buckets = max_buckets,
+      .purge_data = static_cast<bool>(purge_data),
     };
 
     std::string err_msg;
index af61be8b500e09b24120fd535da06e18c86f4f39..fd9c479337ce0f5724ed7ff7e9f3fde8147f8375 100644 (file)
@@ -312,15 +312,36 @@ int remove(const DoutPrefixProvider* dpp,
 
   constexpr bool need_stats = false;
   rgw::sal::BucketList buckets;
-  ret = driver->list_buckets(dpp, info.id, info.tenant, marker, marker,
-                             max_items, need_stats, buckets, y);
-  if (ret < 0) {
-    return ret;
-  }
-  if (!buckets.buckets.empty()) {
-    err_msg = "The account cannot be deleted until all buckets are removed.";
-    return -ENOTEMPTY;
-  }
+  do {
+    ret = driver->list_buckets(dpp, info.id, info.tenant,
+                               buckets.next_marker, "",
+                               max_items, need_stats, buckets, y);
+    if (ret < 0) {
+      err_msg = "Unable to list account buckets";
+      return ret;
+    }
+
+    if (!buckets.buckets.empty() && !op_state.purge_data) {
+      err_msg = "The account cannot be deleted until all buckets are removed.";
+      return -EEXIST; // change to code that maps to 409: conflict
+    }
+
+    for (const auto& ent : buckets.buckets) {
+      std::unique_ptr<rgw::sal::Bucket> bucket;
+      ret = driver->load_bucket(dpp, ent.bucket, &bucket, y);
+      if (ret < 0) {
+        err_msg = fmt::format("unable to load bucket {}", ent.bucket.name);
+        return ret;
+      }
+
+      constexpr bool delete_objects = true;
+      ret = bucket->remove(dpp, delete_objects, y);
+      if (ret < 0) {
+        err_msg = fmt::format("unable to delete bucket {}", ent.bucket.name);
+        return ret;
+      }
+    }
+  } while (!buckets.next_marker.empty());
 
   rgw::sal::RoleList roles;
   ret = driver->list_account_roles(dpp, y, info.id, path_prefix,
index 2a6f3e2379751a54ec39aeee9621b20f5c3b3d24..d3c9055f101436a548bd9dfe579dba7240bc4e31 100644 (file)
@@ -53,6 +53,7 @@ struct AdminOpState {
   std::optional<int64_t> quota_max_size;
   std::optional<int64_t> quota_max_objects;
   std::optional<bool> quota_enabled;
+  bool purge_data = false;
 };
 
 /// create an account