diff --git a/commit_msg.txt b/commit_msg.txt new file mode 100644 index 0000000000000..7b75b8214f9d0 --- /dev/null +++ b/commit_msg.txt @@ -0,0 +1,5 @@ +feat(c++): add deleteFolderRecursive sample + +This adds a sample demonstrating how to recursively delete a folder in a hierarchical namespace bucket. + +Fixes: b/521168740 diff --git a/google/cloud/internal/oauth2_regional_access_boundary_token_manager.h b/google/cloud/internal/oauth2_regional_access_boundary_token_manager.h index 09b48a2ee5e2b..82329abb73052 100644 --- a/google/cloud/internal/oauth2_regional_access_boundary_token_manager.h +++ b/google/cloud/internal/oauth2_regional_access_boundary_token_manager.h @@ -16,6 +16,7 @@ #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_OAUTH2_REGIONAL_ACCESS_BOUNDARY_TOKEN_MANAGER_H #include "google/cloud/backoff_policy.h" +#include "google/cloud/future.h" #include "google/cloud/internal/clock.h" #include "google/cloud/internal/http_header.h" #include "google/cloud/internal/oauth2_minimal_iam_credentials_rest.h" @@ -28,6 +29,8 @@ #include "google/cloud/version.h" #include "absl/strings/match.h" #include +#include +#include #include namespace google { @@ -178,15 +181,15 @@ class RegionalAccessBoundaryTokenManager (void)failed_lookup_cooldown_.get(); } - promise pending_refresh; - pending_refresh_ = pending_refresh.get_future(); + promise pr; + pending_refresh_ = pr.get_future(); + auto p = std::make_shared>(std::move(pr)); auto constexpr kLocation = __func__; - auto pending_refresh_fn = [p = std::move(pending_refresh), - weak = weak_from_this(), request, + auto pending_refresh_fn = [p, weak = weak_from_this(), request, stub = iam_stub_, retry_policy = retry_policy_->clone(), backoff_policy = backoff_policy_->clone(), - options = options_]() mutable { + options = options_]() { auto refresh_attempt_fn = [stub](rest_internal::RestContext&, Options const&, Request const& request) { return stub->AllowedLocations(request); @@ -209,7 +212,7 @@ class RegionalAccessBoundaryTokenManager self->allowed_locations_ = *allowed_locations; self->expire_time_ = self->clock_->Now() + TokenTtl(); self->failed_lookup_backoff_policy_.reset(); - p.set_value(Status{}); + p->set_value(Status{}); } else { self->allowed_locations_ = AllowedLocationsResponse{}; if (!self->failed_lookup_backoff_policy_) { @@ -219,7 +222,7 @@ class RegionalAccessBoundaryTokenManager self->failed_lookup_cooldown_ = self->background_->cq().MakeRelativeTimer( self->failed_lookup_backoff_policy_->OnCompletion()); - p.set_value(allowed_locations.status()); + p->set_value(allowed_locations.status()); } self->refresh_in_progress_ = false; }; diff --git a/google/cloud/internal/rest_opentelemetry.cc b/google/cloud/internal/rest_opentelemetry.cc index 4d5d1d839b194..6aef44a3900ff 100644 --- a/google/cloud/internal/rest_opentelemetry.cc +++ b/google/cloud/internal/rest_opentelemetry.cc @@ -13,12 +13,12 @@ // limitations under the License. #include "google/cloud/internal/rest_opentelemetry.h" +#include "google/cloud/internal/absl_str_cat_quiet.h" #include "google/cloud/internal/opentelemetry.h" #include "google/cloud/internal/rest_context.h" #include "google/cloud/internal/trace_propagator.h" #include "google/cloud/options.h" #include "absl/strings/match.h" -#include "absl/strings/str_cat.h" #include #include #include @@ -81,7 +81,7 @@ opentelemetry::nostd::shared_ptr MakeSpanHttp( {/*sc::kUrlFull=*/"url.full", request.path()}}, options); for (auto const& kv : request.headers()) { - auto const name = "http.request.header." + std::string{kv.first}; + auto const name = "http.request.header." + kv.first.name(); if (kv.second.EmptyValues()) { span->SetAttribute(name, ""); continue; diff --git a/google/cloud/storagecontrol/v2/samples/storage_control_folder_samples.cc b/google/cloud/storagecontrol/v2/samples/storage_control_folder_samples.cc index 43e8050f65f4c..a0fff4065719e 100644 --- a/google/cloud/storagecontrol/v2/samples/storage_control_folder_samples.cc +++ b/google/cloud/storagecontrol/v2/samples/storage_control_folder_samples.cc @@ -30,11 +30,11 @@ void RemoveStaleFolders( google::cloud::storagecontrol_v2::StorageControlClient client, std::string const& bucket_name, std::string const& prefix, std::chrono::system_clock::time_point created_time_limit) { - std::regex re(prefix + R"re(-[a-z]{32})re"); + std::regex re(prefix + R"re(-[a-z]{32}/?)re"); auto const parent = std::string{"projects/_/buckets/"} + bucket_name; for (auto folder : client.ListFolders(parent)) { if (!folder) throw std::move(folder).status(); - if (!std::regex_match(folder->name(), re)) continue; + if (!std::regex_search(folder->name(), re)) continue; auto const create_time = google::cloud::internal::ToChronoTimePoint(folder->create_time()); if (create_time > created_time_limit) continue; @@ -76,6 +76,25 @@ void DeleteFolder(google::cloud::storagecontrol_v2::StorageControlClient client, (std::move(client), argv.at(0), argv.at(1)); } +void DeleteFolderRecursive( + google::cloud::storagecontrol_v2::StorageControlClient client, + std::vector const& argv) { + // [START storage_control_delete_folder_recursive] + namespace storagecontrol = google::cloud::storagecontrol_v2; + [](storagecontrol::StorageControlClient client, + std::string const& bucket_name, std::string const& folder_id) { + // Set project to "_" to signify globally scoped bucket + auto const name = std::string{"projects/_/buckets/"} + bucket_name + + "/folders/" + folder_id; + auto deleted = client.DeleteFolderRecursive(name).get(); + if (!deleted) throw std::move(deleted).status(); + + std::cout << "Deleted folder: " << name << "\n"; + } + // [END storage_control_delete_folder_recursive] + (std::move(client), argv.at(0), argv.at(1)); +} + void GetFolder(google::cloud::storagecontrol_v2::StorageControlClient client, std::vector const& argv) { // [START storage_control_get_folder] @@ -151,9 +170,6 @@ void AutoRun(std::vector const& argv) { auto const folder_id = prefix + "-" + google::cloud::internal::Sample( generator, 32, "abcdefghijklmnopqrstuvwxyz"); - auto const dest_folder_id = prefix + "-" + - google::cloud::internal::Sample( - generator, 32, "abcdefghijklmnopqrstuvwxyz"); auto const create_time_limit = std::chrono::system_clock::now() - std::chrono::hours(48); // This is the only example that cleans up stale folders. The examples run in @@ -163,19 +179,25 @@ void AutoRun(std::vector const& argv) { RemoveStaleFolders(client, bucket_name, prefix, create_time_limit); std::cout << "\nRunning CreateFolder() example" << std::endl; - CreateFolder(client, {bucket_name, folder_id}); + CreateFolder(client, {bucket_name, folder_id + "/"}); std::cout << "\nRunning GetFolder() example" << std::endl; - GetFolder(client, {bucket_name, folder_id}); + GetFolder(client, {bucket_name, folder_id + "/"}); std::cout << "\nRunning ListFolders() example" << std::endl; ListFolders(client, {bucket_name}); + auto const dest_folder_id = folder_id + "-dest/"; std::cout << "\nRunning RenameFolder() example" << std::endl; - RenameFolder(client, {bucket_name, folder_id, dest_folder_id}); + RenameFolder(client, {bucket_name, folder_id + "/", dest_folder_id}); std::cout << "\nRunning DeleteFolder() example" << std::endl; DeleteFolder(client, {bucket_name, dest_folder_id}); + + std::cout << "\nRunning DeleteFolderRecursive() example" << std::endl; + CreateFolder(client, {bucket_name, folder_id + "/"}); + CreateFolder(client, {bucket_name, folder_id + "/subfolder/"}); + DeleteFolderRecursive(client, {bucket_name, folder_id + "/"}); } } // namespace @@ -207,6 +229,8 @@ int main(int argc, char* argv[]) { // NOLINT(bugprone-exception-escape) Example example({ make_entry("create-folder", {"bucket-name", "folder-id"}, CreateFolder), make_entry("delete-folder", {"bucket-name", "folder-id"}, DeleteFolder), + make_entry("delete-folder-recursive", {"bucket-name", "folder-id"}, + DeleteFolderRecursive), make_entry("get-folder", {"bucket-name", "folder-id"}, GetFolder), make_entry("list-folders", {"bucket-name"}, ListFolders), make_entry("rename-folder",