google-cloud-storage 1.45.0 → 1.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -335,7 +335,7 @@ module Google
335
335
  if_metageneration_match: if_metageneration_match,
336
336
  if_metageneration_not_match: if_metageneration_not_match
337
337
  end
338
- alias authenticatedRead! auth!
338
+ alias authenticatedRead! auth! # rubocop:disable Naming/MethodName
339
339
  alias auth_read! auth!
340
340
  alias authenticated! auth!
341
341
  alias authenticated_read! auth!
@@ -382,7 +382,7 @@ module Google
382
382
  if_metageneration_match: if_metageneration_match,
383
383
  if_metageneration_not_match: if_metageneration_not_match
384
384
  end
385
- alias bucketOwnerFullControl! owner_full!
385
+ alias bucketOwnerFullControl! owner_full! # rubocop:disable Naming/MethodName
386
386
 
387
387
  ##
388
388
  # Convenience method to apply the `bucketOwnerRead` predefined ACL
@@ -426,7 +426,7 @@ module Google
426
426
  if_metageneration_match: if_metageneration_match,
427
427
  if_metageneration_not_match: if_metageneration_not_match
428
428
  end
429
- alias bucketOwnerRead! owner_read!
429
+ alias bucketOwnerRead! owner_read! # rubocop:disable Naming/MethodName
430
430
 
431
431
  ##
432
432
  # Convenience method to apply the `private` predefined ACL
@@ -513,7 +513,7 @@ module Google
513
513
  if_metageneration_match: if_metageneration_match,
514
514
  if_metageneration_not_match: if_metageneration_not_match
515
515
  end
516
- alias projectPrivate! project_private!
516
+ alias projectPrivate! project_private! # rubocop:disable Naming/MethodName
517
517
 
518
518
  ##
519
519
  # Convenience method to apply the `publicRead` predefined ACL
@@ -557,7 +557,7 @@ module Google
557
557
  if_metageneration_match: if_metageneration_match,
558
558
  if_metageneration_not_match: if_metageneration_not_match
559
559
  end
560
- alias publicRead! public!
560
+ alias publicRead! public! # rubocop:disable Naming/MethodName
561
561
  alias public_read! public!
562
562
 
563
563
  protected
@@ -83,10 +83,12 @@ module Google
83
83
  token: @token,
84
84
  max: @max,
85
85
  versions: @versions,
86
- user_project: @user_project
86
+ user_project: @user_project,
87
+ match_glob: @match_glob
87
88
  File::List.from_gapi gapi, @service, @bucket, @prefix,
88
89
  @delimiter, @max, @versions,
89
- user_project: @user_project
90
+ user_project: @user_project,
91
+ match_glob: @match_glob
90
92
  end
91
93
 
92
94
  ##
@@ -163,7 +165,9 @@ module Google
163
165
  # Google::Apis::StorageV1::Objects object.
164
166
  def self.from_gapi gapi_list, service, bucket = nil, prefix = nil,
165
167
  delimiter = nil, max = nil, versions = nil,
166
- user_project: nil
168
+ user_project: nil, match_glob: nil,
169
+ include_folders_as_prefixes: nil,
170
+ soft_deleted: nil
167
171
  files = new(Array(gapi_list.items).map do |gapi_object|
168
172
  File.from_gapi gapi_object, service, user_project: user_project
169
173
  end)
@@ -176,6 +180,9 @@ module Google
176
180
  files.instance_variable_set :@max, max
177
181
  files.instance_variable_set :@versions, versions
178
182
  files.instance_variable_set :@user_project, user_project
183
+ files.instance_variable_set :@match_glob, match_glob
184
+ files.instance_variable_set :@include_folders_as_prefixes, include_folders_as_prefixes
185
+ files.instance_variable_set :@soft_deleted, soft_deleted
179
186
  files
180
187
  end
181
188
 
@@ -60,7 +60,8 @@ module Google
60
60
  ##
61
61
  # The external url to the file.
62
62
  def ext_url
63
- "#{GOOGLEAPIS_URL}#{ext_path}"
63
+ root_url = @service.service.root_url.chomp "/"
64
+ "#{root_url}#{ext_path}"
64
65
  end
65
66
 
66
67
  def apply_option_defaults options
@@ -91,7 +92,7 @@ module Google
91
92
 
92
93
  def error_msg attr_name
93
94
  "Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
94
- "see https://cloud.google.com/iam/docs/service-accounts"
95
+ "see https://cloud.google.com/iam/docs/service-accounts"
95
96
  end
96
97
 
97
98
  def post_object options
@@ -144,8 +145,8 @@ module Google
144
145
 
145
146
  def generate_signed_url issuer, signed_string, expires, query
146
147
  url = "#{ext_url}?GoogleAccessId=#{url_escape issuer}" \
147
- "&Expires=#{expires}" \
148
- "&Signature=#{url_escape signed_string}"
148
+ "&Expires=#{expires}" \
149
+ "&Signature=#{url_escape signed_string}"
149
150
 
150
151
  query&.each do |name, value|
151
152
  url << "&#{url_escape name}=#{url_escape value}"
@@ -131,7 +131,7 @@ module Google
131
131
  # methods below are public visibility only for unit testing
132
132
  # rubocop:disable Style/StringLiterals
133
133
  def escape_characters str
134
- str.split("").map do |s|
134
+ str.chars.map do |s|
135
135
  if s.ascii_only?
136
136
  case s
137
137
  when "\\"
@@ -207,7 +207,7 @@ module Google
207
207
 
208
208
  def error_msg attr_name
209
209
  "Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
210
- "see https://cloud.google.com/iam/docs/service-accounts"
210
+ "see https://cloud.google.com/iam/docs/service-accounts"
211
211
  end
212
212
 
213
213
  def service_account_signer signer
@@ -243,7 +243,7 @@ module Google
243
243
  headers_arr = canonical_headers.map do |k, v|
244
244
  [k.downcase, v.strip.gsub(/[^\S\t]+/, " ").gsub(/\t+/, " ")]
245
245
  end
246
- canonical_headers = Hash[headers_arr]
246
+ canonical_headers = headers_arr.to_h
247
247
  canonical_headers["host"] = host_name virtual_hosted_style, bucket_bound_hostname
248
248
 
249
249
  canonical_headers = canonical_headers.sort_by(&:first).to_h
@@ -295,13 +295,13 @@ module Google
295
295
  ##
296
296
  # The external path to the bucket, with trailing slash.
297
297
  def bucket_path path_style
298
- return "/#{@bucket_name}/" if path_style
298
+ "/#{@bucket_name}/" if path_style
299
299
  end
300
300
 
301
301
  ##
302
302
  # The external url to the file.
303
303
  def ext_url scheme, virtual_hosted_style, bucket_bound_hostname
304
- url = GOOGLEAPIS_URL.dup
304
+ url = @service.service.root_url.chomp "/"
305
305
  if virtual_hosted_style
306
306
  parts = url.split "//"
307
307
  parts[1] = "#{@bucket_name}.#{parts[1]}"
@@ -763,6 +763,30 @@ module Google
763
763
  @gapi.retention_expiration_time
764
764
  end
765
765
 
766
+ ##
767
+ # This soft delete time is the time when the object became
768
+ # soft-deleted.
769
+ #
770
+ # @return [DateTime, nil] A DateTime representing the time at
771
+ # which the object became soft-deleted, or `nil` if the file was
772
+ # not deleted.
773
+ #
774
+ def soft_delete_time
775
+ @gapi.soft_delete_time
776
+ end
777
+
778
+ ##
779
+ # This hard delete time is The time when the file will be permanently
780
+ # deleted.
781
+ #
782
+ # @return [DateTime, nil] A DateTime representing the time at
783
+ # which the file will be permanently deleted, or `nil` if the file is
784
+ # not soft deleted.
785
+ #
786
+ def hard_delete_time
787
+ @gapi.hard_delete_time
788
+ end
789
+
766
790
  ##
767
791
  # Retrieves a list of versioned files for the current object.
768
792
  #
@@ -825,6 +849,9 @@ module Google
825
849
  # @param [Integer] if_metageneration_not_match Makes the operation
826
850
  # conditional on whether the file's current metageneration does not
827
851
  # match the given value.
852
+ # @param [Boolean] override_unlocked_retention
853
+ # Must be true to remove the retention configuration, reduce its unlocked
854
+ # retention period, or change its mode from unlocked to locked.
828
855
  #
829
856
  # @yield [file] a block yielding a delegate object for updating the file
830
857
  #
@@ -865,7 +892,8 @@ module Google
865
892
  if_generation_match: nil,
866
893
  if_generation_not_match: nil,
867
894
  if_metageneration_match: nil,
868
- if_metageneration_not_match: nil
895
+ if_metageneration_not_match: nil,
896
+ override_unlocked_retention: nil
869
897
  updater = Updater.new gapi
870
898
  yield updater
871
899
  updater.check_for_changed_metadata!
@@ -875,7 +903,8 @@ module Google
875
903
  if_generation_match: if_generation_match,
876
904
  if_generation_not_match: if_generation_not_match,
877
905
  if_metageneration_match: if_metageneration_match,
878
- if_metageneration_not_match: if_metageneration_not_match
906
+ if_metageneration_not_match: if_metageneration_not_match,
907
+ override_unlocked_retention: override_unlocked_retention
879
908
  end
880
909
 
881
910
  ##
@@ -1560,6 +1589,64 @@ module Google
1560
1589
  true
1561
1590
  end
1562
1591
 
1592
+ # Mode of object level retention configuration.
1593
+ # Valid values are 'Locked' or 'Unlocked'
1594
+ #
1595
+ # @return [String]
1596
+ def retention_mode
1597
+ @gapi.retention&.mode
1598
+ end
1599
+
1600
+ # The earliest time in RFC 3339 UTC "Zulu" format that the object can
1601
+ # be deleted or replaced.
1602
+ #
1603
+ # @return [DateTime]
1604
+ def retention_retain_until_time
1605
+ @gapi.retention&.retain_until_time
1606
+ end
1607
+
1608
+ # A collection of object level retention parameters.
1609
+ # The full list of available options are outlined at the [JSON API docs]
1610
+ # (https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request-body).
1611
+ #
1612
+ # @return [Google::Apis::StorageV1::Object::Retention]
1613
+ def retention
1614
+ @gapi.retention
1615
+ end
1616
+
1617
+ ##
1618
+ # Update method to update retention parameter of an object / file
1619
+ # It accepts params as a Hash of attributes in the following format:
1620
+ #
1621
+ # { mode: 'Locked|Unlocked', retain_until_time: '2023-12-19T03:22:23+00:00' }
1622
+ #
1623
+ # @param [Hash(String => String)] new_retention_attributes
1624
+ #
1625
+ # @example Update retention parameters for the File / Object
1626
+ # require "google/cloud/storage"
1627
+ # storage = Google::Cloud::Storage.new
1628
+ # bucket = storage.bucket "my-bucket"
1629
+ # file = bucket.file "avatars/heidi/400x400.png"
1630
+ # retention_params = { mode: 'Unlocked', retain_until_time: '2023-12-19T03:22:23+00:00'.to_datetime }
1631
+ # file.retention = retention_params
1632
+ #
1633
+ # @example Update retention parameters for the File / Object with override enabled
1634
+ # require "google/cloud/storage"
1635
+ # storage = Google::Cloud::Storage.new
1636
+ # bucket = storage.bucket "my-bucket"
1637
+ # file = bucket.file "avatars/heidi/400x400.png"
1638
+ # retention_params = { mode: 'Unlocked',
1639
+ # retain_until_time: '2023-12-19T03:22:23+00:00'.to_datetime,
1640
+ # override_unlocked_retention: true }
1641
+ # file.retention = retention_params
1642
+ #
1643
+ def retention= new_retention_attributes
1644
+ @gapi.retention ||= Google::Apis::StorageV1::Object::Retention.new
1645
+ @gapi.retention.mode = new_retention_attributes[:mode]
1646
+ @gapi.retention.retain_until_time = new_retention_attributes[:retain_until_time]
1647
+ update_gapi! :retention, override_unlocked_retention: new_retention_attributes[:override_unlocked_retention]
1648
+ end
1649
+
1563
1650
  ##
1564
1651
  # Public URL to access the file. If the file is not public, requests to
1565
1652
  # the URL will return an error. (See {File::Acl#public!} and
@@ -1985,15 +2072,59 @@ module Google
1985
2072
  def self.gapi_from_attrs gapi, attributes
1986
2073
  attributes.flatten!
1987
2074
  return nil if attributes.empty?
1988
- attr_params = Hash[attributes.map do |attr|
1989
- [attr, gapi.send(attr)]
1990
- end]
2075
+ attr_params = attributes.to_h do |attr|
2076
+ [attr, gapi.send(attr)]
2077
+ end
1991
2078
  # Sending nil metadata results in an Apiary runtime error:
1992
2079
  # NoMethodError: undefined method `each' for nil:NilClass
1993
2080
  attr_params.reject! { |k, v| k == :metadata && v.nil? }
1994
2081
  Google::Apis::StorageV1::Object.new(**attr_params)
1995
2082
  end
1996
2083
 
2084
+ ##
2085
+ # from_gs_url is a method to fetch bucket details and file details from a gs url
2086
+ #
2087
+ # @return [Hash(String => String)]
2088
+ #
2089
+ # @example Fetch bucket_name and file_Path from gs url:
2090
+ # require "google/cloud/storage"
2091
+ # gs_url= "gs://my-todo-app/avatars/heidi.jpeg"
2092
+ # file=Google::Cloud::Storage::File
2093
+ # file.from_gs_url(gs_url)
2094
+ # =>
2095
+ # {"bucket_name"=>"my-todo-app", "file_path"=>"avatars/heidi.jpeg"}
2096
+ #
2097
+ # @example Fetch bucket_name , file_Path and other query params from gs url:
2098
+ # require "google/cloud/storage"
2099
+ # gs_url= "gs://my-todo-app/test_sub_folder/heidi.jpeg?params1=test1&params2=test2"
2100
+ # file=Google::Cloud::Storage::File
2101
+ # file.from_gs_url(gs_url)
2102
+ # =>{
2103
+ # "bucket_name"=>"my-todo-app",
2104
+ # "file_path"=>"test_sub_folder/heidi.jpeg",
2105
+ # "options" => {
2106
+ # "params1"=>"test1",
2107
+ # "params2"=>"test2"
2108
+ # }
2109
+ # }
2110
+
2111
+ def self.from_gs_url gs_url
2112
+ prefix = "gs://".freeze
2113
+ raise ArgumentError, "Invalid GCS URL" unless gs_url.start_with? prefix
2114
+ # seprating params from input url
2115
+ path, query = gs_url.sub(prefix, "").split("?", 2)
2116
+ # parsing the url
2117
+ bucket_name, file_path = path.split "/", 2
2118
+ query_params = URI.decode_www_form(query).to_h if query
2119
+ url_items = {
2120
+ "bucket_name" => bucket_name,
2121
+ "file_path" => file_path
2122
+ }
2123
+ # adding url params to output hash
2124
+ url_items.merge! "options" => query_params if query
2125
+ url_items
2126
+ end
2127
+
1997
2128
  protected
1998
2129
 
1999
2130
  ##
@@ -2015,7 +2146,8 @@ module Google
2015
2146
  if_generation_match: nil,
2016
2147
  if_generation_not_match: nil,
2017
2148
  if_metageneration_match: nil,
2018
- if_metageneration_not_match: nil
2149
+ if_metageneration_not_match: nil,
2150
+ override_unlocked_retention: nil
2019
2151
  attributes = Array(attributes)
2020
2152
  attributes.flatten!
2021
2153
  return if attributes.empty?
@@ -2044,7 +2176,8 @@ module Google
2044
2176
  if_generation_not_match: if_generation_not_match,
2045
2177
  if_metageneration_match: if_metageneration_match,
2046
2178
  if_metageneration_not_match: if_metageneration_not_match,
2047
- user_project: user_project
2179
+ user_project: user_project,
2180
+ override_unlocked_retention: override_unlocked_retention
2048
2181
  end
2049
2182
  end
2050
2183
 
@@ -2107,10 +2240,8 @@ module Google
2107
2240
  [dest_bucket, dest_path]
2108
2241
  end
2109
2242
 
2110
- # rubocop:disable Style/MultipleComparison
2111
-
2112
2243
  def verify_file! file, verify = :md5
2113
- verify_md5 = verify == :md5 || verify == :all
2244
+ verify_md5 = verify == :md5 || verify == :all
2114
2245
  verify_crc32c = verify == :crc32c || verify == :all
2115
2246
  Verifier.verify_md5! self, file if verify_md5 && md5
2116
2247
  Verifier.verify_crc32c! self, file if verify_crc32c && crc32c
@@ -168,10 +168,10 @@ module Google
168
168
  # puts binding.role
169
169
  # end
170
170
  #
171
- def each &block
171
+ def each(&)
172
172
  return enum_for :each unless block_given?
173
173
 
174
- @bindings.each(&block)
174
+ @bindings.each(&)
175
175
  end
176
176
 
177
177
  ##
@@ -62,6 +62,15 @@ module Google
62
62
  @service = service
63
63
  end
64
64
 
65
+ ##
66
+ # The universe domain the client is connected to
67
+ #
68
+ # @return [String]
69
+ #
70
+ def universe_domain
71
+ service.universe_domain
72
+ end
73
+
65
74
  ##
66
75
  # The Storage project connected to.
67
76
  #
@@ -90,8 +99,7 @@ module Google
90
99
  # @return [String] The service account email address.
91
100
  #
92
101
  def service_account_email
93
- @service_account_email ||= \
94
- service.project_service_account.email_address
102
+ @service_account_email ||= service.project_service_account.email_address
95
103
  end
96
104
 
97
105
  ##
@@ -184,11 +192,20 @@ module Google
184
192
  # puts bucket.name
185
193
  # end
186
194
  #
187
- def buckets prefix: nil, token: nil, max: nil, user_project: nil
195
+ # @example Retrieve soft deleted buckets
196
+ # require "google/cloud/storage"
197
+ #
198
+ # storage = Google::Cloud::Storage.new
199
+ #
200
+ # soft_deleted_buckets = storage.buckets soft_deleted: true
201
+ # soft_deleted_buckets.each do |bucket|
202
+ # puts bucket.name
203
+ # end
204
+ def buckets prefix: nil, token: nil, max: nil, user_project: nil, soft_deleted: nil
188
205
  gapi = service.list_buckets \
189
- prefix: prefix, token: token, max: max, user_project: user_project
206
+ prefix: prefix, token: token, max: max, user_project: user_project, soft_deleted: soft_deleted
190
207
  Bucket::List.from_gapi \
191
- gapi, service, prefix, max, user_project: user_project
208
+ gapi, service, prefix, max, user_project: user_project, soft_deleted: soft_deleted
192
209
  end
193
210
  alias find_buckets buckets
194
211
 
@@ -214,6 +231,10 @@ module Google
214
231
  # account, transit costs will be billed to the given project. This
215
232
  # parameter is required with requester pays-enabled buckets. The
216
233
  # default is `nil`.
234
+ # @param [Integer] generation generation no of bucket
235
+ # on whether the bucket's current metageneration matches the given value.
236
+ # @param [Boolean] soft_deleted If true, returns the soft-deleted bucket.
237
+ # This parameter is required if generation is specified.
217
238
  #
218
239
  # The value provided will be applied to all operations on the returned
219
240
  # bucket instance and its files.
@@ -247,9 +268,20 @@ module Google
247
268
  # bucket = storage.bucket "other-project-bucket",
248
269
  # user_project: "my-other-project"
249
270
  # files = bucket.files # Billed to "my-other-project"
271
+ # @example With `soft_deleted` set to true and generation specified:
272
+ # require "google/cloud/storage"
273
+ #
274
+ # storage = Google::Cloud::Storage.new
275
+ #
276
+ # bucket = storage.bucket "my-bucket",
277
+ # soft_deleted: true,
278
+ # generation: 1234567889
279
+ # puts bucket.name
250
280
  #
251
281
  def bucket bucket_name,
252
282
  skip_lookup: false,
283
+ generation: nil,
284
+ soft_deleted: nil,
253
285
  if_metageneration_match: nil,
254
286
  if_metageneration_not_match: nil,
255
287
  user_project: nil
@@ -260,7 +292,10 @@ module Google
260
292
  gapi = service.get_bucket bucket_name,
261
293
  if_metageneration_match: if_metageneration_match,
262
294
  if_metageneration_not_match: if_metageneration_not_match,
263
- user_project: user_project
295
+ user_project: user_project,
296
+ soft_deleted: soft_deleted,
297
+ generation: generation
298
+
264
299
  Bucket.from_gapi gapi, service, user_project: user_project
265
300
  rescue Google::Cloud::NotFoundError
266
301
  nil
@@ -372,6 +407,8 @@ module Google
372
407
  # bucket instance and its files.
373
408
  #
374
409
  # See also {Bucket#requester_pays=} and {Bucket#requester_pays}.
410
+ # @param [Boolean] enable_object_retention
411
+ # When set to true, object retention is enabled for this bucket.
375
412
  #
376
413
  # @yield [bucket] a block for configuring the bucket before it is
377
414
  # created
@@ -386,6 +423,13 @@ module Google
386
423
  #
387
424
  # bucket = storage.create_bucket "my-bucket"
388
425
  #
426
+ # @example
427
+ # require "google/cloud/storage"
428
+ #
429
+ # storage = Google::Cloud::Storage.new
430
+ #
431
+ # bucket = storage.create_bucket "my-bucket", enable_object_retention: true
432
+ #
389
433
  # @example Configure the bucket in a block:
390
434
  # require "google/cloud/storage"
391
435
  #
@@ -403,6 +447,7 @@ module Google
403
447
  # b.lifecycle.add_set_storage_class_rule "COLDLINE", age: 10
404
448
  # end
405
449
  #
450
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
406
451
  def create_bucket bucket_name,
407
452
  acl: nil,
408
453
  default_acl: nil,
@@ -416,11 +461,14 @@ module Google
416
461
  versioning: nil,
417
462
  requester_pays: nil,
418
463
  user_project: nil,
419
- autoclass_enabled: false
464
+ autoclass_enabled: false,
465
+ enable_object_retention: nil,
466
+ hierarchical_namespace: nil
420
467
  params = {
421
468
  name: bucket_name,
422
469
  location: location,
423
- custom_placement_config: custom_placement_config
470
+ custom_placement_config: custom_placement_config,
471
+ hierarchical_namespace: hierarchical_namespace
424
472
  }.delete_if { |_, v| v.nil? }
425
473
  new_bucket = Google::Apis::StorageV1::Bucket.new(**params)
426
474
  storage_class = storage_class_for storage_class
@@ -433,6 +481,7 @@ module Google
433
481
  b.website_404 = website_404 unless website_404.nil?
434
482
  b.versioning = versioning unless versioning.nil?
435
483
  b.requester_pays = requester_pays unless requester_pays.nil?
484
+ b.hierarchical_namespace = hierarchical_namespace unless hierarchical_namespace.nil?
436
485
  end
437
486
  yield updater if block_given?
438
487
  updater.check_for_changed_labels!
@@ -440,9 +489,11 @@ module Google
440
489
  updater.check_for_mutable_lifecycle!
441
490
  gapi = service.insert_bucket \
442
491
  new_bucket, acl: acl_rule(acl), default_acl: acl_rule(default_acl),
443
- user_project: user_project
492
+ user_project: user_project,
493
+ enable_object_retention: enable_object_retention
444
494
  Bucket.from_gapi gapi, service, user_project: user_project
445
495
  end
496
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
446
497
 
447
498
  ##
448
499
  # Creates a new HMAC key.
@@ -529,6 +580,32 @@ module Google
529
580
  max: max, user_project: user_project
530
581
  end
531
582
 
583
+ ##
584
+ # Restores a soft deleted bucket with bucket name and generation.
585
+ #
586
+ # @param [String] bucket_name Name of the bucket.
587
+ # @param [Fixnum] generation Generation of the bucket.
588
+ #
589
+ # @return [Google::Cloud::Storage::Bucket, nil] Returns nil if bucket
590
+ # does not exist
591
+ #
592
+ # @example
593
+ # require "google/cloud/storage"
594
+ #
595
+ # storage = Google::Cloud::Storage.new
596
+ # generation= 123
597
+ #
598
+ # bucket = storage.restore_bucket "my-bucket", generation
599
+ # puts bucket.name
600
+ #
601
+ def restore_bucket bucket_name,
602
+ generation,
603
+ options: {}
604
+ gapi = service.restore_bucket bucket_name, generation,
605
+ options: options
606
+ Bucket.from_gapi gapi, service
607
+ end
608
+
532
609
  ##
533
610
  # Generates a signed URL. See [Signed
534
611
  # URLs](https://cloud.google.com/storage/docs/access-control/signed-urls)