Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
877b90a
WIP
shubhangi-google Jun 16, 2025
e036c60
wip
shubhangi-google Jun 20, 2025
33a8d55
wip
shubhangi-google Jun 20, 2025
7f5d121
get and list working
shubhangi-google Jun 20, 2025
1dcd5bb
pause_disable_resume_working
shubhangi-google Jun 24, 2025
f99baa4
adding all samples
shubhangi-google Jul 1, 2025
65d5833
adding comments
shubhangi-google Jul 3, 2025
d8498e4
adding comment
shubhangi-google Jul 3, 2025
842bdf2
updates
shubhangi-google Jul 3, 2025
bd0b9cd
Update storage_control_create_anywhere_cache.rb
shubhangi-google Jul 3, 2025
3b9cda3
Update storage_control_disable_anywhere_cache.rb
shubhangi-google Jul 3, 2025
feb8f47
updates
shubhangi-google Jul 3, 2025
af3c7ef
updates
shubhangi-google Jul 4, 2025
e69000b
Update storage_control_create_anywhere_cache.rb
shubhangi-google Jul 4, 2025
808d1e9
Update storage_control_pause_anywhere_cache.rb
shubhangi-google Jul 4, 2025
54f2c14
updating
shubhangi-google Jul 4, 2025
7edf04d
removing reference for V2 library
shubhangi-google Jul 11, 2025
4b4d0a6
fix lint
shubhangi-google Jul 15, 2025
90f3a0b
Update storage_control_update_anywhere_cache.rb
shubhangi-google Aug 1, 2025
93af0da
try refreshing operation status
shubhangi-google Sep 2, 2025
2b29efc
try operation refresh
shubhangi-google Sep 2, 2025
b78928f
try get request
shubhangi-google Sep 2, 2025
b6020d3
fix syntax error
shubhangi-google Sep 3, 2025
fecdaa6
updating test cases with delay
shubhangi-google Sep 7, 2025
78b6dbf
fix lint issue
shubhangi-google Sep 7, 2025
cecd6d9
lint fix
shubhangi-google Sep 7, 2025
6415ed6
wip
shubhangi-google Sep 19, 2025
f319c86
Merge branch 'main' into anywhere_cache_samples_v2_new
shubhangi-google Sep 19, 2025
5f992f0
updated
shubhangi-google Sep 19, 2025
306948c
updated
shubhangi-google Sep 19, 2025
c9d1c6b
update
shubhangi-google Sep 19, 2025
6181f59
try
shubhangi-google Sep 19, 2025
f3e8775
try
shubhangi-google Sep 19, 2025
4209f80
try
shubhangi-google Sep 19, 2025
976451e
try
shubhangi-google Sep 19, 2025
57adc0c
try
shubhangi-google Sep 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions google-cloud-storage-control/samples/acceptance/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
require "minitest/autorun"
require "minitest/focus"
require "minitest/hooks/default"
require "google/cloud/storage/control"

def random_bucket_name
t = Time.now.utc.iso8601.gsub ":", "-"
Expand All @@ -26,9 +27,11 @@ def random_folder_name prefix: "ruby-storage-control-folder-samples-test-"
t = Time.now.utc.iso8601.gsub ":", "-"
"#{prefix}-#{t}-#{SecureRandom.hex 4}".downcase
end
def storage_client
@storage_client ||= Google::Cloud::Storage.new
end

def create_bucket_helper bucket_name, uniform_bucket_level_access: nil, hierarchical_namespace: nil
storage_client = Google::Cloud::Storage.new
retry_resource_exhaustion do
storage_client.create_bucket bucket_name do |b|
b.uniform_bucket_level_access = uniform_bucket_level_access
Expand All @@ -38,7 +41,6 @@ def create_bucket_helper bucket_name, uniform_bucket_level_access: nil, hierarch
end

def delete_bucket_helper bucket_name
storage_client = Google::Cloud::Storage.new
retry_resource_exhaustion do
bucket = storage_client.bucket bucket_name
return unless bucket
Expand All @@ -60,3 +62,33 @@ def retry_resource_exhaustion
end
raise Google::Cloud::ResourceExhaustedError, "Maybe take a break from creating and deleting buckets for a bit"
end

# Waits until all Anywhere Caches for a given bucket are deleted.
#
# This method polls the Storage Control API, listing the Anywhere Caches
# associated with the specified bucket. If caches are found, it waits and
# retries with an exponential backoff strategy until no caches remain.
#
# @param bucket_name [String] The name of the Google Cloud Storage bucket.
# @return [Integer] The final count of Anywhere Caches, which will be 0
# the method completes successfully after all caches are deleted.
def count_anywhere_caches bucket_name
storage_control_client = Google::Cloud::Storage::Control.storage_control

# Set project to "_" to signify global bucket
parent = "projects/_/buckets/#{bucket_name}"
request = Google::Cloud::Storage::Control::V2::ListAnywhereCachesRequest.new(
parent: parent
)
result = storage_control_client.list_anywhere_caches request
min_delay = 180 # 3 minutes
max_delay = 900 # 15 minutes
while result.response.anywhere_caches.count != 0
puts "Cache not deleted yet, Retrying in #{min_delay} seconds."
sleep min_delay
min_delay = [min_delay * 2, max_delay].min # Exponential backoff with a max delay
result = storage_control_client.list_anywhere_caches request
end
Comment on lines +84 to +91

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The polling logic can be made clearer. The variable min_delay is being modified within the loop, which can be confusing as its name implies a fixed minimum. It's better to use a separate variable for the current delay to improve readability.

Additionally, the delay values 180 and 900 are magic numbers. It's a good practice to define them as constants with descriptive names (e.g., INITIAL_DELAY_SECONDS, MAX_DELAY_SECONDS).

  initial_delay = 180 # 3 minutes
  max_delay = 900 # 15 minutes
  current_delay = initial_delay
  while result.response.anywhere_caches.count != 0
    puts "Cache not deleted yet, Retrying in #{current_delay} seconds."
    sleep current_delay
    current_delay = [current_delay * 2, max_delay].min # Exponential backoff with a max delay
    result = storage_control_client.list_anywhere_caches request
  end


result.response.anywhere_caches.count
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Copyright 2025 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_anywhere_cache"
require_relative "../storage_control_list_anywhere_caches"
require_relative "../storage_control_get_anywhere_cache"
require_relative "../storage_control_update_anywhere_cache"
require_relative "../storage_control_pause_anywhere_cache"
require_relative "../storage_control_resume_anywhere_cache"
require_relative "../storage_control_disable_anywhere_cache"

describe "Storage Control Anywhere Cache" do
let(:bucket_name) { random_bucket_name }
let(:zone) { "us-east1-b" }
# Set project to "_" to signify global bucket
let(:anywhere_cache_name) { "projects/_/buckets/#{bucket_name}/anywhereCaches/#{zone}" }

before :all do
create_bucket_helper bucket_name
end

after :all do
count_anywhere_caches bucket_name # Ensure all caches are deleted before deleting bucket
delete_bucket_helper bucket_name
end

it "handles Anywhere cache lifecycle in sequence" do
out_create, _err = capture_io do
create_anywhere_cache bucket_name: bucket_name, zone: zone
end
assert_includes out_create, "AnywhereCache created - #{anywhere_cache_name}"

out_list, _err = capture_io do
list_anywhere_caches bucket_name: bucket_name
end
assert_includes out_list, "AnywhereCache #{anywhere_cache_name} found in list"

out_get, _err = capture_io do
get_anywhere_cache bucket_name: bucket_name, anywhere_cache_id: zone
end
assert_includes out_get, "AnywhereCache #{anywhere_cache_name} fetched"

out_update, _err = capture_io do
update_anywhere_cache bucket_name: bucket_name, anywhere_cache_id: zone
end
assert_includes out_update, "AnywhereCache #{anywhere_cache_name} updated"

out_pause, _err = capture_io do
pause_anywhere_cache bucket_name: bucket_name, anywhere_cache_id: zone
end
assert_includes out_pause, "AnywhereCache #{anywhere_cache_name} paused"

out_resume, _err = capture_io do
resume_anywhere_cache bucket_name: bucket_name, anywhere_cache_id: zone
end
assert_includes out_resume, "AnywhereCache #{anywhere_cache_name} running"

out_disable, _err = capture_io do
disable_anywhere_cache bucket_name: bucket_name, anywhere_cache_id: zone
end
assert_includes out_disable, "AnywhereCache #{anywhere_cache_name} disabled"
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2025 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_anywhere_cache]
require "google/cloud/storage/control"

def create_anywhere_cache bucket_name:, zone:
# The Name of your GCS bucket
# bucket_name = "your-unique-bucket-name"

# Zone where you want to create cache
# zone = "your-zone-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 = "projects/_/buckets/#{bucket_name}"
name = "#{parent}/anywhereCaches/#{zone}"

anywhere_cache = Google::Cloud::Storage::Control::V2::AnywhereCache.new(
name: name,
zone: zone
)
# Create a request.
request = Google::Cloud::Storage::Control::V2::CreateAnywhereCacheRequest.new(
parent: parent,
anywhere_cache: anywhere_cache
)
# The request creates a new cache in the specified zone.
# The cache is created in the specified bucket.
begin
operation = storage_control_client.create_anywhere_cache request
puts "AnywhereCache operation created - #{operation.name}"
get_request = Google::Cloud::Storage::Control::V2::GetAnywhereCacheRequest.new(
name: name
)
result = storage_control_client.get_anywhere_cache get_request
min_delay = 180 # 3 minutes
max_delay = 900 # 15 minutes
while result.state != "running"
puts "Cache not running yet, current state is #{result.state}. Retrying in #{min_delay} seconds."
sleep min_delay
min_delay = [min_delay * 2, max_delay].min # Exponential backoff with a max delay
result = storage_control_client.get_anywhere_cache get_request
end
Comment on lines +49 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This polling logic can be improved for clarity. The variable min_delay is being modified within the loop, which can be confusing as its name implies a fixed minimum. Using a separate variable for the current delay makes the code easier to understand.

Also, the delay values 180 and 900 are magic numbers. They should be defined as constants with descriptive names to improve maintainability.

    initial_delay = 180 # 3 minutes
    max_delay = 900 # 15 minutes
    current_delay = initial_delay
    while result.state != "running"
      puts "Cache not running yet, current state is #{result.state}. Retrying in #{current_delay} seconds."
      sleep current_delay
      current_delay = [current_delay * 2, max_delay].min # Exponential backoff with a max delay
      result = storage_control_client.get_anywhere_cache get_request
    end

puts "AnywhereCache created - #{result.name}"
Comment on lines +43 to +57

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This sample uses a manual polling loop with get_anywhere_cache to wait for the create_anywhere_cache operation to complete. The client library provides a more robust and idiomatic way to handle long-running operations (LROs) using operation.wait_until_done!. This simplifies the code, makes it less error-prone, and uses the library's built-in exponential backoff mechanism.

    operation = storage_control_client.create_anywhere_cache request
    puts "AnywhereCache operation created - #{operation.name}"
    operation.wait_until_done!
    if operation.error?
      puts "Error creating AnywhereCache: #{operation.error.message}"
    else
      result = operation.response
      puts "AnywhereCache created - #{result.name}"
    end

rescue Google::Cloud::Error => e
puts "Error creating AnywhereCache: #{e.message}"
end
end
# [END storage_control_create_anywhere_cache]
create_anywhere_cache bucket_name: ARGV.shift, zone: ARGV.shift if $PROGRAM_NAME == __FILE__
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2025 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_anywhere_cache]
require "google/cloud/storage/control"

def disable_anywhere_cache bucket_name:, anywhere_cache_id:
# The Name of your GCS bucket
# bucket_name = "your-unique-bucket-name"

# A value that, along with the bucket's name, uniquely identifies the cache
# anywhere_cache_id = "us-east1-b"

# 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 = "projects/_/buckets/#{bucket_name}"
name = "#{parent}/anywhereCaches/#{anywhere_cache_id}"

# Create a request.
request = Google::Cloud::Storage::Control::V2::DisableAnywhereCacheRequest.new(
name: name
)
# The request disables the cache, but does not delete it.
# The cache can be re-enabled later.
begin
result = storage_control_client.disable_anywhere_cache request
puts "AnywhereCache #{result.name} #{result.state}"
rescue Google::Cloud::Error => e
puts "Error disabling AnywhereCache: #{e.message}"
end
end
# [END storage_control_disable_anywhere_cache]
disable_anywhere_cache bucket_name: ARGV.shift, anywhere_cache_id: ARGV.shift if $PROGRAM_NAME == __FILE__
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2025 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_anywhere_cache]
require "google/cloud/storage/control"

def get_anywhere_cache bucket_name:, anywhere_cache_id:
# The Name of your GCS bucket
# bucket_name = "your-unique-bucket-name"

# A value that, along with the bucket's name, uniquely identifies the cache
# anywhere_cache_id = "us-east1-b"

# 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 = "projects/_/buckets/#{bucket_name}"
name = "#{parent}/anywhereCaches/#{anywhere_cache_id}"

# Create a request.
request = Google::Cloud::Storage::Control::V2::GetAnywhereCacheRequest.new(
name: name
)
# The request retrieves the cache in the specified bucket.
# The cache is identified by the specified ID.
# The cache is in the specified bucket.

begin
result = storage_control_client.get_anywhere_cache request
puts "AnywhereCache #{result.name} fetched"
rescue Google::Cloud::Error => e
puts "Error fetching AnywhereCache: #{e.message}"
end
end
# [END storage_control_get_anywhere_cache]
get_anywhere_cache bucket_name: ARGV.shift, anywhere_cache_id: ARGV.shift if $PROGRAM_NAME == __FILE__
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 2025 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_anywhere_caches]
require "google/cloud/storage/control"

def list_anywhere_caches bucket_name:
# The Name of your GCS bucket
# bucket_name = "your-unique-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 = "projects/_/buckets/#{bucket_name}"

# Create a request.
request = Google::Cloud::Storage::Control::V2::ListAnywhereCachesRequest.new(
parent: parent
)
# The request lists all caches in the specified bucket.
# The caches are identified by the specified bucket name.
begin
result = storage_control_client.list_anywhere_caches request
result.response.anywhere_caches.each do |item|
puts "AnywhereCache #{item.name} found in list"
end
Comment on lines +35 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation result.response.anywhere_caches.each only iterates over the first page of results. To correctly handle pagination and process all caches, you should iterate directly over the Gapic::PagedEnumerable object that list_anywhere_caches returns.

    result.each do |item|
      puts "AnywhereCache #{item.name} found in list"
    end

rescue Google::Cloud::Error => e
puts "Error listing AnywhereCaches: #{e.message}"
end
end
# [END storage_control_list_anywhere_caches]
list_anywhere_caches bucket_name: ARGV.shift if $PROGRAM_NAME == __FILE__
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright 2025 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_pause_anywhere_cache]
require "google/cloud/storage/control"

def pause_anywhere_cache bucket_name:, anywhere_cache_id:
# The Name of your GCS bucket
# bucket_name = "your-unique-bucket-name"

# A value that, along with the bucket's name, uniquely identifies the cache
# anywhere_cache_id = "us-east1-b"

# 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 = "projects/_/buckets/#{bucket_name}"
name = "#{parent}/anywhereCaches/#{anywhere_cache_id}"

# Create a request.
request = Google::Cloud::Storage::Control::V2::PauseAnywhereCacheRequest.new(
name: name
)
# The request pauses the cache, but does not delete it.
# The cache can be resumed later.
# The cache is paused in the specified bucket.
begin
result = storage_control_client.pause_anywhere_cache request
puts "AnywhereCache #{result.name} #{result.state}"
rescue Google::Cloud::Error => e
puts "Error pausing AnywhereCache: #{e.message}"
end
end
# [END storage_control_pause_anywhere_cache]
pause_anywhere_cache bucket_name: ARGV.shift, anywhere_cache_id: ARGV.shift if $PROGRAM_NAME == __FILE__
Loading