google-cloud-storage 1.35.0 → 1.54.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.
@@ -15,6 +15,7 @@
15
15
 
16
16
  require "google/cloud/storage/version"
17
17
  require "google/apis/storage_v1"
18
+ require "google/cloud/config"
18
19
  require "digest"
19
20
  require "mini_mime"
20
21
  require "pathname"
@@ -36,11 +37,20 @@ module Google
36
37
  # @private
37
38
  attr_accessor :credentials
38
39
 
40
+ # @private
41
+ def universe_domain
42
+ service.universe_domain
43
+ end
44
+
39
45
  ##
40
46
  # Creates a new Service instance.
47
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
41
48
  def initialize project, credentials, retries: nil,
42
49
  timeout: nil, open_timeout: nil, read_timeout: nil,
43
- send_timeout: nil, host: nil, quota_project: nil
50
+ send_timeout: nil, host: nil, quota_project: nil,
51
+ max_elapsed_time: nil, base_interval: nil, max_interval: nil,
52
+ multiplier: nil, upload_chunk_size: nil, universe_domain: nil
53
+ host ||= Google::Cloud::Storage.configure.endpoint
44
54
  @project = project
45
55
  @credentials = credentials
46
56
  @service = API::StorageService.new
@@ -57,9 +67,23 @@ module Google
57
67
  "gl-ruby/#{RUBY_VERSION} gccl/#{Google::Cloud::Storage::VERSION}"
58
68
  @service.request_options.header["Accept-Encoding"] = "gzip"
59
69
  @service.request_options.quota_project = quota_project if quota_project
70
+ @service.request_options.max_elapsed_time = max_elapsed_time if max_elapsed_time
71
+ @service.request_options.base_interval = base_interval if base_interval
72
+ @service.request_options.max_interval = max_interval if max_interval
73
+ @service.request_options.multiplier = multiplier if multiplier
74
+ @service.request_options.add_invocation_id_header = true
75
+ @service.request_options.upload_chunk_size = upload_chunk_size if upload_chunk_size
60
76
  @service.authorization = @credentials.client if @credentials
61
77
  @service.root_url = host if host
78
+ @service.universe_domain = universe_domain || Google::Cloud::Storage.configure.universe_domain
79
+ begin
80
+ @service.verify_universe_domain!
81
+ rescue Google::Apis::UniverseDomainError => e
82
+ # TODO: Create a Google::Cloud::Error subclass for this.
83
+ raise Google::Cloud::Error, e.message
84
+ end
62
85
  end
86
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
63
87
 
64
88
  def service
65
89
  return mocked_service if mocked_service
@@ -73,11 +97,11 @@ module Google
73
97
 
74
98
  ##
75
99
  # Retrieves a list of buckets for the given project.
76
- def list_buckets prefix: nil, token: nil, max: nil, user_project: nil
100
+ def list_buckets prefix: nil, token: nil, max: nil, user_project: nil, options: {}
77
101
  execute do
78
102
  service.list_buckets \
79
103
  @project, prefix: prefix, page_token: token, max_results: max,
80
- user_project: user_project(user_project)
104
+ user_project: user_project(user_project), options: options
81
105
  end
82
106
  end
83
107
 
@@ -87,12 +111,14 @@ module Google
87
111
  def get_bucket bucket_name,
88
112
  if_metageneration_match: nil,
89
113
  if_metageneration_not_match: nil,
90
- user_project: nil
114
+ user_project: nil,
115
+ options: {}
91
116
  execute do
92
117
  service.get_bucket bucket_name,
93
118
  if_metageneration_match: if_metageneration_match,
94
119
  if_metageneration_not_match: if_metageneration_not_match,
95
- user_project: user_project(user_project)
120
+ user_project: user_project(user_project),
121
+ options: options
96
122
  end
97
123
  end
98
124
 
@@ -100,13 +126,16 @@ module Google
100
126
  # Creates a new bucket.
101
127
  # Returns Google::Apis::StorageV1::Bucket.
102
128
  def insert_bucket bucket_gapi, acl: nil, default_acl: nil,
103
- user_project: nil
129
+ user_project: nil, enable_object_retention: nil,
130
+ options: {}
104
131
  execute do
105
132
  service.insert_bucket \
106
133
  @project, bucket_gapi,
107
134
  predefined_acl: acl,
108
135
  predefined_default_object_acl: default_acl,
109
- user_project: user_project(user_project)
136
+ user_project: user_project(user_project),
137
+ options: options,
138
+ enable_object_retention: enable_object_retention
110
139
  end
111
140
  end
112
141
 
@@ -118,11 +147,17 @@ module Google
118
147
  predefined_default_acl: nil,
119
148
  if_metageneration_match: nil,
120
149
  if_metageneration_not_match: nil,
121
- user_project: nil
150
+ user_project: nil,
151
+ options: {}
122
152
  bucket_gapi ||= Google::Apis::StorageV1::Bucket.new
123
153
  bucket_gapi.acl = [] if predefined_acl
124
154
  bucket_gapi.default_object_acl = [] if predefined_default_acl
125
155
 
156
+ if options[:retries].nil?
157
+ is_idempotent = retry? if_metageneration_match: if_metageneration_match
158
+ options = is_idempotent ? {} : { retries: 0 }
159
+ end
160
+
126
161
  execute do
127
162
  service.patch_bucket bucket_name,
128
163
  bucket_gapi,
@@ -130,7 +165,8 @@ module Google
130
165
  predefined_default_object_acl: predefined_default_acl,
131
166
  if_metageneration_match: if_metageneration_match,
132
167
  if_metageneration_not_match: if_metageneration_not_match,
133
- user_project: user_project(user_project)
168
+ user_project: user_project(user_project),
169
+ options: options
134
170
  end
135
171
  end
136
172
 
@@ -139,119 +175,144 @@ module Google
139
175
  def delete_bucket bucket_name,
140
176
  if_metageneration_match: nil,
141
177
  if_metageneration_not_match: nil,
142
- user_project: nil
178
+ user_project: nil,
179
+ options: {}
143
180
  execute do
144
181
  service.delete_bucket bucket_name,
145
182
  if_metageneration_match: if_metageneration_match,
146
183
  if_metageneration_not_match: if_metageneration_not_match,
147
- user_project: user_project(user_project)
184
+ user_project: user_project(user_project),
185
+ options: options
148
186
  end
149
187
  end
150
188
 
151
189
  ##
152
190
  # Locks retention policy on a bucket.
153
191
  def lock_bucket_retention_policy bucket_name, metageneration,
154
- user_project: nil
192
+ user_project: nil,
193
+ options: {}
155
194
  execute do
156
195
  service.lock_bucket_retention_policy \
157
196
  bucket_name, metageneration,
158
- user_project: user_project(user_project)
197
+ user_project: user_project(user_project),
198
+ options: options
159
199
  end
160
200
  end
161
201
 
162
202
  ##
163
203
  # Retrieves a list of ACLs for the given bucket.
164
- def list_bucket_acls bucket_name, user_project: nil
204
+ def list_bucket_acls bucket_name, user_project: nil, options: {}
165
205
  execute do
166
206
  service.list_bucket_access_controls \
167
- bucket_name, user_project: user_project(user_project)
207
+ bucket_name, user_project: user_project(user_project),
208
+ options: options
168
209
  end
169
210
  end
170
211
 
171
212
  ##
172
213
  # Creates a new bucket ACL.
173
- def insert_bucket_acl bucket_name, entity, role, user_project: nil
214
+ def insert_bucket_acl bucket_name, entity, role, user_project: nil, options: {}
174
215
  params = { entity: entity, role: role }.delete_if { |_k, v| v.nil? }
175
216
  new_acl = Google::Apis::StorageV1::BucketAccessControl.new(**params)
217
+ if options[:retries].nil?
218
+ options = options.merge({ retries: 0 })
219
+ end
176
220
  execute do
177
221
  service.insert_bucket_access_control \
178
- bucket_name, new_acl, user_project: user_project(user_project)
222
+ bucket_name, new_acl, user_project: user_project(user_project),
223
+ options: options
179
224
  end
180
225
  end
181
226
 
182
227
  ##
183
228
  # Permanently deletes a bucket ACL.
184
- def delete_bucket_acl bucket_name, entity, user_project: nil
229
+ def delete_bucket_acl bucket_name, entity, user_project: nil, options: {}
230
+ if options[:retries].nil?
231
+ options = options.merge({ retries: 0 })
232
+ end
185
233
  execute do
186
234
  service.delete_bucket_access_control \
187
- bucket_name, entity, user_project: user_project(user_project)
235
+ bucket_name, entity, user_project: user_project(user_project),
236
+ options: options
188
237
  end
189
238
  end
190
239
 
191
240
  ##
192
241
  # Retrieves a list of default ACLs for the given bucket.
193
- def list_default_acls bucket_name, user_project: nil
242
+ def list_default_acls bucket_name, user_project: nil, options: {}
194
243
  execute do
195
244
  service.list_default_object_access_controls \
196
- bucket_name, user_project: user_project(user_project)
245
+ bucket_name, user_project: user_project(user_project),
246
+ options: options
197
247
  end
198
248
  end
199
249
 
200
250
  ##
201
251
  # Creates a new default ACL.
202
- def insert_default_acl bucket_name, entity, role, user_project: nil
252
+ def insert_default_acl bucket_name, entity, role, user_project: nil, options: {}
253
+ if options[:retries].nil?
254
+ options = options.merge({ retries: 0 })
255
+ end
203
256
  param = { entity: entity, role: role }.delete_if { |_k, v| v.nil? }
204
257
  new_acl = Google::Apis::StorageV1::ObjectAccessControl.new(**param)
205
258
  execute do
206
259
  service.insert_default_object_access_control \
207
- bucket_name, new_acl, user_project: user_project(user_project)
260
+ bucket_name, new_acl, user_project: user_project(user_project),
261
+ options: options
208
262
  end
209
263
  end
210
264
 
211
265
  ##
212
266
  # Permanently deletes a default ACL.
213
- def delete_default_acl bucket_name, entity, user_project: nil
267
+ def delete_default_acl bucket_name, entity, user_project: nil, options: {}
268
+ if options[:retries].nil?
269
+ options = options.merge({ retries: 0 })
270
+ end
214
271
  execute do
215
272
  service.delete_default_object_access_control \
216
- bucket_name, entity, user_project: user_project(user_project)
273
+ bucket_name, entity, user_project: user_project(user_project),
274
+ options: options
217
275
  end
218
276
  end
219
277
 
220
278
  ##
221
279
  # Returns Google::Apis::StorageV1::Policy
222
- def get_bucket_policy bucket_name, requested_policy_version: nil, user_project: nil
280
+ def get_bucket_policy bucket_name, requested_policy_version: nil, user_project: nil,
281
+ options: {}
223
282
  # get_bucket_iam_policy(bucket, fields: nil, quota_user: nil,
224
283
  # user_ip: nil, options: nil)
225
284
  execute do
226
285
  service.get_bucket_iam_policy bucket_name, options_requested_policy_version: requested_policy_version,
227
- user_project: user_project(user_project)
286
+ user_project: user_project(user_project), options: options
228
287
  end
229
288
  end
230
289
 
231
290
  ##
232
291
  # Returns Google::Apis::StorageV1::Policy
233
- def set_bucket_policy bucket_name, new_policy, user_project: nil
292
+ def set_bucket_policy bucket_name, new_policy, user_project: nil, options: {}
234
293
  execute do
235
294
  service.set_bucket_iam_policy \
236
- bucket_name, new_policy, user_project: user_project(user_project)
295
+ bucket_name, new_policy, user_project: user_project(user_project), options: options
237
296
  end
238
297
  end
239
298
 
240
299
  ##
241
300
  # Returns Google::Apis::StorageV1::TestIamPermissionsResponse
242
- def test_bucket_permissions bucket_name, permissions, user_project: nil
301
+ def test_bucket_permissions bucket_name, permissions, user_project: nil, options: {}
243
302
  execute do
244
303
  service.test_bucket_iam_permissions \
245
- bucket_name, permissions, user_project: user_project(user_project)
304
+ bucket_name, permissions, user_project: user_project(user_project),
305
+ options: options
246
306
  end
247
307
  end
248
308
 
249
309
  ##
250
310
  # Retrieves a list of Pub/Sub notification subscriptions for a bucket.
251
- def list_notifications bucket_name, user_project: nil
311
+ def list_notifications bucket_name, user_project: nil, options: {}
252
312
  execute do
253
313
  service.list_notifications bucket_name,
254
- user_project: user_project(user_project)
314
+ user_project: user_project(user_project),
315
+ options: options
255
316
  end
256
317
  end
257
318
 
@@ -259,7 +320,7 @@ module Google
259
320
  # Creates a new Pub/Sub notification subscription for a bucket.
260
321
  def insert_notification bucket_name, topic_name, custom_attrs: nil,
261
322
  event_types: nil, prefix: nil, payload: nil,
262
- user_project: nil
323
+ user_project: nil, options: {}
263
324
  params =
264
325
  { custom_attributes: custom_attrs,
265
326
  event_types: event_types(event_types),
@@ -268,41 +329,54 @@ module Google
268
329
  topic: topic_path(topic_name) }.delete_if { |_k, v| v.nil? }
269
330
  new_notification = Google::Apis::StorageV1::Notification.new(**params)
270
331
 
332
+ if options[:retries].nil?
333
+ options = options.merge({ retries: 0 })
334
+ end
335
+
271
336
  execute do
272
337
  service.insert_notification \
273
338
  bucket_name, new_notification,
274
- user_project: user_project(user_project)
339
+ user_project: user_project(user_project),
340
+ options: options
275
341
  end
276
342
  end
277
343
 
278
344
  ##
279
345
  # Retrieves a Pub/Sub notification subscription for a bucket.
280
- def get_notification bucket_name, notification_id, user_project: nil
346
+ def get_notification bucket_name, notification_id, user_project: nil, options: {}
281
347
  execute do
282
348
  service.get_notification bucket_name, notification_id,
283
- user_project: user_project(user_project)
349
+ user_project: user_project(user_project),
350
+ options: options
284
351
  end
285
352
  end
286
353
 
287
354
  ##
288
355
  # Deletes a new Pub/Sub notification subscription for a bucket.
289
- def delete_notification bucket_name, notification_id, user_project: nil
356
+ def delete_notification bucket_name, notification_id, user_project: nil, options: {}
290
357
  execute do
291
358
  service.delete_notification bucket_name, notification_id,
292
- user_project: user_project(user_project)
359
+ user_project: user_project(user_project),
360
+ options: options
293
361
  end
294
362
  end
295
363
 
296
364
  ##
297
365
  # Retrieves a list of files matching the criteria.
298
366
  def list_files bucket_name, delimiter: nil, max: nil, token: nil,
299
- prefix: nil, versions: nil, user_project: nil
367
+ prefix: nil, versions: nil, user_project: nil,
368
+ match_glob: nil, include_folders_as_prefixes: nil,
369
+ soft_deleted: nil, options: {}
300
370
  execute do
301
371
  service.list_objects \
302
372
  bucket_name, delimiter: delimiter, max_results: max,
303
373
  page_token: token, prefix: prefix,
304
374
  versions: versions,
305
- user_project: user_project(user_project)
375
+ user_project: user_project(user_project),
376
+ match_glob: match_glob,
377
+ include_folders_as_prefixes: include_folders_as_prefixes,
378
+ soft_deleted: soft_deleted,
379
+ options: options
306
380
  end
307
381
  end
308
382
 
@@ -330,7 +404,8 @@ module Google
330
404
  if_generation_not_match: nil,
331
405
  if_metageneration_match: nil,
332
406
  if_metageneration_not_match: nil,
333
- user_project: nil
407
+ user_project: nil,
408
+ options: {}
334
409
  params = {
335
410
  cache_control: cache_control,
336
411
  content_type: content_type,
@@ -348,6 +423,13 @@ module Google
348
423
  file_obj = Google::Apis::StorageV1::Object.new(**params)
349
424
  content_type ||= mime_type_for(path || Pathname(source).to_path)
350
425
 
426
+ if options[:retries].nil?
427
+ is_idempotent = retry? if_generation_match: if_generation_match
428
+ options = is_idempotent ? key_options(key) : key_options(key).merge(retries: 0)
429
+ else
430
+ options = key_options(key).merge options
431
+ end
432
+
351
433
  execute do
352
434
  service.insert_object bucket_name,
353
435
  file_obj,
@@ -362,7 +444,7 @@ module Google
362
444
  if_metageneration_not_match: if_metageneration_not_match,
363
445
  kms_key_name: kms_key,
364
446
  user_project: user_project(user_project),
365
- options: key_options(key)
447
+ options: options
366
448
  end
367
449
  end
368
450
 
@@ -376,7 +458,9 @@ module Google
376
458
  if_metageneration_match: nil,
377
459
  if_metageneration_not_match: nil,
378
460
  key: nil,
379
- user_project: nil
461
+ user_project: nil,
462
+ soft_deleted: nil,
463
+ options: {}
380
464
  execute do
381
465
  service.get_object \
382
466
  bucket_name, file_path,
@@ -386,7 +470,8 @@ module Google
386
470
  if_metageneration_match: if_metageneration_match,
387
471
  if_metageneration_not_match: if_metageneration_not_match,
388
472
  user_project: user_project(user_project),
389
- options: key_options(key)
473
+ soft_deleted: soft_deleted,
474
+ options: key_options(key).merge(options)
390
475
  end
391
476
  end
392
477
 
@@ -411,8 +496,17 @@ module Google
411
496
  if_source_metageneration_match: nil,
412
497
  if_source_metageneration_not_match: nil,
413
498
  token: nil,
414
- user_project: nil
499
+ user_project: nil,
500
+ options: {}
415
501
  key_options = rewrite_key_options source_key, destination_key
502
+
503
+ if options[:retries].nil?
504
+ is_idempotent = retry? if_generation_match: if_generation_match
505
+ options = is_idempotent ? key_options : key_options.merge(retries: 0)
506
+ else
507
+ options = key_options.merge options
508
+ end
509
+
416
510
  execute do
417
511
  service.rewrite_object source_bucket_name,
418
512
  source_file_path,
@@ -432,7 +526,7 @@ module Google
432
526
  if_source_metageneration_not_match: if_source_metageneration_not_match,
433
527
  rewrite_token: token,
434
528
  user_project: user_project(user_project),
435
- options: key_options
529
+ options: options
436
530
  end
437
531
  end
438
532
 
@@ -447,12 +541,19 @@ module Google
447
541
  if_source_generation_match: nil,
448
542
  if_generation_match: nil,
449
543
  if_metageneration_match: nil,
450
- user_project: nil
451
-
544
+ user_project: nil,
545
+ options: {}
452
546
  source_objects = compose_file_source_objects source_files, if_source_generation_match
453
547
  compose_req = Google::Apis::StorageV1::ComposeRequest.new source_objects: source_objects,
454
548
  destination: destination_gapi
455
549
 
550
+ if options[:retries].nil?
551
+ is_idempotent = retry? if_generation_match: if_generation_match
552
+ options = is_idempotent ? key_options(key) : key_options(key).merge(retries: 0)
553
+ else
554
+ options = key_options.merge options
555
+ end
556
+
456
557
  execute do
457
558
  service.compose_object bucket_name,
458
559
  destination_path,
@@ -461,7 +562,7 @@ module Google
461
562
  if_generation_match: if_generation_match,
462
563
  if_metageneration_match: if_metageneration_match,
463
564
  user_project: user_project(user_project),
464
- options: key_options(key)
565
+ options: options
465
566
  end
466
567
  end
467
568
 
@@ -475,12 +576,12 @@ module Google
475
576
  # Apis::StorageV1::StorageService and Apis::Core::DownloadCommand at
476
577
  # the end of this file.
477
578
  def download_file bucket_name, file_path, target_path, generation: nil,
478
- key: nil, range: nil, user_project: nil
479
- options = key_options key
579
+ key: nil, range: nil, user_project: nil, options: {}
580
+ options = key_options(key).merge(options)
480
581
  options = range_header options, range
481
582
 
482
583
  execute do
483
- service.get_object_with_response \
584
+ service.get_object \
484
585
  bucket_name, file_path,
485
586
  download_dest: target_path, generation: generation,
486
587
  user_project: user_project(user_project),
@@ -499,8 +600,16 @@ module Google
499
600
  if_metageneration_match: nil,
500
601
  if_metageneration_not_match: nil,
501
602
  predefined_acl: nil,
502
- user_project: nil
603
+ user_project: nil,
604
+ override_unlocked_retention: nil,
605
+ options: {}
503
606
  file_gapi ||= Google::Apis::StorageV1::Object.new
607
+
608
+ if options[:retries].nil?
609
+ is_idempotent = retry? if_metageneration_match: if_metageneration_match
610
+ options = is_idempotent ? {} : { retries: 0 }
611
+ end
612
+
504
613
  execute do
505
614
  service.patch_object bucket_name,
506
615
  file_path,
@@ -511,7 +620,9 @@ module Google
511
620
  if_metageneration_match: if_metageneration_match,
512
621
  if_metageneration_not_match: if_metageneration_not_match,
513
622
  predefined_acl: predefined_acl,
514
- user_project: user_project(user_project)
623
+ user_project: user_project(user_project),
624
+ override_unlocked_retention: override_unlocked_retention,
625
+ options: options
515
626
  end
516
627
  end
517
628
 
@@ -524,7 +635,13 @@ module Google
524
635
  if_generation_not_match: nil,
525
636
  if_metageneration_match: nil,
526
637
  if_metageneration_not_match: nil,
527
- user_project: nil
638
+ user_project: nil,
639
+ options: {}
640
+ if options[:retries].nil?
641
+ is_idempotent = retry? generation: generation, if_generation_match: if_generation_match
642
+ options = is_idempotent ? {} : { retries: 0 }
643
+ end
644
+
528
645
  execute do
529
646
  service.delete_object bucket_name, file_path,
530
647
  generation: generation,
@@ -532,40 +649,84 @@ module Google
532
649
  if_generation_not_match: if_generation_not_match,
533
650
  if_metageneration_match: if_metageneration_match,
534
651
  if_metageneration_not_match: if_metageneration_not_match,
535
- user_project: user_project(user_project)
652
+ user_project: user_project(user_project),
653
+ options: options
654
+ end
655
+ end
656
+
657
+ ##
658
+ # Restores a soft-deleted object.
659
+ def restore_file bucket_name,
660
+ file_path,
661
+ generation,
662
+ copy_source_acl: nil,
663
+ if_generation_match: nil,
664
+ if_generation_not_match: nil,
665
+ if_metageneration_match: nil,
666
+ if_metageneration_not_match: nil,
667
+ projection: nil,
668
+ user_project: nil,
669
+ fields: nil,
670
+ options: {}
671
+ if options[:retries].nil?
672
+ is_idempotent = retry? generation: generation, if_generation_match: if_generation_match
673
+ options = is_idempotent ? {} : { retries: 0 }
674
+ end
675
+
676
+ execute do
677
+ service.restore_object bucket_name, file_path, generation,
678
+ copy_source_acl: copy_source_acl,
679
+ if_generation_match: if_generation_match,
680
+ if_generation_not_match: if_generation_not_match,
681
+ if_metageneration_match: if_metageneration_match,
682
+ if_metageneration_not_match: if_metageneration_not_match,
683
+ projection: projection,
684
+ user_project: user_project(user_project),
685
+ fields: fields,
686
+ options: options
536
687
  end
537
688
  end
538
689
 
539
690
  ##
540
691
  # Retrieves a list of ACLs for the given file.
541
- def list_file_acls bucket_name, file_name, user_project: nil
692
+ def list_file_acls bucket_name, file_name, user_project: nil, options: {}
542
693
  execute do
543
694
  service.list_object_access_controls \
544
- bucket_name, file_name, user_project: user_project(user_project)
695
+ bucket_name, file_name, user_project: user_project(user_project),
696
+ options: options
545
697
  end
546
698
  end
547
699
 
548
700
  ##
549
701
  # Creates a new file ACL.
550
702
  def insert_file_acl bucket_name, file_name, entity, role,
551
- generation: nil, user_project: nil
703
+ generation: nil, user_project: nil,
704
+ options: {}
705
+ if options[:retries].nil?
706
+ options = options.merge({ retries: 0 })
707
+ end
552
708
  params = { entity: entity, role: role }.delete_if { |_k, v| v.nil? }
553
709
  new_acl = Google::Apis::StorageV1::ObjectAccessControl.new(**params)
554
710
  execute do
555
711
  service.insert_object_access_control \
556
712
  bucket_name, file_name, new_acl,
557
- generation: generation, user_project: user_project(user_project)
713
+ generation: generation, user_project: user_project(user_project),
714
+ options: options
558
715
  end
559
716
  end
560
717
 
561
718
  ##
562
719
  # Permanently deletes a file ACL.
563
720
  def delete_file_acl bucket_name, file_name, entity, generation: nil,
564
- user_project: nil
721
+ user_project: nil, options: {}
722
+ if options[:retries].nil?
723
+ options = options.merge({ retries: 0 })
724
+ end
565
725
  execute do
566
726
  service.delete_object_access_control \
567
727
  bucket_name, file_name, entity,
568
- generation: generation, user_project: user_project(user_project)
728
+ generation: generation, user_project: user_project(user_project),
729
+ options: options
569
730
  end
570
731
  end
571
732
 
@@ -573,32 +734,41 @@ module Google
573
734
  # Creates a new HMAC key for the specified service account.
574
735
  # Returns Google::Apis::StorageV1::HmacKey.
575
736
  def create_hmac_key service_account_email, project_id: nil,
576
- user_project: nil
737
+ user_project: nil, options: {}
738
+ if options[:retries].nil?
739
+ options = options.merge({ retries: 0 })
740
+ end
741
+
577
742
  execute do
578
743
  service.create_project_hmac_key \
579
744
  (project_id || @project), service_account_email,
580
- user_project: user_project(user_project)
745
+ user_project: user_project(user_project),
746
+ options: options
581
747
  end
582
748
  end
583
749
 
584
750
  ##
585
751
  # Deletes an HMAC key. Key must be in the INACTIVE state.
586
- def delete_hmac_key access_id, project_id: nil, user_project: nil
752
+ def delete_hmac_key access_id, project_id: nil, user_project: nil,
753
+ options: {}
587
754
  execute do
588
755
  service.delete_project_hmac_key \
589
756
  (project_id || @project), access_id,
590
- user_project: user_project(user_project)
757
+ user_project: user_project(user_project),
758
+ options: options
591
759
  end
592
760
  end
593
761
 
594
762
  ##
595
763
  # Retrieves an HMAC key's metadata.
596
764
  # Returns Google::Apis::StorageV1::HmacKeyMetadata.
597
- def get_hmac_key access_id, project_id: nil, user_project: nil
765
+ def get_hmac_key access_id, project_id: nil, user_project: nil,
766
+ options: {}
598
767
  execute do
599
768
  service.get_project_hmac_key \
600
769
  (project_id || @project), access_id,
601
- user_project: user_project(user_project)
770
+ user_project: user_project(user_project),
771
+ options: options
602
772
  end
603
773
  end
604
774
 
@@ -607,14 +777,15 @@ module Google
607
777
  # Returns Google::Apis::StorageV1::HmacKeysMetadata.
608
778
  def list_hmac_keys max: nil, token: nil, service_account_email: nil,
609
779
  project_id: nil, show_deleted_keys: nil,
610
- user_project: nil
780
+ user_project: nil, options: {}
611
781
  execute do
612
782
  service.list_project_hmac_keys \
613
783
  (project_id || @project),
614
784
  max_results: max, page_token: token,
615
785
  service_account_email: service_account_email,
616
786
  show_deleted_keys: show_deleted_keys,
617
- user_project: user_project(user_project)
787
+ user_project: user_project(user_project),
788
+ options: options
618
789
  end
619
790
  end
620
791
 
@@ -623,11 +794,44 @@ module Google
623
794
  # for valid states.
624
795
  # Returns Google::Apis::StorageV1::HmacKeyMetadata.
625
796
  def update_hmac_key access_id, hmac_key_metadata_object,
626
- project_id: nil, user_project: nil
797
+ project_id: nil, user_project: nil,
798
+ options: {}
627
799
  execute do
628
800
  service.update_project_hmac_key \
629
801
  (project_id || @project), access_id, hmac_key_metadata_object,
630
- user_project: user_project(user_project)
802
+ user_project: user_project(user_project),
803
+ options: options
804
+ end
805
+ end
806
+
807
+ ##
808
+ # Updates a bucket, including its ACL metadata.
809
+ def update_bucket bucket_name,
810
+ bucket_gapi = nil,
811
+ predefined_acl: nil,
812
+ predefined_default_acl: nil,
813
+ if_metageneration_match: nil,
814
+ if_metageneration_not_match: nil,
815
+ user_project: nil,
816
+ options: {}
817
+ bucket_gapi ||= Google::Apis::StorageV1::Bucket.new
818
+ bucket_gapi.acl = [] if predefined_acl
819
+ bucket_gapi.default_object_acl = [] if predefined_default_acl
820
+
821
+ if options[:retries].nil?
822
+ is_idempotent = retry? if_metageneration_match: if_metageneration_match
823
+ options = is_idempotent ? {} : { retries: 0 }
824
+ end
825
+
826
+ execute do
827
+ service.update_bucket bucket_name,
828
+ bucket_gapi,
829
+ predefined_acl: predefined_acl,
830
+ predefined_default_object_acl: predefined_default_acl,
831
+ if_metageneration_match: if_metageneration_match,
832
+ if_metageneration_not_match: if_metageneration_not_match,
833
+ user_project: user_project(user_project),
834
+ options: options
631
835
  end
632
836
  end
633
837
 
@@ -645,6 +849,18 @@ module Google
645
849
  "#{self.class}(#{@project})"
646
850
  end
647
851
 
852
+ ##
853
+ # Add custom Google extension headers to the requests that use the signed URLs.
854
+ def add_custom_headers headers
855
+ @service.request_options.header.merge! headers
856
+ end
857
+
858
+ ##
859
+ # Add custom Google extension header to the requests that use the signed URLs.
860
+ def add_custom_header header_name, header_value
861
+ @service.request_options.header[header_name] = header_value
862
+ end
863
+
648
864
  protected
649
865
 
650
866
  def user_project user_project
@@ -763,163 +979,11 @@ module Google
763
979
  rescue Google::Apis::Error => e
764
980
  raise Google::Cloud::Error.from_error(e)
765
981
  end
766
- end
767
- end
768
- end
769
-
770
- # rubocop:disable all
771
-
772
- # @private
773
- #
774
- # IMPORTANT: These monkey-patches of Apis::StorageV1::StorageService and
775
- # Apis::Core::DownloadCommand must be verified and updated (if needed) for
776
- # every upgrade of google-api-client.
777
- #
778
- # The purpose of these modifications is to provide access to response headers
779
- # (in particular, the Content-Encoding header) for the #download_file method,
780
- # above. If google-api-client is modified to expose response headers to its
781
- # clients, this code should be removed, and #download_file updated to use that
782
- # solution instead.
783
- #
784
- module Apis
785
- # @private
786
- module StorageV1
787
- # @private
788
- class StorageService
789
- # Returns a two-element array containing:
790
- # * The `result` that is the usual return type of #get_object.
791
- # * The `http_resp` from DownloadCommand#execute_once.
792
- def get_object_with_response(bucket, object, generation: nil, if_generation_match: nil, if_generation_not_match: nil, if_metageneration_match: nil, if_metageneration_not_match: nil, projection: nil, user_project: nil, fields: nil, quota_user: nil, user_ip: nil, download_dest: nil, options: nil, &block)
793
- if download_dest.nil?
794
- command = make_simple_command(:get, 'b/{bucket}/o/{object}', options)
795
- else
796
- command = make_download_command(:get, 'b/{bucket}/o/{object}', options)
797
- command.download_dest = download_dest
798
- end
799
- command.response_representation = Google::Apis::StorageV1::Object::Representation
800
- command.response_class = Google::Apis::StorageV1::Object
801
- command.params['bucket'] = bucket unless bucket.nil?
802
- command.params['object'] = object unless object.nil?
803
- command.query['generation'] = generation unless generation.nil?
804
- command.query['ifGenerationMatch'] = if_generation_match unless if_generation_match.nil?
805
- command.query['ifGenerationNotMatch'] = if_generation_not_match unless if_generation_not_match.nil?
806
- command.query['ifMetagenerationMatch'] = if_metageneration_match unless if_metageneration_match.nil?
807
- command.query['ifMetagenerationNotMatch'] = if_metageneration_not_match unless if_metageneration_not_match.nil?
808
- command.query['projection'] = projection unless projection.nil?
809
- command.query['userProject'] = user_project unless user_project.nil?
810
- command.query['fields'] = fields unless fields.nil?
811
- command.query['quotaUser'] = quota_user unless quota_user.nil?
812
- command.query['userIp'] = user_ip unless user_ip.nil?
813
- execute_or_queue_command_with_response(command, &block)
814
- end
815
-
816
- # Returns a two-element array containing:
817
- # * The `result` that is the usual return type of #execute_or_queue_command.
818
- # * The `http_resp` from DownloadCommand#execute_once.
819
- def execute_or_queue_command_with_response(command, &callback)
820
- batch_command = current_batch
821
- if batch_command
822
- raise "Can not combine services in a batch" if Thread.current[:google_api_batch_service] != self
823
- batch_command.add(command, &callback)
824
- nil
825
- else
826
- command.execute_with_response(client, &callback)
827
- end
828
- end
829
- end
830
- end
831
- # @private
832
- module Core
833
- # @private
834
- # Streaming/resumable media download support
835
- class DownloadCommand < ApiCommand
836
- # Returns a two-element array containing:
837
- # * The `result` that is the usual return type of #execute.
838
- # * The `http_resp` from #execute_once.
839
- def execute_with_response(client)
840
- prepare!
841
- begin
842
- Retriable.retriable tries: options.retries + 1,
843
- base_interval: 1,
844
- multiplier: 2,
845
- on: RETRIABLE_ERRORS do |try|
846
- # This 2nd level retriable only catches auth errors, and supports 1 retry, which allows
847
- # auth to be re-attempted without having to retry all sorts of other failures like
848
- # NotFound, etc
849
- auth_tries = (try == 1 && authorization_refreshable? ? 2 : 1)
850
- Retriable.retriable tries: auth_tries,
851
- on: [Google::Apis::AuthorizationError, Signet::AuthorizationError],
852
- on_retry: proc { |*| refresh_authorization } do
853
- execute_once_with_response(client).tap do |result|
854
- if block_given?
855
- yield result, nil
856
- end
857
- end
858
- end
859
- end
860
- rescue => e
861
- if block_given?
862
- yield nil, e
863
- else
864
- raise e
865
- end
866
- end
867
- ensure
868
- release!
869
- end
870
-
871
- # Returns a two-element array containing:
872
- # * The `result` that is the usual return type of #execute_once.
873
- # * The `http_resp`.
874
- def execute_once_with_response(client, &block)
875
- request_header = header.dup
876
- apply_request_options(request_header)
877
- download_offset = nil
878
-
879
- if @offset > 0
880
- logger.debug { sprintf('Resuming download from offset %d', @offset) }
881
- request_header[RANGE_HEADER] = sprintf('bytes=%d-', @offset)
882
- end
883
-
884
- http_res = client.get(url.to_s,
885
- query: query,
886
- header: request_header,
887
- follow_redirect: true) do |res, chunk|
888
- status = res.http_header.status_code.to_i
889
- next unless OK_STATUS.include?(status)
890
-
891
- download_offset ||= (status == 206 ? @offset : 0)
892
- download_offset += chunk.bytesize
893
-
894
- if download_offset - chunk.bytesize == @offset
895
- next_chunk = chunk
896
- else
897
- # Oh no! Requested a chunk, but received the entire content
898
- chunk_index = @offset - (download_offset - chunk.bytesize)
899
- next_chunk = chunk.byteslice(chunk_index..-1)
900
- next if next_chunk.nil?
901
- end
902
- # logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
903
- @download_io.write(next_chunk)
904
-
905
- @offset += next_chunk.bytesize
906
- end
907
-
908
- @download_io.flush
909
982
 
910
- if @close_io_on_finish
911
- result = nil
912
- else
913
- result = @download_io
914
- end
915
- check_status(http_res.status.to_i, http_res.header, http_res.body)
916
- success([result, http_res], &block)
917
- rescue => e
918
- @download_io.flush
919
- error(e, rethrow: true, &block)
983
+ def retry? query_params
984
+ query_params.any? { |_key, val| !val.nil? }
920
985
  end
921
986
  end
922
987
  end
923
988
  end
924
- # rubocop:enable all
925
989
  end