Skip to content
11 changes: 10 additions & 1 deletion google-cloud-storage/lib/google/cloud/storage/bucket/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ class List < DelegateClass(::Array)
# that match the request and this value should be passed to
# the next {Google::Cloud::Storage::Project#buckets} to continue.
attr_accessor :token
##
# Provides a list of bucket names that are unreachable.
#
# This is only populated when `return_partial_success` is set to `true`
# in the call to {Google::Cloud::Storage::Project#buckets}.
#
# @return [Array<String>]
attr_reader :unreachable

##
# @private Create a new Bucket::List with an array of values.
Expand Down Expand Up @@ -147,7 +155,7 @@ def all request_limit: nil, &block
# @private New Bucket::List from a Google API Client
# Google::Apis::StorageV1::Buckets object.
def self.from_gapi gapi_list, service, prefix = nil, max = nil,
user_project: nil, soft_deleted: nil
user_project: nil, soft_deleted: nil, return_partial_success: nil
buckets = new(Array(gapi_list.items).map do |gapi_object|
Bucket.from_gapi gapi_object, service, user_project: user_project
end)
Expand All @@ -157,6 +165,7 @@ def self.from_gapi gapi_list, service, prefix = nil, max = nil,
buckets.instance_variable_set :@max, max
buckets.instance_variable_set :@user_project, user_project
buckets.instance_variable_set :@soft_deleted, soft_deleted
buckets.instance_variable_set :@unreachable, Array(gapi_list.unreachable) if return_partial_success
buckets
end

Expand Down
20 changes: 17 additions & 3 deletions google-cloud-storage/lib/google/cloud/storage/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ def add_custom_header header_name, header_value
# bucket instances and their files.
#
# See also {Bucket#requester_pays=} and {Bucket#requester_pays}.
# @param [Boolean] return_partial_success
# If true, the response will contain a list of unreachable buckets.
# If false, ListBuckets will throw an error if there are any unreachable buckets.
#
# @return [Array<Google::Cloud::Storage::Bucket>] (See
# {Google::Cloud::Storage::Bucket::List})
Expand Down Expand Up @@ -201,11 +204,22 @@ def add_custom_header header_name, header_value
# soft_deleted_buckets.each do |bucket|
# puts bucket.name
# end
def buckets prefix: nil, token: nil, max: nil, user_project: nil, soft_deleted: nil
# @example Retrieve list of unreachable buckets
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# buckets = storage.buckets return_partial_success: true
# buckets.unreachable.each do |unreachable_bucket_name|
# puts unreachable_bucket_name
# end
#
def buckets prefix: nil, token: nil, max: nil, user_project: nil, soft_deleted: nil, return_partial_success: nil
gapi = service.list_buckets \
prefix: prefix, token: token, max: max, user_project: user_project, soft_deleted: soft_deleted
prefix: prefix, token: token, max: max, user_project: user_project, soft_deleted: soft_deleted, return_partial_success: return_partial_success
Bucket::List.from_gapi \
gapi, service, prefix, max, user_project: user_project, soft_deleted: soft_deleted
gapi, service, prefix, max, user_project: user_project, soft_deleted: soft_deleted, return_partial_success: return_partial_success

end
alias find_buckets buckets

Expand Down
6 changes: 4 additions & 2 deletions google-cloud-storage/lib/google/cloud/storage/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,14 @@ def project_service_account

##
# Retrieves a list of buckets for the given project.
def list_buckets prefix: nil, token: nil, max: nil, user_project: nil, soft_deleted: nil, options: {}
def list_buckets prefix: nil, token: nil, max: nil, user_project: nil, soft_deleted: nil, return_partial_success: nil, options: {}
execute do
service.list_buckets \
@project, prefix: prefix, page_token: token, max_results: max,
user_project: user_project(user_project),
soft_deleted: soft_deleted, options: options
soft_deleted: soft_deleted,
return_partial_success: return_partial_success,
options: options
end
end

Expand Down
19 changes: 19 additions & 0 deletions google-cloud-storage/samples/acceptance/buckets_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
require_relative "../storage_get_retention_policy"
require_relative "../storage_get_uniform_bucket_level_access"
require_relative "../storage_list_buckets"
require_relative "../storage_list_buckets_with_partial_success"
require_relative "../storage_lock_retention_policy"
require_relative "../storage_remove_bucket_label"
require_relative "../storage_remove_cors_configuration"
Expand Down Expand Up @@ -616,4 +617,22 @@
assert_equal "invalid: Source and destination object names must be different.", exception.message
end
end

describe "list buckets with partial success" do
it 'returns a list of bucket names if return_partial_success_flag is true' do
result = list_buckets_with_partial_success return_partial_success_flag: true
assert_kind_of Array, result
assert result.all? { |n| n.is_a? String }, "expected all items to be String"
end

it 'returns nil for unreachable if return_partial_success_flag is false' do
result = list_buckets_with_partial_success return_partial_success_flag: false
assert_nil result
end

it 'returns nil for unreachable if return_partial_success_flag is not passed' do
result = list_buckets_with_partial_success return_partial_success_flag: nil
assert_nil result
end
end
end
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_list_buckets_partial_success]
# Demonstrates listing Google Cloud Storage buckets with support for partial success.
#
# This method initializes a Google Cloud Storage client and requests a list of buckets.
# When `return_partial_success` is true, the API will return available buckets
# and a list of any buckets that were unreachable.
#
# @param return_partial_success_flag [Boolean] Whether to allow partial success from the API.
# - true: returns the available buckets and populates `unreachable` with bucket names if any.
# - false: throws an error if any buckets are unreachable.
def list_buckets_with_partial_success return_partial_success_flag:
require "google/cloud/storage"

storage = Google::Cloud::Storage.new
bucket_list = storage.buckets return_partial_success: return_partial_success_flag

puts "Reachable buckets:"
# limiting the bucket count to be printed to 10 for brevity
bucket_list.take(10).each do |bucket|
puts bucket.name
end

if bucket_list.unreachable
puts "\nUnreachable buckets:"
# limiting the bucket count to be printed to 10 for brevity
bucket_list.unreachable.take(10).each do |unreachable_bucket_name|
puts unreachable_bucket_name
end
end
end
# [END storage_list_buckets_partial_success]

list_buckets_with_partial_success return_partial_success_flag: ARGV.shift if $PROGRAM_NAME == __FILE__
Loading