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.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +2 -1
- data/CHANGELOG.md +106 -0
- data/CONTRIBUTING.md +3 -4
- data/OVERVIEW.md +30 -0
- data/lib/google/cloud/storage/bucket/acl.rb +12 -14
- data/lib/google/cloud/storage/bucket/cors.rb +4 -1
- data/lib/google/cloud/storage/bucket/lifecycle.rb +99 -21
- data/lib/google/cloud/storage/bucket/list.rb +3 -3
- data/lib/google/cloud/storage/bucket.rb +421 -62
- data/lib/google/cloud/storage/credentials.rb +16 -14
- data/lib/google/cloud/storage/file/acl.rb +181 -20
- data/lib/google/cloud/storage/file/list.rb +3 -3
- data/lib/google/cloud/storage/file/signer_v2.rb +3 -5
- data/lib/google/cloud/storage/file/signer_v4.rb +12 -10
- data/lib/google/cloud/storage/file/verifier.rb +2 -2
- data/lib/google/cloud/storage/file.rb +223 -32
- data/lib/google/cloud/storage/hmac_key/list.rb +3 -3
- data/lib/google/cloud/storage/policy/binding.rb +5 -3
- data/lib/google/cloud/storage/policy/bindings.rb +2 -2
- data/lib/google/cloud/storage/policy/condition.rb +4 -2
- data/lib/google/cloud/storage/policy.rb +2 -2
- data/lib/google/cloud/storage/post_object.rb +2 -1
- data/lib/google/cloud/storage/project.rb +38 -18
- data/lib/google/cloud/storage/service.rb +352 -284
- data/lib/google/cloud/storage/version.rb +1 -1
- data/lib/google/cloud/storage.rb +66 -13
- data/lib/google-cloud-storage.rb +51 -7
- metadata +24 -18
@@ -38,17 +38,21 @@ module Google
|
|
38
38
|
|
39
39
|
##
|
40
40
|
# Creates a new Service instance.
|
41
|
-
|
42
|
-
|
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,
|
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
|
-
|
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,
|
110
|
-
|
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
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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,
|
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
|
-
|
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,
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
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
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
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,
|
323
|
-
|
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,
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
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
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
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,
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
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
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
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
|
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.
|
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,
|
400
|
-
|
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
|
-
|
405
|
-
|
406
|
-
|
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,
|
413
|
-
|
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
|
-
|
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
|
-
|
687
|
-
|
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
|