google-cloud-storage 1.30.0 → 1.39.0

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