google-cloud-storage 1.45.0 → 1.56.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.
@@ -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
@@ -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)