google-cloud-storage 1.34.1 → 1.41.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c1a4e8d81d477657fb10766346d62bf9f4bbc9934af2b63a2cadb57195308df
4
- data.tar.gz: 5a40bdb4ecfff8f5e93f3047ed9c6e85ccc5b3bba9a17b00aaeb5dcc979b66b5
3
+ metadata.gz: 76faccf343a999af8ed510541b67d64e5702bc6bbf963f75897a8fa7790a3e33
4
+ data.tar.gz: 628678d5a6cfa02d876f9c2074bd10946f4b26321b3662f3ec4adc867ea2a01f
5
5
  SHA512:
6
- metadata.gz: 5380175443d2e863193a5b176a17e29d76d36eeeaaa7e059569168799a62969f8bd9b4e6359119b035f6586aaeb8af996cadfe01f7e7864db2c183e93e823aa1
7
- data.tar.gz: 3954e38231d1cc1bd5679ed011eef6dd69f644e855f621d4af08dd207c815ede1393285953364256b9d1b49175ac6c35710ed01253ecd92b31ab5a66b2143090
6
+ metadata.gz: b3b97cdc696e3a31de191ef1dc9d787d38213828fee6bb4453bf8b8a66177439fdc82146decdea261c83d6271aabfda9f69e9535a2e875a26fd6cbe62f31d6b2
7
+ data.tar.gz: 6fb8915241720f4ac9a163028ab1db195309591cab27b1e12cb6020bd5fc9c85bebadebc9301f2c68a04c32ea32d24408c20357bd637c91968dc209a96535bde
data/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # Release History
2
2
 
3
+ ### 1.41.0 (2022-09-16)
4
+
5
+ #### Features
6
+
7
+ * add retry support for non-idempotent operations ([#19134](https://github.com/googleapis/google-cloud-ruby/issues/19134))
8
+ #### Bug Fixes
9
+
10
+ * Correct options checks in retry operations ([#19135](https://github.com/googleapis/google-cloud-ruby/issues/19135))
11
+ * Update api for bucket update ([#19110](https://github.com/googleapis/google-cloud-ruby/issues/19110))
12
+
13
+ ### 1.40.0 (2022-09-13)
14
+
15
+ #### Features
16
+
17
+ * Update all patch bucket helper methods to accept preconditions ([#19117](https://github.com/googleapis/google-cloud-ruby/issues/19117))
18
+
19
+ ### 1.39.0 (2022-08-24)
20
+
21
+ #### Features
22
+
23
+ * add support for conditional idempotent operations ([#18834](https://github.com/googleapis/google-cloud-ruby/issues/18834))
24
+
25
+ ### 1.38.0 (2022-07-31)
26
+
27
+ #### Features
28
+
29
+ * Add support for dual region gcs buckets ([#18862](https://github.com/googleapis/google-cloud-ruby/issues/18862))
30
+
31
+ ### 1.37.0 (2022-06-30)
32
+
33
+ #### Features
34
+
35
+ * support OLM Prefix/Suffix ([#18190](https://github.com/googleapis/google-cloud-ruby/issues/18190))
36
+ * allow retry options to be configurable on client initialization ([#18332](https://github.com/googleapis/google-cloud-ruby/issues/18332))
37
+ #### Bug Fixes
38
+
39
+ * update object path parsing to handle hashes in them
40
+
41
+ ### 1.36.2 (2022-04-20)
42
+
43
+ #### Documentation
44
+
45
+ * Document support for dual region buckets
46
+
47
+ ### 1.36.1 / 2022-02-08
48
+
49
+ #### Documentation
50
+
51
+ * Update the RPO sample output. ([#17277](https://www.github.com/googleapis/google-cloud-ruby/issues/17277))
52
+
53
+ ### 1.36.0 / 2022-01-12
54
+
55
+ #### Features
56
+
57
+ * add support for RPO (turbo replication). ([#14407](https://www.github.com/googleapis/google-cloud-ruby/issues/14407))
58
+
59
+ ### 1.35.0 / 2021-12-08
60
+
61
+ #### Features
62
+
63
+ * changed PAP unspecified to inherited
64
+ * support for more client timeout options
65
+
66
+ #### Bug Fixes
67
+
68
+ * Update dependency on the addressable gem to 2.8 to remediate a vulnerability
69
+
3
70
  ### 1.34.1 / 2021-07-08
4
71
 
5
72
  #### Documentation
data/OVERVIEW.md CHANGED
@@ -563,6 +563,38 @@ require "google/cloud/storage"
563
563
  storage = Google::Cloud::Storage.new retries: 10, timeout: 120
564
564
  ```
565
565
 
566
+ The library by default retries all API requests which are always idempotent on a
567
+ "transient" error.
568
+
569
+ For API requests which are idempotent only if the some conditions are satisfied
570
+ (For ex. a file has the same "generation"), the library retries only if the
571
+ condition is specified.
572
+
573
+ Rather than using this default behaviour, you may choose to disable the retries
574
+ on your own.
575
+
576
+ You can pass `retries` as `0` to disable retries for all operations regardless
577
+ of their idempotencies.
578
+
579
+ ```ruby
580
+ require "google/cloud/storage"
581
+
582
+ storage = Google::Cloud::Storage.new retries: 0
583
+ ```
584
+
585
+ You can also disable retries for a particular operation by passing `retries` as
586
+ `0` in the `options` field.
587
+
588
+ ```ruby
589
+ require "google/cloud/storage"
590
+
591
+ storage = Google::Cloud::Storage.new
592
+ service = storage.service
593
+ service.get_bucket bucket_name, options: {retries: 0}
594
+ ```
595
+
596
+ For those API requests which are never idempotent, the library passes retries=0 by default, suppressing any retries.
597
+
566
598
  See the [Storage status and error
567
599
  codes](https://cloud.google.com/storage/docs/json_api/v1/status-codes)
568
600
  for a list of error conditions.
@@ -349,8 +349,8 @@ module Google
349
349
  #
350
350
  # bucket.acl.auth!
351
351
  #
352
- def auth!
353
- update_predefined_acl! "authenticatedRead"
352
+ def auth! if_metageneration_match: nil
353
+ update_predefined_acl! "authenticatedRead", if_metageneration_match: if_metageneration_match
354
354
  end
355
355
  alias authenticatedRead! auth!
356
356
  alias auth_read! auth!
@@ -370,8 +370,8 @@ module Google
370
370
  #
371
371
  # bucket.acl.private!
372
372
  #
373
- def private!
374
- update_predefined_acl! "private"
373
+ def private! if_metageneration_match: nil
374
+ update_predefined_acl! "private", if_metageneration_match: if_metageneration_match
375
375
  end
376
376
 
377
377
  ##
@@ -387,8 +387,8 @@ module Google
387
387
  #
388
388
  # bucket.acl.project_private!
389
389
  #
390
- def project_private!
391
- update_predefined_acl! "projectPrivate"
390
+ def project_private! if_metageneration_match: nil
391
+ update_predefined_acl! "projectPrivate", if_metageneration_match: if_metageneration_match
392
392
  end
393
393
  alias projectPrivate! project_private!
394
394
 
@@ -405,8 +405,8 @@ module Google
405
405
  #
406
406
  # bucket.acl.public!
407
407
  #
408
- def public!
409
- update_predefined_acl! "publicRead"
408
+ def public! if_metageneration_match: nil
409
+ update_predefined_acl! "publicRead", if_metageneration_match: if_metageneration_match
410
410
  end
411
411
  alias publicRead! public!
412
412
  alias public_read! public!
@@ -423,8 +423,8 @@ module Google
423
423
  #
424
424
  # bucket.acl.public_write!
425
425
  #
426
- def public_write!
427
- update_predefined_acl! "publicReadWrite"
426
+ def public_write! if_metageneration_match: nil
427
+ update_predefined_acl! "publicReadWrite", if_metageneration_match: if_metageneration_match
428
428
  end
429
429
  alias publicReadWrite! public_write!
430
430
 
@@ -437,9 +437,10 @@ module Google
437
437
  self
438
438
  end
439
439
 
440
- def update_predefined_acl! acl_role
440
+ def update_predefined_acl! acl_role, if_metageneration_match: nil
441
441
  @service.patch_bucket @bucket, predefined_acl: acl_role,
442
- user_project: user_project
442
+ user_project: user_project,
443
+ if_metageneration_match: if_metageneration_match
443
444
  clear!
444
445
  end
445
446
 
@@ -714,8 +715,8 @@ module Google
714
715
  #
715
716
  # bucket.default_acl.auth!
716
717
  #
717
- def auth!
718
- update_predefined_default_acl! "authenticatedRead"
718
+ def auth! if_metageneration_match: nil
719
+ update_predefined_default_acl! "authenticatedRead", if_metageneration_match: if_metageneration_match
719
720
  end
720
721
  alias authenticatedRead! auth!
721
722
  alias auth_read! auth!
@@ -735,8 +736,8 @@ module Google
735
736
  #
736
737
  # bucket.default_acl.owner_full!
737
738
  #
738
- def owner_full!
739
- update_predefined_default_acl! "bucketOwnerFullControl"
739
+ def owner_full! if_metageneration_match: nil
740
+ update_predefined_default_acl! "bucketOwnerFullControl", if_metageneration_match: if_metageneration_match
740
741
  end
741
742
  alias bucketOwnerFullControl! owner_full!
742
743
 
@@ -753,8 +754,8 @@ module Google
753
754
  #
754
755
  # bucket.default_acl.owner_read!
755
756
  #
756
- def owner_read!
757
- update_predefined_default_acl! "bucketOwnerRead"
757
+ def owner_read! if_metageneration_match: nil
758
+ update_predefined_default_acl! "bucketOwnerRead", if_metageneration_match: if_metageneration_match
758
759
  end
759
760
  alias bucketOwnerRead! owner_read!
760
761
 
@@ -771,8 +772,8 @@ module Google
771
772
  #
772
773
  # bucket.default_acl.private!
773
774
  #
774
- def private!
775
- update_predefined_default_acl! "private"
775
+ def private! if_metageneration_match: nil
776
+ update_predefined_default_acl! "private", if_metageneration_match: if_metageneration_match
776
777
  end
777
778
 
778
779
  ##
@@ -788,8 +789,8 @@ module Google
788
789
  #
789
790
  # bucket.default_acl.project_private!
790
791
  #
791
- def project_private!
792
- update_predefined_default_acl! "projectPrivate"
792
+ def project_private! if_metageneration_match: nil
793
+ update_predefined_default_acl! "projectPrivate", if_metageneration_match: if_metageneration_match
793
794
  end
794
795
  alias projectPrivate! project_private!
795
796
 
@@ -806,8 +807,8 @@ module Google
806
807
  #
807
808
  # bucket.default_acl.public!
808
809
  #
809
- def public!
810
- update_predefined_default_acl! "publicRead"
810
+ def public! if_metageneration_match: nil
811
+ update_predefined_default_acl! "publicRead", if_metageneration_match: if_metageneration_match
811
812
  end
812
813
  alias publicRead! public!
813
814
  alias public_read! public!
@@ -820,9 +821,10 @@ module Google
820
821
  self
821
822
  end
822
823
 
823
- def update_predefined_default_acl! acl_role
824
+ def update_predefined_default_acl! acl_role, if_metageneration_match: nil
824
825
  @service.patch_bucket @bucket, predefined_default_acl: acl_role,
825
- user_project: user_project
826
+ user_project: user_project,
827
+ if_metageneration_match: if_metageneration_match
826
828
  clear!
827
829
  end
828
830
 
@@ -53,6 +53,8 @@ module Google
53
53
  # rule.storage_class #=> "COLDLINE"
54
54
  # rule.age #=> 10
55
55
  # rule.matches_storage_class #=> ["STANDARD", "NEARLINE"]
56
+ # rule.matches_prefix #=> ["myprefix/foo"]
57
+ # rule.matches_suffix #=> [".jpg", ".png"]
56
58
  #
57
59
  # @example Updating the bucket's lifecycle management rules in a block.
58
60
  # require "google/cloud/storage"
@@ -138,6 +140,12 @@ module Google
138
140
  # files. If the value is N, this condition is satisfied when there
139
141
  # are at least N versions (including the live version) newer than
140
142
  # this version of the file.
143
+ # @param [Array<String,Symbol>] matches_prefix
144
+ # Files having their name with the specified list of prefixs will be matched.
145
+ # Arguments will be converted from symbols to strings.
146
+ # @param [Array<String,Symbol>] matches_suffix
147
+ # Files having their name with the specified list of suffixes will be matched.
148
+ # Arguments will be converted from symbols to strings.
141
149
  #
142
150
  # @example
143
151
  # require "google/cloud/storage"
@@ -157,7 +165,9 @@ module Google
157
165
  is_live: nil,
158
166
  matches_storage_class: nil,
159
167
  noncurrent_time_before: nil,
160
- num_newer_versions: nil
168
+ num_newer_versions: nil,
169
+ matches_prefix: nil,
170
+ matches_suffix: nil
161
171
  push Rule.new(
162
172
  "SetStorageClass",
163
173
  storage_class: storage_class_for(storage_class),
@@ -169,12 +179,14 @@ module Google
169
179
  is_live: is_live,
170
180
  matches_storage_class: storage_class_for(matches_storage_class),
171
181
  noncurrent_time_before: noncurrent_time_before,
172
- num_newer_versions: num_newer_versions
182
+ num_newer_versions: num_newer_versions,
183
+ matches_prefix: Array(matches_prefix),
184
+ matches_suffix: Array(matches_suffix)
173
185
  )
174
186
  end
175
187
 
176
188
  ##
177
- # Adds a SetStorageClass lifecycle rule to the Object Lifecycle
189
+ # Adds a Delete lifecycle rule to the Object Lifecycle
178
190
  # Management rules for a bucket.
179
191
  #
180
192
  # @see https://cloud.google.com/storage/docs/lifecycle Object
@@ -221,6 +233,12 @@ module Google
221
233
  # files. If the value is N, this condition is satisfied when there
222
234
  # are at least N versions (including the live version) newer than
223
235
  # this version of the file.
236
+ # @param [Array<String,Symbol>] matches_prefix
237
+ # Files having their name with the specified list of prefixs will be matched.
238
+ # Arguments will be converted from symbols to strings.
239
+ # @param [Array<String,Symbol>] matches_suffix
240
+ # Files having their name with the specified list of suffixes will be matched.
241
+ # Arguments will be converted from symbols to strings.
224
242
  #
225
243
  # @example
226
244
  # require "google/cloud/storage"
@@ -239,7 +257,9 @@ module Google
239
257
  is_live: nil,
240
258
  matches_storage_class: nil,
241
259
  noncurrent_time_before: nil,
242
- num_newer_versions: nil
260
+ num_newer_versions: nil,
261
+ matches_prefix: nil,
262
+ matches_suffix: nil
243
263
  push Rule.new(
244
264
  "Delete",
245
265
  age: age,
@@ -250,7 +270,49 @@ module Google
250
270
  is_live: is_live,
251
271
  matches_storage_class: storage_class_for(matches_storage_class),
252
272
  noncurrent_time_before: noncurrent_time_before,
253
- num_newer_versions: num_newer_versions
273
+ num_newer_versions: num_newer_versions,
274
+ matches_prefix: Array(matches_prefix),
275
+ matches_suffix: Array(matches_suffix)
276
+ )
277
+ end
278
+
279
+ ##
280
+ # Adds a AbortIncompleteMultipartUpload lifecycle rule to the Object Lifecycle
281
+ # Management rules for a bucket.
282
+ #
283
+ # @see https://cloud.google.com/storage/docs/lifecycle Object
284
+ # Lifecycle Management
285
+ # @see https://cloud.google.com/storage/docs/managing-lifecycles
286
+ # Managing Object Lifecycles
287
+ #
288
+ # @param [Integer] age The age of a file (in days). This condition is
289
+ # satisfied when a file reaches the specified age.
290
+ # @param [Array<String,Symbol>] matches_prefix
291
+ # Files having their name with the specified list of prefixs will be matched.
292
+ # Arguments will be converted from symbols to strings.
293
+ # @param [Array<String,Symbol>] matches_suffix
294
+ # Files having their name with the specified list of suffixes will be matched.
295
+ # Arguments will be converted from symbols to strings.
296
+ #
297
+ # @example
298
+ # require "google/cloud/storage"
299
+ #
300
+ # storage = Google::Cloud::Storage.new
301
+ #
302
+ # bucket = storage.create_bucket "my-bucket" do |b|
303
+ # b.lifecycle.add_abort_incomplete_multipart_upload_rule age: 10,
304
+ # matches_prefix: ["images/"],
305
+ # matches_suffix: [".pdf"]
306
+ # end
307
+ #
308
+ def add_abort_incomplete_multipart_upload_rule age: nil,
309
+ matches_prefix: nil,
310
+ matches_suffix: nil
311
+ push Rule.new(
312
+ "AbortIncompleteMultipartUpload",
313
+ age: age,
314
+ matches_prefix: Array(matches_prefix),
315
+ matches_suffix: Array(matches_suffix)
254
316
  )
255
317
  end
256
318
 
@@ -346,6 +408,8 @@ module Google
346
408
  # rule.storage_class #=> "COLDLINE"
347
409
  # rule.age #=> 10
348
410
  # rule.matches_storage_class #=> ["STANDARD", "NEARLINE"]
411
+ # rule.matches_prefix #=> ["myprefix/foo"]
412
+ # rule.matches_suffix #=> [".jpg", ".png"]
349
413
  #
350
414
  # @example Updating the bucket's lifecycle rules in a block.
351
415
  # require "google/cloud/storage"
@@ -382,6 +446,8 @@ module Google
382
446
  attr_accessor :matches_storage_class
383
447
  attr_accessor :noncurrent_time_before
384
448
  attr_accessor :num_newer_versions
449
+ attr_accessor :matches_prefix
450
+ attr_accessor :matches_suffix
385
451
 
386
452
  # @private
387
453
  def initialize action,
@@ -394,7 +460,9 @@ module Google
394
460
  is_live: nil,
395
461
  matches_storage_class: nil,
396
462
  noncurrent_time_before: nil,
397
- num_newer_versions: nil
463
+ num_newer_versions: nil,
464
+ matches_prefix: nil,
465
+ matches_suffix: nil
398
466
  @action = action
399
467
  @storage_class = storage_class
400
468
  @age = age
@@ -406,6 +474,8 @@ module Google
406
474
  @matches_storage_class = Array(matches_storage_class)
407
475
  @noncurrent_time_before = noncurrent_time_before
408
476
  @num_newer_versions = num_newer_versions
477
+ @matches_prefix = Array(matches_prefix)
478
+ @matches_suffix = Array(matches_suffix)
409
479
  end
410
480
 
411
481
  # @private
@@ -420,7 +490,9 @@ module Google
420
490
  is_live,
421
491
  matches_storage_class,
422
492
  noncurrent_time_before,
423
- num_newer_versions
493
+ num_newer_versions,
494
+ matches_prefix,
495
+ matches_suffix
424
496
  )
425
497
  Google::Apis::StorageV1::Bucket::Lifecycle::Rule.new(
426
498
  action: action_gapi(action, storage_class),
@@ -445,7 +517,9 @@ module Google
445
517
  is_live,
446
518
  matches_storage_class,
447
519
  noncurrent_time_before,
448
- num_newer_versions
520
+ num_newer_versions,
521
+ matches_prefix,
522
+ matches_suffix
449
523
  Google::Apis::StorageV1::Bucket::Lifecycle::Rule::Condition.new(
450
524
  age: age,
451
525
  created_before: created_before,
@@ -455,7 +529,9 @@ module Google
455
529
  is_live: is_live,
456
530
  matches_storage_class: Array(matches_storage_class),
457
531
  noncurrent_time_before: noncurrent_time_before,
458
- num_newer_versions: num_newer_versions
532
+ num_newer_versions: num_newer_versions,
533
+ matches_prefix: Array(matches_prefix),
534
+ matches_suffix: Array(matches_suffix)
459
535
  )
460
536
  end
461
537
 
@@ -475,7 +551,9 @@ module Google
475
551
  is_live: c.is_live,
476
552
  matches_storage_class: c.matches_storage_class,
477
553
  noncurrent_time_before: c.noncurrent_time_before,
478
- num_newer_versions: c.num_newer_versions
554
+ num_newer_versions: c.num_newer_versions,
555
+ matches_prefix: c.matches_prefix,
556
+ matches_suffix: c.matches_suffix
479
557
  )
480
558
  end
481
559
 
@@ -279,7 +279,7 @@ module Google
279
279
  #
280
280
  # @return [String]
281
281
  #
282
- # @see https://cloud.google.com/storage/docs/concepts-techniques
282
+ # @see https://cloud.google.com/storage/docs/locations
283
283
  #
284
284
  def location
285
285
  @gapi.location
@@ -301,6 +301,20 @@ module Google
301
301
  @gapi.location_type
302
302
  end
303
303
 
304
+ ##
305
+ # Returns the list of regional locations for custom dual-region buckets.
306
+ #
307
+ # @return [String, nil] Returns nil if the property has not been set before creation,
308
+ # if the bucket's resource has not been loaded from the server,
309
+ # or if the bucket is not a dual-regions bucket.
310
+
311
+ # @see https://cloud.google.com/storage/docs/json_api/v1/buckets and
312
+ # https://cloud.google.com/storage/docs/locations
313
+ #
314
+ def data_locations
315
+ @gapi.custom_placement_config&.data_locations
316
+ end
317
+
304
318
  ##
305
319
  # The destination bucket name for the bucket's logs.
306
320
  #
@@ -932,11 +946,11 @@ module Google
932
946
  end
933
947
 
934
948
  ##
935
- # The value for Public Access Prevention in the bucket's IAM configuration. Currently, `unspecified` and
949
+ # The value for Public Access Prevention in the bucket's IAM configuration. Currently, `inherited` and
936
950
  # `enforced` are supported. When set to `enforced`, Public Access Prevention is enforced in the bucket's IAM
937
951
  # configuration. This value can be modified by calling {#public_access_prevention=}.
938
952
  #
939
- # @return [String, nil] Currently, `unspecified` and `enforced` are supported. Returns `nil` if the bucket has
953
+ # @return [String, nil] Currently, `inherited` and `enforced` are supported. Returns `nil` if the bucket has
940
954
  # no IAM configuration.
941
955
  #
942
956
  # @example
@@ -958,7 +972,7 @@ module Google
958
972
  # calling {#public_access_prevention}.
959
973
  #
960
974
  # @param [Symbol, String] new_public_access_prevention The bucket's new Public Access Prevention configuration.
961
- # Currently, `unspecified` and `enforced` are supported. When set to `enforced`, Public Access
975
+ # Currently, `inherited` and `enforced` are supported. When set to `enforced`, Public Access
962
976
  # Prevention is enforced in the bucket's IAM configuration.
963
977
  #
964
978
  # @example Set Public Access Prevention to enforced:
@@ -971,15 +985,15 @@ module Google
971
985
  # bucket.public_access_prevention = :enforced
972
986
  # bucket.public_access_prevention #=> "enforced"
973
987
  #
974
- # @example Set Public Access Prevention to unspecified:
988
+ # @example Set Public Access Prevention to inherited:
975
989
  # require "google/cloud/storage"
976
990
  #
977
991
  # storage = Google::Cloud::Storage.new
978
992
  #
979
993
  # bucket = storage.bucket "my-bucket"
980
994
  #
981
- # bucket.public_access_prevention = :unspecified
982
- # bucket.public_access_prevention #=> "unspecified"
995
+ # bucket.public_access_prevention = :inherited
996
+ # bucket.public_access_prevention #=> "inherited"
983
997
  #
984
998
  def public_access_prevention= new_public_access_prevention
985
999
  @gapi.iam_configuration ||= API::Bucket::IamConfiguration.new
@@ -1011,11 +1025,11 @@ module Google
1011
1025
  end
1012
1026
 
1013
1027
  ##
1014
- # Whether the value for Public Access Prevention in the bucket's IAM configuration is `unspecified`. The default
1028
+ # Whether the value for Public Access Prevention in the bucket's IAM configuration is `inherited`. The default
1015
1029
  # is `false`. This value can be modified by calling {Bucket#public_access_prevention=}.
1016
1030
  #
1017
1031
  # @return [Boolean] Returns `false` if the bucket has no IAM configuration or if Public Access Prevention is
1018
- # not `unspecified` in the IAM configuration. Returns `true` if Public Access Prevention is `unspecified` in
1032
+ # not `inherited` in the IAM configuration. Returns `true` if Public Access Prevention is `inherited` in
1019
1033
  # the IAM configuration.
1020
1034
  #
1021
1035
  # @example
@@ -1025,12 +1039,70 @@ module Google
1025
1039
  #
1026
1040
  # bucket = storage.bucket "my-bucket"
1027
1041
  #
1028
- # bucket.public_access_prevention = :unspecified
1029
- # bucket.public_access_prevention_unspecified? # true
1042
+ # bucket.public_access_prevention = :inherited
1043
+ # bucket.public_access_prevention_inherited? # true
1030
1044
  #
1031
- def public_access_prevention_unspecified?
1045
+ def public_access_prevention_inherited?
1032
1046
  return false unless @gapi.iam_configuration&.public_access_prevention
1033
- @gapi.iam_configuration.public_access_prevention.to_s == "unspecified"
1047
+ ["inherited", "unspecified"].include? @gapi.iam_configuration.public_access_prevention.to_s
1048
+ end
1049
+
1050
+ alias public_access_prevention_unspecified? public_access_prevention_inherited?
1051
+
1052
+ ##
1053
+ # Recovery Point Objective (RPO) is another attribute of a bucket, it measures how long it takes for a set of
1054
+ # updates to be asynchronously copied to the other region.
1055
+ # Currently, `DEFAULT` and `ASYNC_TURBO` are supported. When set to `ASYNC_TURBO`, Turbo Replication is enabled
1056
+ # for a bucket. `DEFAULT` is used to reset rpo on an existing bucket with rpo set to `ASYNC_TURBO`.
1057
+ # This value can be modified by calling {#rpo=}.
1058
+ #
1059
+ # @return [String, nil] Currently, `DEFAULT` and `ASYNC_TURBO` are supported. Returns `nil` if the bucket has
1060
+ # no RPO.
1061
+ #
1062
+ # @example
1063
+ # require "google/cloud/storage"
1064
+ #
1065
+ # storage = Google::Cloud::Storage.new
1066
+ #
1067
+ # bucket = storage.bucket "my-bucket"
1068
+ #
1069
+ # bucket.rpo = :DEFAULT
1070
+ # bucket.rpo #=> "DEFAULT"
1071
+ #
1072
+ def rpo
1073
+ @gapi.rpo
1074
+ end
1075
+
1076
+ ##
1077
+ # Sets the value for Recovery Point Objective (RPO) in the bucket. This value can be queried by calling {#rpo}.
1078
+ #
1079
+ # @param [Symbol, String] new_rpo The bucket's new Recovery Point Objective metadata.
1080
+ # Currently, `DEFAULT` and `ASYNC_TURBO` are supported. When set to `ASYNC_TURBO`, Turbo Replication
1081
+ # is enabled for a bucket.
1082
+ #
1083
+ # @example Set RPO to DEFAULT:
1084
+ # require "google/cloud/storage"
1085
+ #
1086
+ # storage = Google::Cloud::Storage.new
1087
+ #
1088
+ # bucket = storage.bucket "my-bucket"
1089
+ #
1090
+ # bucket.rpo = :DEFAULT
1091
+ # bucket.rpo #=> "DEFAULT"
1092
+ #
1093
+ # @example Set RPO to ASYNC_TURBO:
1094
+ # require "google/cloud/storage"
1095
+ #
1096
+ # storage = Google::Cloud::Storage.new
1097
+ #
1098
+ # bucket = storage.bucket "my-bucket"
1099
+ #
1100
+ # bucket.rpo = :ASYNC_TURBO
1101
+ # bucket.rpo #=> "ASYNC_TURBO"
1102
+ #
1103
+ def rpo= new_rpo
1104
+ @gapi.rpo = new_rpo&.to_s
1105
+ patch_gapi! :rpo
1034
1106
  end
1035
1107
 
1036
1108
  ##
@@ -1098,9 +1170,9 @@ module Google
1098
1170
  updater.check_for_mutable_cors!
1099
1171
  updater.check_for_mutable_lifecycle!
1100
1172
  return if updater.updates.empty?
1101
- patch_gapi! updater.updates,
1102
- if_metageneration_match: if_metageneration_match,
1103
- if_metageneration_not_match: if_metageneration_not_match
1173
+ update_gapi! updater.updates,
1174
+ if_metageneration_match: if_metageneration_match,
1175
+ if_metageneration_not_match: if_metageneration_not_match
1104
1176
  end
1105
1177
 
1106
1178
  ##
@@ -2833,6 +2905,26 @@ module Google
2833
2905
  self
2834
2906
  end
2835
2907
 
2908
+ def update_gapi! attributes,
2909
+ if_metageneration_match: nil,
2910
+ if_metageneration_not_match: nil
2911
+ attributes = Array(attributes)
2912
+ attributes.flatten!
2913
+ return if attributes.empty?
2914
+ ensure_service!
2915
+ update_args = Hash[attributes.map do |attr|
2916
+ [attr, @gapi.send(attr)]
2917
+ end]
2918
+ update_gapi = API::Bucket.new(**update_args)
2919
+ @gapi = service.update_bucket name,
2920
+ update_gapi,
2921
+ if_metageneration_match: if_metageneration_match,
2922
+ if_metageneration_not_match: if_metageneration_not_match,
2923
+ user_project: user_project
2924
+ @lazy = nil
2925
+ self
2926
+ end
2927
+
2836
2928
  ##
2837
2929
  # Raise an error if the file is not found.
2838
2930
  def ensure_io_or_file_exists! file
@@ -48,7 +48,7 @@ module Google
48
48
  #
49
49
  def ext_path
50
50
  path = "/#{@bucket}/#{@path}"
51
- escaped = Addressable::URI.escape path
51
+ escaped = Addressable::URI.encode_component path, Addressable::URI::CharacterClasses::PATH
52
52
  special_var = "${filename}"
53
53
  # Restore the unencoded `${filename}` variable, if present.
54
54
  if path.include? special_var