google-cloud-storage 1.35.0 → 1.54.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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