From a9c0e61dc222579be16e6de065d1a226915b4563 Mon Sep 17 00:00:00 2001 From: Sneha Sahu Date: Mon, 2 Nov 2026 13:06:26 +0000 Subject: [PATCH 1/2] samples(storage-control): add Rapid Cache samples Adds create, get, list, update and disable Rapid Cache samples for Storage Control, with an acceptance test gated by STORAGE_CONTROL_RUN_RAPID_CACHE_TESTS. b/482946642 [Generated-by: AI] --- .../samples/Gemfile.lock | 52 ++++----- .../samples/acceptance/helper.rb | 42 ++++++- .../storage_control_rapid_cache_test.rb | 110 ++++++++++++++++++ .../storage_control_create_rapid_cache.rb | 57 +++++++++ .../storage_control_disable_rapid_cache.rb | 48 ++++++++ .../storage_control_get_rapid_cache.rb | 43 +++++++ .../storage_control_list_rapid_caches.rb | 43 +++++++ .../storage_control_update_rapid_cache.rb | 66 +++++++++++ 8 files changed, 433 insertions(+), 28 deletions(-) create mode 100644 google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb create mode 100644 google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb create mode 100644 google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb create mode 100644 google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb create mode 100644 google-cloud-storage-control/samples/storage_control_list_rapid_caches.rb create mode 100644 google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb diff --git a/google-cloud-storage-control/samples/Gemfile.lock b/google-cloud-storage-control/samples/Gemfile.lock index f86a65ee1570..34d24917efec 100644 --- a/google-cloud-storage-control/samples/Gemfile.lock +++ b/google-cloud-storage-control/samples/Gemfile.lock @@ -19,7 +19,7 @@ GEM net-http (~> 0.5) faraday-retry (2.4.0) faraday (~> 2.0) - gapic-common (1.3.0) + gapic-common (1.6.1) faraday (>= 1.9, < 3.a) faraday-retry (>= 1.0, < 3.a) google-cloud-env (~> 2.2) @@ -28,7 +28,7 @@ GEM googleapis-common-protos (~> 1.6) googleapis-common-protos-types (~> 1.15) googleauth (~> 1.12) - grpc (~> 1.66) + grpc (>= 1.84.1, < 2.a) google-apis-core (1.2.5) addressable (~> 2.9) faraday (~> 2.13) @@ -58,11 +58,11 @@ GEM google-cloud-core (~> 1.6) googleauth (~> 1.9) mini_mime (~> 1.0) - google-cloud-storage-control (1.4.0) + google-cloud-storage-control (1.4.2) google-cloud-core (~> 1.6) google-cloud-storage-control-v2 (>= 0.0, < 2.a) - google-cloud-storage-control-v2 (1.13.0) - gapic-common (~> 1.3) + google-cloud-storage-control-v2 (1.15.0) + gapic-common (~> 1.6) google-cloud-errors (~> 1.0) grpc-google-iam-v1 (~> 1.11) google-logging-utils (0.2.0) @@ -109,31 +109,31 @@ GEM os (>= 0.9, < 2.0) pstore (~> 0.1) signet (>= 0.16, < 2.a) - grpc (1.83.0) + grpc (1.85.0) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-aarch64-linux-gnu) + grpc (1.85.0-aarch64-linux-gnu) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-aarch64-linux-musl) + grpc (1.85.0-aarch64-linux-musl) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-arm64-darwin) + grpc (1.85.0-arm64-darwin) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-x86-linux-gnu) + grpc (1.85.0-x86-linux-gnu) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-x86-linux-musl) + grpc (1.85.0-x86-linux-musl) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-x86_64-darwin) + grpc (1.85.0-x86_64-darwin) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-x86_64-linux-gnu) + grpc (1.85.0-x86_64-linux-gnu) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) - grpc (1.83.0-x86_64-linux-musl) + grpc (1.85.0-x86_64-linux-musl) google-protobuf (>= 3.25, < 5.0) googleapis-common-protos-types (~> 1.0) grpc-google-iam-v1 (1.12.0) @@ -230,7 +230,7 @@ CHECKSUMS faraday-follow_redirects (0.5.0) sha256=5cde93c894b30943a5d2b93c2fe9284216a6b756f7af406a1e55f211d97d10ad faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588 faraday-retry (2.4.0) sha256=7b79c48fb7e56526faf247b12d94a680071ff40c9fda7cf1ec1549439ad11ebe - gapic-common (1.3.0) sha256=4e5d9be1effb7366e2cda13c0f44922285d5613ac8de8b9b18c2c835fe4faa91 + gapic-common (1.6.1) sha256=b4d5c2b1a68f30bb316581e447678377972773ce44d3f5959580b1df075a801e google-apis-core (1.2.5) sha256=e21562b5627a0fc6a0c3165e429c3afed0f6a628eaa514e83f7204dda1adff69 google-apis-iamcredentials_v1 (0.28.0) sha256=0a92ffe6cc39c569554af2a77a25dfc61519ed8bbb64ab04cffdd352dc5ef106 google-apis-storage_v1 (0.65.0) sha256=4247aa542931691f6988ab61e45cdea2878cbfe897a98eec4af9cdcb678eb359 @@ -238,8 +238,8 @@ CHECKSUMS google-cloud-env (2.4.0) sha256=01cb35ecee5d1c4d1cd4deaed8bb5bddc838e296bcc2a35c5d1ddd07ce40d28d google-cloud-errors (1.7.0) sha256=6e682f42d89aae08689f36f28495de629d756da076bafff0003bac7f8042ebb3 google-cloud-storage (1.62.0) sha256=e2c3c08bf8fd40d50be92304084942203314d4fc0ee52028e99f9359c3ad1330 - google-cloud-storage-control (1.4.0) sha256=f43ef850840e907a701fc95492a9cd7f95e7c7a7283ae7b456714b4ed1080ed4 - google-cloud-storage-control-v2 (1.13.0) sha256=7e4192323c3afcf77ad06c8708ec28e97ed1294d6fc372c308681594f347c42f + google-cloud-storage-control (1.4.2) sha256=4f7718c26278fada9a0ff2d52e2f995057be4696154eab0efd6465333c3afba4 + google-cloud-storage-control-v2 (1.15.0) sha256=c5103303a07ebdd775cbf2d6a4ed57d3dbdf284460eecb46a0dc14505fd78367 google-logging-utils (0.2.0) sha256=675462b4ea5affa825a3442694ca2d75d0069455a1d0956127207498fca3df7b google-protobuf (4.35.1) sha256=a3a6471331d918f58dfa4d014a8f6286f0af2cf4840216bde52fcf2ea3fe3726 google-protobuf (4.35.1-aarch64-linux-gnu) sha256=50ca44d0eeff3f8475e630a1accdd974256f3510694d574e2c9d6119ea8bc9e1 @@ -254,15 +254,15 @@ CHECKSUMS googleapis-common-protos (1.9.0) sha256=207be372d8d25e3876e1e1155d057e14f3c92f8f5428772864a8ce04a0b756e4 googleapis-common-protos-types (1.23.0) sha256=992e740a523794d9fc5f29a504465d8fc737aaa16c930fe7228e3346860faf0a googleauth (1.17.3) sha256=9a655455885c0c17a8b70537acd2a992a7c7842c43c06c6612dfb0d93e755d58 - grpc (1.83.0) sha256=38119e7f9f7cbc98e79145201da4be470a7542b0befad454651d35015ea55c59 - grpc (1.83.0-aarch64-linux-gnu) sha256=11562efdded494b2277fd9c3c530dfdf90177faa111526ae9e748d0be29f1a9d - grpc (1.83.0-aarch64-linux-musl) sha256=ee745eab4f3922ed27d379cbc4bc0a99e58db367fa96312e9fe258aafd3afeb2 - grpc (1.83.0-arm64-darwin) sha256=25dd772aa80529f014d70da069787cd39b469c9edacbe493da4ff19952a147e2 - grpc (1.83.0-x86-linux-gnu) sha256=e9b20f54b8e8915f3921f12b266742e79da2c31d60e88295e15d0d16ea3cfd55 - grpc (1.83.0-x86-linux-musl) sha256=868e66d9c2a77eca1a93292fd879565219821fb5888673aedd08154303c9520c - grpc (1.83.0-x86_64-darwin) sha256=cfad91d559d1907159a5247fb12dc112a8ea0ebe2027ca7f5ab648d01a645716 - grpc (1.83.0-x86_64-linux-gnu) sha256=25d66bfa3cb1b05258b3f9632478c7e7ceb52cb16ccc0b4b26d7df36be7158b1 - grpc (1.83.0-x86_64-linux-musl) sha256=a5023264dbb8038c23b147bbf80adb06932ef11b5ab493412e9e37a43114fa8c + grpc (1.85.0) sha256=790fb8073453a7a4e4ade9ab265b92d6e8129f60c8ddae06cc9e3cb18e3e2366 + grpc (1.85.0-aarch64-linux-gnu) sha256=d38ea50e5b45ce7ee8416b522e5926d271a94f8a3346d886625efe0043c6e2bd + grpc (1.85.0-aarch64-linux-musl) sha256=a84380f5586ae7d6393f69543c07ff5c85758236f52ebdc02c675530d2154015 + grpc (1.85.0-arm64-darwin) sha256=27441b9851dbb07b57442b54cfaa4c31a6f0446a409bf0d932c1d0f94fc243b7 + grpc (1.85.0-x86-linux-gnu) sha256=23466d2db1f493e615e025323f483af50e36316fa8f4645adcf9d5f7f0abcc13 + grpc (1.85.0-x86-linux-musl) sha256=1066fa19a851954a1954ea98fab520f8af00e7454de00edd2a87e3a10f5cf86d + grpc (1.85.0-x86_64-darwin) sha256=e451ef4d733408530db44028197e8d9449743fcaed2ef81801e537a3c03d1516 + grpc (1.85.0-x86_64-linux-gnu) sha256=1623b7d7c9a7c8a2f4709ffa00ad98fb873a530cf7003de76fc9136adebcaa9d + grpc (1.85.0-x86_64-linux-musl) sha256=dfc3ffa78de52c9b491d580ca445e0a4f62fbbc88c5d9e0c24abcdb812133d7b grpc-google-iam-v1 (1.12.0) sha256=a70ecad8987e340d5e22e7bf01be31256c84b29a3f78bebd385a4a110e1f2aef json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a jwt (3.2.0) sha256=5419b1fe37b1da0982bd07051f573a8b8789ab724c2aa7e785e4784a3ed217d7 diff --git a/google-cloud-storage-control/samples/acceptance/helper.rb b/google-cloud-storage-control/samples/acceptance/helper.rb index e419ad4b5798..f7713e28a63a 100644 --- a/google-cloud-storage-control/samples/acceptance/helper.rb +++ b/google-cloud-storage-control/samples/acceptance/helper.rb @@ -32,15 +32,53 @@ def storage_client @storage_client ||= Google::Cloud::Storage.new end -def create_bucket_helper bucket_name, uniform_bucket_level_access: nil, hierarchical_namespace: nil +def create_bucket_helper bucket_name, uniform_bucket_level_access: nil, hierarchical_namespace: nil, location: nil retry_resource_exhaustion do - storage_client.create_bucket bucket_name do |b| + storage_client.create_bucket bucket_name, location: location do |b| b.uniform_bucket_level_access = uniform_bucket_level_access b.hierarchical_namespace = hierarchical_namespace end end end +# Returns the region of a zone, e.g. "us-east1" for "us-east1-b". +def zone_region zone + zone.sub(/-[a-z]\z/, "") +end + +# Returns the IDs of the Rapid Caches of a bucket, or an empty array if they +# cannot be listed. +# +# @param bucket_name [String] The name of the Google Cloud Storage bucket. +def rapid_cache_ids_helper bucket_name + storage_control_client = Google::Cloud::Storage::Control.storage_control + # Set project to "_" to signify global bucket + parent = "projects/_/buckets/#{bucket_name}" + storage_control_client.list_rapid_caches(parent: parent).map { |cache| cache.name.split("/").last } +rescue StandardError => e + puts "\nFailed to list Rapid Caches in bucket #{bucket_name}: #{e.message}" + [] +end + +# Best-effort deletion of a bucket that had a Rapid Cache. +# +# A bucket cannot be deleted until its Rapid Cache has been fully removed, +# which can take more than 30 minutes after the cache is disabled. This method +# retries briefly and then leaves the bucket for the stale bucket cleanup job. +# +# @param bucket_name [String] The name of the Google Cloud Storage bucket. +def delete_bucket_with_rapid_cache_helper bucket_name, attempts: 6, interval: 20 + attempts.times do |attempt| + delete_bucket_helper bucket_name + return true + rescue Google::Cloud::FailedPreconditionError, Google::Cloud::AlreadyExistsError => e + puts "\nBucket #{bucket_name} not deleted yet (attempt #{attempt + 1}/#{attempts}): #{e.message}" + sleep interval + end + puts "\nLeaving bucket #{bucket_name} for the stale bucket cleanup job." + false +end + def delete_bucket_helper bucket_name retry_resource_exhaustion do bucket = storage_client.bucket bucket_name diff --git a/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb b/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb new file mode 100644 index 000000000000..bde54cbdc400 --- /dev/null +++ b/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb @@ -0,0 +1,110 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require_relative "helper" +require_relative "../storage_control_create_rapid_cache" +require_relative "../storage_control_get_rapid_cache" +require_relative "../storage_control_list_rapid_caches" +require_relative "../storage_control_update_rapid_cache" +require_relative "../storage_control_disable_rapid_cache" + +describe "Storage Control Rapid Cache" do + # Rapid Cache Ultra requires a regional bucket with hierarchical namespace + # enabled, located in the same region as the cache zone. + let(:zone) { ENV["STORAGE_CONTROL_RAPID_CACHE_ZONE"] || "us-east1-b" } + let(:bucket_name) { @bucket_name } + # Like the Anywhere Cache tests, these tests are not run in CI because a + # bucket cannot be deleted until its Rapid Cache has been fully removed, + # which can take more than 30 minutes. Set + # STORAGE_CONTROL_RUN_RAPID_CACHE_TESTS to run them. + let(:run_tests) { ENV["STORAGE_CONTROL_RUN_RAPID_CACHE_TESTS"] } + + before :all do + next unless run_tests + + @bucket_name = random_bucket_name + create_bucket_helper @bucket_name, + location: zone_region(zone), + uniform_bucket_level_access: true, + hierarchical_namespace: { enabled: true } + end + + after :all do + # Best-effort cleanup. The bucket cannot be deleted while it still has a + # Rapid Cache, so it may be left for the stale bucket cleanup job. + delete_bucket_with_rapid_cache_helper @bucket_name if @bucket_name + end + + it "handles Rapid Cache lifecycle in sequence" do + skip "Set STORAGE_CONTROL_RUN_RAPID_CACHE_TESTS to run Rapid Cache tests" unless run_tests + + cache_id = nil + out_disable = nil + begin + out_create, _err = capture_io do + create_rapid_cache bucket_name: bucket_name, zone: zone + end + prefix = "Created Rapid Cache: " + assert_includes out_create, prefix + cache_name = out_create.split(prefix, 2).last.split.first + # The Rapid Cache ID is assigned by the server. + cache_id = cache_name[%r{/rapidCaches/([^/]+)\z}, 1] + refute_nil cache_id + + out_get, _err = capture_io do + get_rapid_cache bucket_name: bucket_name, cache_id: cache_id + end + assert_includes out_get, cache_name + assert_includes out_get, "Zone: #{zone}" + + out_list, _err = capture_io do + list_rapid_caches bucket_name: bucket_name + end + assert_includes out_list, cache_name + + out_update, _err = capture_io do + update_rapid_cache bucket_name: bucket_name, cache_id: cache_id, ttl_seconds: 172_800 + end + assert_includes out_update, "Updated Rapid Cache: #{cache_name}" + assert_includes out_update, "TTL: 172800 seconds" + ensure + # Always disable the cache so that it does not outlive the test. If the + # cache ID is unknown (e.g. create failed after the cache was created), + # disable every cache in the bucket. Do not let a disable failure hide an + # earlier failure. + (cache_id ? [cache_id] : rapid_cache_ids_helper(bucket_name)).each do |id| + out, _err = capture_io do + disable_rapid_cache bucket_name: bucket_name, cache_id: id + end + out_disable = out if id == cache_id + rescue StandardError => e + puts "\nFailed to disable Rapid Cache #{id}: #{e.message}" + end + end + refute_nil out_disable, "disable_rapid_cache failed" + assert_includes out_disable, "Disabling Rapid Cache: #{cache_name}" + assert_includes out_disable, "Operation: " + + # The cache moves to the "disabled" state shortly after the request. + out_state = "" + 12.times do + out_state, _err = capture_io do + get_rapid_cache bucket_name: bucket_name, cache_id: cache_id + end + break if out_state.include? "State: disabled" + sleep 10 + end + assert_includes out_state, "State: disabled" + end +end diff --git a/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb new file mode 100644 index 000000000000..e7834d6ee120 --- /dev/null +++ b/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb @@ -0,0 +1,57 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_control_create_rapid_cache] +require "google/cloud/storage/control" + +# Creates a Rapid Cache for a bucket in the given zone. +# +# @param bucket_name [String] The name of the bucket. Rapid Cache Ultra +# requires a bucket with hierarchical namespace enabled. +# @param zone [String] The zone in which to create the Rapid Cache. The zone +# must be in the same region as the bucket (e.g., "us-east1-b"). +# +# @example +# create_rapid_cache bucket_name: "your-unique-bucket-name", zone: "us-east1-b" +# +def create_rapid_cache bucket_name:, zone: + # Create a client object. The client can be reused for multiple calls. + storage_control_client = Google::Cloud::Storage::Control.storage_control + # Set project to "_" to signify global bucket + parent = storage_control_client.bucket_path project: "_", bucket: bucket_name + + # The Rapid Cache ID is assigned by the server. + rapid_cache = Google::Cloud::Storage::Control::V2::RapidCache.new( + zone: zone, + cache_type: "rapid-cache-ultra" + ) + request = Google::Cloud::Storage::Control::V2::CreateRapidCacheRequest.new( + parent: parent, + rapid_cache: rapid_cache + ) + + # Creating a Rapid Cache is a long-running operation. Poll the operation + # until it completes. + operation = storage_control_client.create_rapid_cache request + until operation.done? + sleep 1 + operation = storage_control_client.operations_client.get_operation name: operation.name + end + raise operation.error.message if operation.error? + + puts "Created Rapid Cache: #{operation.response.name}" +end +# [END storage_control_create_rapid_cache] + +create_rapid_cache bucket_name: ARGV.shift, zone: ARGV.shift if $PROGRAM_NAME == __FILE__ diff --git a/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb new file mode 100644 index 000000000000..b1e6a89a99d1 --- /dev/null +++ b/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb @@ -0,0 +1,48 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_control_disable_rapid_cache] +require "google/cloud/storage/control" + +# Disables a Rapid Cache. +# +# @param bucket_name [String] The name of the bucket. +# @param cache_id [String] The ID of the Rapid Cache. +# +# @example +# disable_rapid_cache bucket_name: "your-unique-bucket-name", cache_id: "your-rapid-cache-id" +# +def disable_rapid_cache bucket_name:, cache_id: + # Create a client object. The client can be reused for multiple calls. + storage_control_client = Google::Cloud::Storage::Control.storage_control + # Set project to "_" to signify global bucket + name = storage_control_client.rapid_cache_path project: "_", + bucket: bucket_name, + rapid_cache: cache_id + + request = Google::Cloud::Storage::Control::V2::DisableRapidCacheRequest.new name: name + + # Disabling a Rapid Cache starts a long-running operation. The cache moves + # to the "disabled" state within seconds, but the operation only completes + # once the cache has been fully removed, which can take more than 30 + # minutes. This sample does not wait for the operation to complete; use + # get_rapid_cache to check the cache state. + operation = storage_control_client.disable_rapid_cache request + + puts "Disabling Rapid Cache: #{name}" + puts "Operation: #{operation.name}" +end +# [END storage_control_disable_rapid_cache] + +disable_rapid_cache bucket_name: ARGV.shift, cache_id: ARGV.shift if $PROGRAM_NAME == __FILE__ diff --git a/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb new file mode 100644 index 000000000000..594ce837174d --- /dev/null +++ b/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb @@ -0,0 +1,43 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_control_get_rapid_cache] +require "google/cloud/storage/control" + +# Retrieves the metadata of a Rapid Cache. +# +# @param bucket_name [String] The name of the bucket. +# @param cache_id [String] The ID of the Rapid Cache. +# +# @example +# get_rapid_cache bucket_name: "your-unique-bucket-name", cache_id: "your-rapid-cache-id" +# +def get_rapid_cache bucket_name:, cache_id: + # Create a client object. The client can be reused for multiple calls. + storage_control_client = Google::Cloud::Storage::Control.storage_control + # Set project to "_" to signify global bucket + name = storage_control_client.rapid_cache_path project: "_", + bucket: bucket_name, + rapid_cache: cache_id + + request = Google::Cloud::Storage::Control::V2::GetRapidCacheRequest.new name: name + rapid_cache = storage_control_client.get_rapid_cache request + + puts "Got Rapid Cache: #{rapid_cache.name}" + puts "Zone: #{rapid_cache.zone}" + puts "State: #{rapid_cache.state}" +end +# [END storage_control_get_rapid_cache] + +get_rapid_cache bucket_name: ARGV.shift, cache_id: ARGV.shift if $PROGRAM_NAME == __FILE__ diff --git a/google-cloud-storage-control/samples/storage_control_list_rapid_caches.rb b/google-cloud-storage-control/samples/storage_control_list_rapid_caches.rb new file mode 100644 index 000000000000..015e3cd98626 --- /dev/null +++ b/google-cloud-storage-control/samples/storage_control_list_rapid_caches.rb @@ -0,0 +1,43 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_control_list_rapid_caches] +require "google/cloud/storage/control" + +# Lists the Rapid Caches of a bucket. +# +# @param bucket_name [String] The name of the bucket. +# +# @example +# list_rapid_caches bucket_name: "your-unique-bucket-name" +# +def list_rapid_caches bucket_name: + # Create a client object. The client can be reused for multiple calls. + storage_control_client = Google::Cloud::Storage::Control.storage_control + # Set project to "_" to signify global bucket + parent = storage_control_client.bucket_path project: "_", bucket: bucket_name + + request = Google::Cloud::Storage::Control::V2::ListRapidCachesRequest.new parent: parent + + # The returned enumerable fetches additional pages as needed. + rapid_caches = storage_control_client.list_rapid_caches request + rapid_caches.each do |rapid_cache| + puts rapid_cache.name + end + + puts "Listed Rapid Caches in bucket #{bucket_name}" +end +# [END storage_control_list_rapid_caches] + +list_rapid_caches bucket_name: ARGV.shift if $PROGRAM_NAME == __FILE__ diff --git a/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb new file mode 100644 index 000000000000..ad1337d6387a --- /dev/null +++ b/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb @@ -0,0 +1,66 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_control_update_rapid_cache] +require "google/cloud/storage/control" + +# Updates the time to live (TTL) of a Rapid Cache. +# +# @param bucket_name [String] The name of the bucket. +# @param cache_id [String] The ID of the Rapid Cache. +# @param ttl_seconds [Integer] The new TTL for cache entries, in seconds. The +# TTL must be between 1 hour and 7 days. +# +# @example +# update_rapid_cache bucket_name: "your-unique-bucket-name", +# cache_id: "your-rapid-cache-id", +# ttl_seconds: 172_800 # 2 days +# +def update_rapid_cache bucket_name:, cache_id:, ttl_seconds: + # Create a client object. The client can be reused for multiple calls. + storage_control_client = Google::Cloud::Storage::Control.storage_control + # Set project to "_" to signify global bucket + name = storage_control_client.rapid_cache_path project: "_", + bucket: bucket_name, + rapid_cache: cache_id + + rapid_cache = Google::Cloud::Storage::Control::V2::RapidCache.new( + name: name, + ttl: Google::Protobuf::Duration.new(seconds: ttl_seconds) + ) + # Only the fields listed in the update mask are changed. + update_mask = Google::Protobuf::FieldMask.new paths: ["ttl"] + request = Google::Cloud::Storage::Control::V2::UpdateRapidCacheRequest.new( + rapid_cache: rapid_cache, + update_mask: update_mask + ) + + # Updating a Rapid Cache is a long-running operation. Poll the operation + # until it completes. + operation = storage_control_client.update_rapid_cache request + until operation.done? + sleep 1 + operation = storage_control_client.operations_client.get_operation name: operation.name + end + raise operation.error.message if operation.error? + + result = operation.response + puts "Updated Rapid Cache: #{result.name}" + puts "TTL: #{result.ttl.seconds} seconds" +end +# [END storage_control_update_rapid_cache] + +if $PROGRAM_NAME == __FILE__ + update_rapid_cache bucket_name: ARGV.shift, cache_id: ARGV.shift, ttl_seconds: Integer(ARGV.shift) +end From ca80ffe398d5724c454c78714b784766d95cf455 Mon Sep 17 00:00:00 2001 From: Sneha Sahu Date: Mon, 2 Nov 2026 18:21:55 +0000 Subject: [PATCH 2/2] docs(storage-control): align rapid cache samples with reference integration test Set the explicit cache name (ID = zone), cache_type rapid-cache-ultra and ttl 24h on create; wait for the disable LRO; tests assert running state, cache type, list membership and the updated ttl, and bound the disable wait. Aligns with googleapis/google-cloud-java#14529. b/482946642 [Generated-by: AI] --- .../samples/acceptance/helper.rb | 14 ----- .../storage_control_rapid_cache_test.rb | 63 ++++++++++--------- .../storage_control_create_rapid_cache.rb | 15 ++++- .../storage_control_disable_rapid_cache.rb | 30 ++++++--- .../storage_control_get_rapid_cache.rb | 6 +- .../storage_control_update_rapid_cache.rb | 5 +- 6 files changed, 73 insertions(+), 60 deletions(-) diff --git a/google-cloud-storage-control/samples/acceptance/helper.rb b/google-cloud-storage-control/samples/acceptance/helper.rb index f7713e28a63a..d516b63831b5 100644 --- a/google-cloud-storage-control/samples/acceptance/helper.rb +++ b/google-cloud-storage-control/samples/acceptance/helper.rb @@ -46,20 +46,6 @@ def zone_region zone zone.sub(/-[a-z]\z/, "") end -# Returns the IDs of the Rapid Caches of a bucket, or an empty array if they -# cannot be listed. -# -# @param bucket_name [String] The name of the Google Cloud Storage bucket. -def rapid_cache_ids_helper bucket_name - storage_control_client = Google::Cloud::Storage::Control.storage_control - # Set project to "_" to signify global bucket - parent = "projects/_/buckets/#{bucket_name}" - storage_control_client.list_rapid_caches(parent: parent).map { |cache| cache.name.split("/").last } -rescue StandardError => e - puts "\nFailed to list Rapid Caches in bucket #{bucket_name}: #{e.message}" - [] -end - # Best-effort deletion of a bucket that had a Rapid Cache. # # A bucket cannot be deleted until its Rapid Cache has been fully removed, diff --git a/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb b/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb index bde54cbdc400..adeaa9dfdcf2 100644 --- a/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb +++ b/google-cloud-storage-control/samples/acceptance/storage_control_rapid_cache_test.rb @@ -24,6 +24,12 @@ # enabled, located in the same region as the cache zone. let(:zone) { ENV["STORAGE_CONTROL_RAPID_CACHE_ZONE"] || "us-east1-b" } let(:bucket_name) { @bucket_name } + # The Rapid Cache ID must be the same as the zone. + let(:cache_id) { zone } + let(:cache_name) { "projects/_/buckets/#{bucket_name}/rapidCaches/#{cache_id}" } + # The disable operation only completes once the cache has been fully + # removed, which can take more than an hour, so bound the wait. + let(:disable_timeout) { 600 } # Like the Anywhere Cache tests, these tests are not run in CI because a # bucket cannot be deleted until its Rapid Cache has been fully removed, # which can take more than 30 minutes. Set @@ -38,6 +44,8 @@ location: zone_region(zone), uniform_bucket_level_access: true, hierarchical_namespace: { enabled: true } + # Wait for the bucket metadata to propagate to the Storage Control API. + sleep 20 end after :all do @@ -49,29 +57,27 @@ it "handles Rapid Cache lifecycle in sequence" do skip "Set STORAGE_CONTROL_RUN_RAPID_CACHE_TESTS to run Rapid Cache tests" unless run_tests - cache_id = nil out_disable = nil begin out_create, _err = capture_io do create_rapid_cache bucket_name: bucket_name, zone: zone end - prefix = "Created Rapid Cache: " - assert_includes out_create, prefix - cache_name = out_create.split(prefix, 2).last.split.first - # The Rapid Cache ID is assigned by the server. - cache_id = cache_name[%r{/rapidCaches/([^/]+)\z}, 1] - refute_nil cache_id + assert_includes out_create, "Created Rapid Cache: #{cache_name}" + assert_includes out_create, "Cache type: rapid-cache-ultra" + assert_includes out_create, "TTL: 86400 seconds" out_get, _err = capture_io do get_rapid_cache bucket_name: bucket_name, cache_id: cache_id end - assert_includes out_get, cache_name + assert_includes out_get, "Got Rapid Cache: #{cache_name}" assert_includes out_get, "Zone: #{zone}" + assert_includes out_get, "Cache type: rapid-cache-ultra" + assert_includes out_get, "State: running" out_list, _err = capture_io do list_rapid_caches bucket_name: bucket_name end - assert_includes out_list, cache_name + assert_includes out_list.lines.map(&:chomp), cache_name out_update, _err = capture_io do update_rapid_cache bucket_name: bucket_name, cache_id: cache_id, ttl_seconds: 172_800 @@ -79,32 +85,31 @@ assert_includes out_update, "Updated Rapid Cache: #{cache_name}" assert_includes out_update, "TTL: 172800 seconds" ensure - # Always disable the cache so that it does not outlive the test. If the - # cache ID is unknown (e.g. create failed after the cache was created), - # disable every cache in the bucket. Do not let a disable failure hide an - # earlier failure. - (cache_id ? [cache_id] : rapid_cache_ids_helper(bucket_name)).each do |id| - out, _err = capture_io do - disable_rapid_cache bucket_name: bucket_name, cache_id: id + # Always disable the cache so that it does not outlive the test. Do not + # let a disable failure or timeout hide an earlier failure. + begin + out_disable, _err = capture_io do + disable_rapid_cache bucket_name: bucket_name, cache_id: cache_id, timeout: disable_timeout end - out_disable = out if id == cache_id rescue StandardError => e - puts "\nFailed to disable Rapid Cache #{id}: #{e.message}" + puts "\nDisable of Rapid Cache #{cache_name} did not complete: #{e.message}" end end - refute_nil out_disable, "disable_rapid_cache failed" - assert_includes out_disable, "Disabling Rapid Cache: #{cache_name}" - assert_includes out_disable, "Operation: " - # The cache moves to the "disabled" state shortly after the request. - out_state = "" - 12.times do - out_state, _err = capture_io do - get_rapid_cache bucket_name: bucket_name, cache_id: cache_id + if out_disable + assert_includes out_disable, "Disabled Rapid Cache: #{cache_name}" + else + # The disable operation did not complete in time. The cache moves to the + # "disabled" state shortly after the request, so check the state instead. + out_state = "" + 12.times do + out_state, _err = capture_io do + get_rapid_cache bucket_name: bucket_name, cache_id: cache_id + end + break if out_state.include? "State: disabled" + sleep 10 end - break if out_state.include? "State: disabled" - sleep 10 + assert_includes out_state, "State: disabled" end - assert_includes out_state, "State: disabled" end end diff --git a/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb index e7834d6ee120..036341c90f81 100644 --- a/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb +++ b/google-cloud-storage-control/samples/storage_control_create_rapid_cache.rb @@ -30,11 +30,17 @@ def create_rapid_cache bucket_name:, zone: storage_control_client = Google::Cloud::Storage::Control.storage_control # Set project to "_" to signify global bucket parent = storage_control_client.bucket_path project: "_", bucket: bucket_name + # The Rapid Cache ID must be the same as the zone. + name = storage_control_client.rapid_cache_path project: "_", + bucket: bucket_name, + rapid_cache: zone - # The Rapid Cache ID is assigned by the server. rapid_cache = Google::Cloud::Storage::Control::V2::RapidCache.new( + name: name, zone: zone, - cache_type: "rapid-cache-ultra" + cache_type: "rapid-cache-ultra", + # Keep cache entries for 24 hours. + ttl: Google::Protobuf::Duration.new(seconds: 86_400) ) request = Google::Cloud::Storage::Control::V2::CreateRapidCacheRequest.new( parent: parent, @@ -50,7 +56,10 @@ def create_rapid_cache bucket_name:, zone: end raise operation.error.message if operation.error? - puts "Created Rapid Cache: #{operation.response.name}" + result = operation.response + puts "Created Rapid Cache: #{result.name}" + puts "Cache type: #{result.cache_type}" + puts "TTL: #{result.ttl.seconds} seconds" end # [END storage_control_create_rapid_cache] diff --git a/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb index b1e6a89a99d1..9911140cc21d 100644 --- a/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb +++ b/google-cloud-storage-control/samples/storage_control_disable_rapid_cache.rb @@ -18,12 +18,15 @@ # Disables a Rapid Cache. # # @param bucket_name [String] The name of the bucket. -# @param cache_id [String] The ID of the Rapid Cache. +# @param cache_id [String] The ID of the Rapid Cache, which is the same as its +# zone (e.g., "us-east1-b"). +# @param timeout [Numeric, nil] The maximum number of seconds to wait for the +# operation to complete. If nil, waits until the operation completes. # # @example -# disable_rapid_cache bucket_name: "your-unique-bucket-name", cache_id: "your-rapid-cache-id" +# disable_rapid_cache bucket_name: "your-unique-bucket-name", cache_id: "us-east1-b" # -def disable_rapid_cache bucket_name:, cache_id: +def disable_rapid_cache bucket_name:, cache_id:, timeout: nil # Create a client object. The client can be reused for multiple calls. storage_control_client = Google::Cloud::Storage::Control.storage_control # Set project to "_" to signify global bucket @@ -33,15 +36,22 @@ def disable_rapid_cache bucket_name:, cache_id: request = Google::Cloud::Storage::Control::V2::DisableRapidCacheRequest.new name: name - # Disabling a Rapid Cache starts a long-running operation. The cache moves - # to the "disabled" state within seconds, but the operation only completes - # once the cache has been fully removed, which can take more than 30 - # minutes. This sample does not wait for the operation to complete; use - # get_rapid_cache to check the cache state. + # Disabling a Rapid Cache is a long-running operation. Poll the operation + # until it completes. operation = storage_control_client.disable_rapid_cache request + deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout if timeout + until operation.done? + if deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) > deadline + raise "Timed out waiting for operation #{operation.name}" + end + sleep 5 + operation = storage_control_client.operations_client.get_operation name: operation.name + end + raise operation.error.message if operation.error? - puts "Disabling Rapid Cache: #{name}" - puts "Operation: #{operation.name}" + result = operation.response + puts "Disabled Rapid Cache: #{result.name}" + puts "State: #{result.state}" end # [END storage_control_disable_rapid_cache] diff --git a/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb index 594ce837174d..df6a890dced1 100644 --- a/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb +++ b/google-cloud-storage-control/samples/storage_control_get_rapid_cache.rb @@ -18,10 +18,11 @@ # Retrieves the metadata of a Rapid Cache. # # @param bucket_name [String] The name of the bucket. -# @param cache_id [String] The ID of the Rapid Cache. +# @param cache_id [String] The ID of the Rapid Cache, which is the same as its +# zone (e.g., "us-east1-b"). # # @example -# get_rapid_cache bucket_name: "your-unique-bucket-name", cache_id: "your-rapid-cache-id" +# get_rapid_cache bucket_name: "your-unique-bucket-name", cache_id: "us-east1-b" # def get_rapid_cache bucket_name:, cache_id: # Create a client object. The client can be reused for multiple calls. @@ -36,6 +37,7 @@ def get_rapid_cache bucket_name:, cache_id: puts "Got Rapid Cache: #{rapid_cache.name}" puts "Zone: #{rapid_cache.zone}" + puts "Cache type: #{rapid_cache.cache_type}" puts "State: #{rapid_cache.state}" end # [END storage_control_get_rapid_cache] diff --git a/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb b/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb index ad1337d6387a..6350198a5241 100644 --- a/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb +++ b/google-cloud-storage-control/samples/storage_control_update_rapid_cache.rb @@ -18,13 +18,14 @@ # Updates the time to live (TTL) of a Rapid Cache. # # @param bucket_name [String] The name of the bucket. -# @param cache_id [String] The ID of the Rapid Cache. +# @param cache_id [String] The ID of the Rapid Cache, which is the same as its +# zone (e.g., "us-east1-b"). # @param ttl_seconds [Integer] The new TTL for cache entries, in seconds. The # TTL must be between 1 hour and 7 days. # # @example # update_rapid_cache bucket_name: "your-unique-bucket-name", -# cache_id: "your-rapid-cache-id", +# cache_id: "us-east1-b", # ttl_seconds: 172_800 # 2 days # def update_rapid_cache bucket_name:, cache_id:, ttl_seconds: