google-cloud-storage 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/google-cloud-storage.rb +124 -0
- data/lib/google/cloud/storage.rb +412 -0
- data/lib/google/cloud/storage/bucket.rb +783 -0
- data/lib/google/cloud/storage/bucket/acl.rb +815 -0
- data/lib/google/cloud/storage/bucket/cors.rb +157 -0
- data/lib/google/cloud/storage/bucket/list.rb +174 -0
- data/lib/google/cloud/storage/credentials.rb +31 -0
- data/lib/google/cloud/storage/errors.rb +67 -0
- data/lib/google/cloud/storage/file.rb +849 -0
- data/lib/google/cloud/storage/file/acl.rb +429 -0
- data/lib/google/cloud/storage/file/list.rb +193 -0
- data/lib/google/cloud/storage/file/verifier.rb +69 -0
- data/lib/google/cloud/storage/project.rb +321 -0
- data/lib/google/cloud/storage/service.rb +310 -0
- data/lib/google/cloud/storage/version.rb +22 -0
- metadata +215 -0
@@ -0,0 +1,783 @@
|
|
1
|
+
# Copyright 2014 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/storage/bucket/acl"
|
17
|
+
require "google/cloud/storage/bucket/list"
|
18
|
+
require "google/cloud/storage/bucket/cors"
|
19
|
+
require "google/cloud/storage/file"
|
20
|
+
require "pathname"
|
21
|
+
|
22
|
+
module Google
|
23
|
+
module Cloud
|
24
|
+
module Storage
|
25
|
+
##
|
26
|
+
# # Bucket
|
27
|
+
#
|
28
|
+
# Represents a Storage bucket. Belongs to a Project and has many Files.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# require "google/cloud"
|
32
|
+
#
|
33
|
+
# gcloud = Google::Cloud.new
|
34
|
+
# storage = gcloud.storage
|
35
|
+
#
|
36
|
+
# bucket = storage.bucket "my-bucket"
|
37
|
+
# file = bucket.file "path/to/my-file.ext"
|
38
|
+
#
|
39
|
+
class Bucket
|
40
|
+
##
|
41
|
+
# @private The Service object.
|
42
|
+
attr_accessor :service
|
43
|
+
|
44
|
+
##
|
45
|
+
# @private The Google API Client object.
|
46
|
+
attr_accessor :gapi
|
47
|
+
|
48
|
+
##
|
49
|
+
# @private Create an empty Bucket object.
|
50
|
+
def initialize
|
51
|
+
@service = nil
|
52
|
+
@gapi = Google::Apis::StorageV1::Bucket.new
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# The kind of item this is.
|
57
|
+
# For buckets, this is always `storage#bucket`.
|
58
|
+
def kind
|
59
|
+
@gapi.kind
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# The ID of the bucket.
|
64
|
+
def id
|
65
|
+
@gapi.id
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# The name of the bucket.
|
70
|
+
def name
|
71
|
+
@gapi.name
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# A URL that can be used to access the bucket using the REST API.
|
76
|
+
def api_url
|
77
|
+
@gapi.self_link
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Creation time of the bucket.
|
82
|
+
def created_at
|
83
|
+
@gapi.time_created
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Returns the current CORS configuration for a static website served
|
88
|
+
# from the bucket.
|
89
|
+
#
|
90
|
+
# The return value is a frozen (unmodifiable) array of hashes containing
|
91
|
+
# the attributes specified for the Bucket resource field
|
92
|
+
# [cors](https://cloud.google.com/storage/docs/json_api/v1/buckets#cors).
|
93
|
+
#
|
94
|
+
# This method also accepts a block for updating the bucket's CORS rules.
|
95
|
+
# See {Bucket::Cors} for details.
|
96
|
+
#
|
97
|
+
# @see https://cloud.google.com/storage/docs/cross-origin Cross-Origin
|
98
|
+
# Resource Sharing (CORS)
|
99
|
+
#
|
100
|
+
# @yield [cors] a block for setting CORS rules
|
101
|
+
# @yieldparam [Bucket::Cors] cors the object accepting CORS rules
|
102
|
+
#
|
103
|
+
# @example Retrieving the bucket's CORS rules.
|
104
|
+
# require "google/cloud"
|
105
|
+
#
|
106
|
+
# gcloud = Google::Cloud.new
|
107
|
+
# storage = gcloud.storage
|
108
|
+
#
|
109
|
+
# bucket = storage.bucket "my-todo-app"
|
110
|
+
# bucket.cors #=> [{"origin"=>["http://example.org"],
|
111
|
+
# # "method"=>["GET","POST","DELETE"],
|
112
|
+
# # "responseHeader"=>["X-My-Custom-Header"],
|
113
|
+
# # "maxAgeSeconds"=>3600}]
|
114
|
+
#
|
115
|
+
# @example Updating the bucket's CORS rules inside a block.
|
116
|
+
# require "google/cloud"
|
117
|
+
#
|
118
|
+
# gcloud = Google::Cloud.new
|
119
|
+
# storage = gcloud.storage
|
120
|
+
# bucket = storage.bucket "my-todo-app"
|
121
|
+
#
|
122
|
+
# bucket.update do |b|
|
123
|
+
# b.cors do |c|
|
124
|
+
# c.add_rule ["http://example.org", "https://example.org"],
|
125
|
+
# "*",
|
126
|
+
# response_headers: ["X-My-Custom-Header"],
|
127
|
+
# max_age: 3600
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
def cors
|
132
|
+
cors_builder = Bucket::Cors.from_gapi @gapi.cors_configurations
|
133
|
+
if block_given?
|
134
|
+
yield cors_builder
|
135
|
+
if cors_builder.changed?
|
136
|
+
@gapi.cors_configurations = cors_builder.to_gapi
|
137
|
+
patch_gapi! :cors_configurations
|
138
|
+
end
|
139
|
+
end
|
140
|
+
cors_builder.freeze # always return frozen objects
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# The location of the bucket.
|
145
|
+
# Object data for objects in the bucket resides in physical
|
146
|
+
# storage within this region. Defaults to US.
|
147
|
+
# See the developer's guide for the authoritative list.
|
148
|
+
#
|
149
|
+
# @see https://cloud.google.com/storage/docs/concepts-techniques
|
150
|
+
def location
|
151
|
+
@gapi.location
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# The destination bucket name for the bucket's logs.
|
156
|
+
#
|
157
|
+
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
158
|
+
#
|
159
|
+
def logging_bucket
|
160
|
+
@gapi.logging.log_bucket if @gapi.logging
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Updates the destination bucket for the bucket's logs.
|
165
|
+
#
|
166
|
+
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
167
|
+
#
|
168
|
+
# @param [String] logging_bucket The bucket to hold the logging output
|
169
|
+
#
|
170
|
+
def logging_bucket= logging_bucket
|
171
|
+
@gapi.logging ||= Google::Apis::StorageV1::Bucket::Logging.new
|
172
|
+
@gapi.logging.log_bucket = logging_bucket
|
173
|
+
patch_gapi! :logging
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# The logging object prefix for the bucket's logs. For more information,
|
178
|
+
#
|
179
|
+
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
180
|
+
#
|
181
|
+
def logging_prefix
|
182
|
+
@gapi.logging.log_object_prefix if @gapi.logging
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# Updates the logging object prefix. This prefix will be used to create
|
187
|
+
# log object names for the bucket. It can be at most 900 characters and
|
188
|
+
# must be a [valid object
|
189
|
+
# name](https://cloud.google.com/storage/docs/bucket-naming#objectnames).
|
190
|
+
# By default, the object prefix is the name of the bucket for which the
|
191
|
+
# logs are enabled.
|
192
|
+
#
|
193
|
+
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
194
|
+
#
|
195
|
+
def logging_prefix= logging_prefix
|
196
|
+
@gapi.logging ||= Google::Apis::StorageV1::Bucket::Logging.new
|
197
|
+
@gapi.logging.log_object_prefix = logging_prefix
|
198
|
+
patch_gapi! :logging
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# The bucket's storage class. This defines how objects in the bucket are
|
203
|
+
# stored and determines the SLA and the cost of storage. Values include
|
204
|
+
# `STANDARD`, `NEARLINE`, and `DURABLE_REDUCED_AVAILABILITY`.
|
205
|
+
def storage_class
|
206
|
+
@gapi.storage_class
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Whether [Object
|
211
|
+
# Versioning](https://cloud.google.com/storage/docs/object-versioning)
|
212
|
+
# is enabled for the bucket.
|
213
|
+
def versioning?
|
214
|
+
@gapi.versioning.enabled? unless @gapi.versioning.nil?
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Updates whether [Object
|
219
|
+
# Versioning](https://cloud.google.com/storage/docs/object-versioning)
|
220
|
+
# is enabled for the bucket.
|
221
|
+
#
|
222
|
+
# @return [Boolean]
|
223
|
+
#
|
224
|
+
def versioning= new_versioning
|
225
|
+
@gapi.versioning ||= Google::Apis::StorageV1::Bucket::Versioning.new
|
226
|
+
@gapi.versioning.enabled = new_versioning
|
227
|
+
patch_gapi! :versioning
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# The index page returned from a static website served from the bucket
|
232
|
+
# when a site visitor requests the top level directory.
|
233
|
+
#
|
234
|
+
# @see https://cloud.google.com/storage/docs/website-configuration#step4
|
235
|
+
# How to Host a Static Website
|
236
|
+
#
|
237
|
+
def website_main
|
238
|
+
@gapi.website.main_page_suffix if @gapi.website
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# Updates the index page returned from a static website served from the
|
243
|
+
# bucket when a site visitor requests the top level directory.
|
244
|
+
#
|
245
|
+
# @see https://cloud.google.com/storage/docs/website-configuration#step4
|
246
|
+
# How to Host a Static Website
|
247
|
+
#
|
248
|
+
def website_main= website_main
|
249
|
+
@gapi.website ||= Google::Apis::StorageV1::Bucket::Website.new
|
250
|
+
@gapi.website.main_page_suffix = website_main
|
251
|
+
patch_gapi! :website
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# The page returned from a static website served from the bucket when a
|
256
|
+
# site visitor requests a resource that does not exist.
|
257
|
+
#
|
258
|
+
# @see https://cloud.google.com/storage/docs/website-configuration#step4
|
259
|
+
# How to Host a Static Website
|
260
|
+
#
|
261
|
+
def website_404
|
262
|
+
@gapi.website.not_found_page if @gapi.website
|
263
|
+
end
|
264
|
+
|
265
|
+
##
|
266
|
+
# Updates the page returned from a static website served from the bucket
|
267
|
+
# when a site visitor requests a resource that does not exist.
|
268
|
+
#
|
269
|
+
# @see https://cloud.google.com/storage/docs/website-configuration#step4
|
270
|
+
# How to Host a Static Website
|
271
|
+
#
|
272
|
+
def website_404= website_404
|
273
|
+
@gapi.website ||= Google::Apis::StorageV1::Bucket::Website.new
|
274
|
+
@gapi.website.not_found_page = website_404
|
275
|
+
patch_gapi! :website
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# Updates the bucket with changes made in the given block in a single
|
280
|
+
# PATCH request. The following attributes may be set: {#cors},
|
281
|
+
# {#logging_bucket=}, {#logging_prefix=}, {#versioning=},
|
282
|
+
# {#website_main=}, and {#website_404=}. In addition, the #cors
|
283
|
+
# configuration accessible in the block is completely mutable and will
|
284
|
+
# be included in the request. (See {Bucket::Cors})
|
285
|
+
#
|
286
|
+
# @yield [bucket] a block yielding a delegate object for updating the
|
287
|
+
# file
|
288
|
+
#
|
289
|
+
# @example
|
290
|
+
# require "google/cloud"
|
291
|
+
#
|
292
|
+
# gcloud = Google::Cloud.new
|
293
|
+
# storage = gcloud.storage
|
294
|
+
#
|
295
|
+
# bucket = storage.bucket "my-bucket"
|
296
|
+
# bucket.update do |b|
|
297
|
+
# b.website_main = "index.html"
|
298
|
+
# b.website_404 = "not_found.html"
|
299
|
+
# b.cors[0]["method"] = ["GET","POST","DELETE"]
|
300
|
+
# b.cors[1]["responseHeader"] << "X-Another-Custom-Header"
|
301
|
+
# end
|
302
|
+
#
|
303
|
+
# @example New CORS rules can also be added in a nested block:
|
304
|
+
# require "google/cloud"
|
305
|
+
#
|
306
|
+
# gcloud = Google::Cloud.new
|
307
|
+
# storage = gcloud.storage
|
308
|
+
# bucket = storage.bucket "my-todo-app"
|
309
|
+
#
|
310
|
+
# bucket.update do |b|
|
311
|
+
# b.cors do |c|
|
312
|
+
# c.add_rule ["http://example.org", "https://example.org"],
|
313
|
+
# "*",
|
314
|
+
# response_headers: ["X-My-Custom-Header"],
|
315
|
+
# max_age: 300
|
316
|
+
# end
|
317
|
+
# end
|
318
|
+
#
|
319
|
+
def update
|
320
|
+
updater = Updater.new @gapi
|
321
|
+
yield updater
|
322
|
+
# Add check for mutable cors
|
323
|
+
updater.check_for_mutable_cors!
|
324
|
+
patch_gapi! updater.updates unless updater.updates.empty?
|
325
|
+
end
|
326
|
+
|
327
|
+
##
|
328
|
+
# Permanently deletes the bucket.
|
329
|
+
# The bucket must be empty before it can be deleted.
|
330
|
+
#
|
331
|
+
# The API call to delete the bucket may be retried under certain
|
332
|
+
# conditions. See {Google::Cloud#storage} to control this behavior.
|
333
|
+
#
|
334
|
+
# @return [Boolean] Returns `true` if the bucket was deleted.
|
335
|
+
#
|
336
|
+
# @example
|
337
|
+
# require "google/cloud"
|
338
|
+
#
|
339
|
+
# gcloud = Google::Cloud.new
|
340
|
+
# storage = gcloud.storage
|
341
|
+
#
|
342
|
+
# bucket = storage.bucket "my-bucket"
|
343
|
+
# bucket.delete
|
344
|
+
#
|
345
|
+
def delete
|
346
|
+
ensure_service!
|
347
|
+
service.delete_bucket name
|
348
|
+
true
|
349
|
+
end
|
350
|
+
|
351
|
+
##
|
352
|
+
# Retrieves a list of files matching the criteria.
|
353
|
+
#
|
354
|
+
# @param [String] prefix Filter results to files whose names begin with
|
355
|
+
# this prefix.
|
356
|
+
# @param [String] delimiter Returns results in a directory-like mode.
|
357
|
+
# `items` will contain only objects whose names, aside from the
|
358
|
+
# `prefix`, do not contain `delimiter`. Objects whose names, aside
|
359
|
+
# from the `prefix`, contain `delimiter` will have their name,
|
360
|
+
# truncated after the `delimiter`, returned in `prefixes`. Duplicate
|
361
|
+
# `prefixes` are omitted.
|
362
|
+
# @param [String] token A previously-returned page token representing
|
363
|
+
# part of the larger set of results to view.
|
364
|
+
# @param [Integer] max Maximum number of items plus prefixes to return.
|
365
|
+
# As duplicate prefixes are omitted, fewer total results may be
|
366
|
+
# returned than requested. The default value of this parameter is
|
367
|
+
# 1,000 items.
|
368
|
+
# @param [Boolean] versions If `true`, lists all versions of an object
|
369
|
+
# as distinct results. The default is `false`. For more information,
|
370
|
+
# see [Object Versioning
|
371
|
+
# ](https://cloud.google.com/storage/docs/object-versioning).
|
372
|
+
#
|
373
|
+
# @return [Array<Google::Cloud::Storage::File>] (See
|
374
|
+
# {Google::Cloud::Storage::File::List})
|
375
|
+
#
|
376
|
+
# @example
|
377
|
+
# require "google/cloud"
|
378
|
+
#
|
379
|
+
# gcloud = Google::Cloud.new
|
380
|
+
# storage = gcloud.storage
|
381
|
+
#
|
382
|
+
# bucket = storage.bucket "my-bucket"
|
383
|
+
# files = bucket.files
|
384
|
+
# files.each do |file|
|
385
|
+
# puts file.name
|
386
|
+
# end
|
387
|
+
#
|
388
|
+
# @example Retrieve all files: (See {File::List#all})
|
389
|
+
# require "google/cloud"
|
390
|
+
#
|
391
|
+
# gcloud = Google::Cloud.new
|
392
|
+
# storage = gcloud.storage
|
393
|
+
#
|
394
|
+
# bucket = storage.bucket "my-bucket"
|
395
|
+
# files = bucket.files
|
396
|
+
# files.all do |file|
|
397
|
+
# puts file.name
|
398
|
+
# end
|
399
|
+
#
|
400
|
+
def files prefix: nil, delimiter: nil, token: nil, max: nil,
|
401
|
+
versions: nil
|
402
|
+
ensure_service!
|
403
|
+
options = {
|
404
|
+
prefix: prefix,
|
405
|
+
delimiter: delimiter,
|
406
|
+
token: token,
|
407
|
+
max: max,
|
408
|
+
versions: versions
|
409
|
+
}
|
410
|
+
gapi = service.list_files name, options
|
411
|
+
File::List.from_gapi gapi, service, name, prefix, delimiter, max,
|
412
|
+
versions
|
413
|
+
end
|
414
|
+
alias_method :find_files, :files
|
415
|
+
|
416
|
+
##
|
417
|
+
# Retrieves a file matching the path.
|
418
|
+
#
|
419
|
+
# If a [customer-supplied encryption
|
420
|
+
# key](https://cloud.google.com/storage/docs/encryption#customer-supplied)
|
421
|
+
# was used with {#create_file}, the `encryption_key` and
|
422
|
+
# `encryption_key_sha256` options must be provided or else the file's
|
423
|
+
# CRC32C checksum and MD5 hash will not be returned.
|
424
|
+
#
|
425
|
+
# @param [String] path Name (path) of the file.
|
426
|
+
# @param [Integer] generation When present, selects a specific revision
|
427
|
+
# of this object. Default is the latest version.
|
428
|
+
# @param [String] encryption_key Optional. The customer-supplied,
|
429
|
+
# AES-256 encryption key used to encrypt the file, if one was provided
|
430
|
+
# to {#create_file}. Must be provided if `encryption_key_sha256` is
|
431
|
+
# provided.
|
432
|
+
# @param [String] encryption_key_sha256 Optional. The SHA256 hash of the
|
433
|
+
# customer-supplied, AES-256 encryption key used to encrypt the file,
|
434
|
+
# if one was provided to {#create_file}. Must be provided if
|
435
|
+
# `encryption_key` is provided.
|
436
|
+
#
|
437
|
+
# @return [Google::Cloud::Storage::File, nil] Returns nil if file does
|
438
|
+
# not exist
|
439
|
+
#
|
440
|
+
# @example
|
441
|
+
# require "google/cloud"
|
442
|
+
#
|
443
|
+
# gcloud = Google::Cloud.new
|
444
|
+
# storage = gcloud.storage
|
445
|
+
#
|
446
|
+
# bucket = storage.bucket "my-bucket"
|
447
|
+
#
|
448
|
+
# file = bucket.file "path/to/my-file.ext"
|
449
|
+
# puts file.name
|
450
|
+
#
|
451
|
+
def file path, generation: nil, encryption_key: nil,
|
452
|
+
encryption_key_sha256: nil
|
453
|
+
ensure_service!
|
454
|
+
options = { generation: generation, key: encryption_key,
|
455
|
+
key_sha256: encryption_key_sha256 }
|
456
|
+
gapi = service.get_file name, path, options
|
457
|
+
File.from_gapi gapi, service
|
458
|
+
rescue Google::Cloud::NotFoundError
|
459
|
+
nil
|
460
|
+
end
|
461
|
+
alias_method :find_file, :file
|
462
|
+
|
463
|
+
##
|
464
|
+
# Creates a new {File} object by providing a path to a local file to
|
465
|
+
# upload and the path to store it with in the bucket.
|
466
|
+
#
|
467
|
+
# #### Customer-supplied encryption keys
|
468
|
+
#
|
469
|
+
# By default, Google Cloud Storage manages server-side encryption keys
|
470
|
+
# on your behalf. However, a [customer-supplied encryption
|
471
|
+
# key](https://cloud.google.com/storage/docs/encryption#customer-supplied)
|
472
|
+
# can be provided with the `encryption_key` and `encryption_key_sha256`
|
473
|
+
# options. If given, the same key and SHA256 hash also must be provided
|
474
|
+
# to subsequently download or copy the file. If you use
|
475
|
+
# customer-supplied encryption keys, you must securely manage your keys
|
476
|
+
# and ensure that they are not lost. Also, please note that file
|
477
|
+
# metadata is not encrypted, with the exception of the CRC32C checksum
|
478
|
+
# and MD5 hash. The names of files and buckets are also not encrypted,
|
479
|
+
# and you can read or update the metadata of an encrypted file without
|
480
|
+
# providing the encryption key.
|
481
|
+
#
|
482
|
+
# @param [String] file Path of the file on the filesystem to upload.
|
483
|
+
# @param [String] path Path to store the file in Google Cloud Storage.
|
484
|
+
# @param [String] acl A predefined set of access controls to apply to
|
485
|
+
# this file.
|
486
|
+
#
|
487
|
+
# Acceptable values are:
|
488
|
+
#
|
489
|
+
# * `auth`, `auth_read`, `authenticated`, `authenticated_read`,
|
490
|
+
# `authenticatedRead` - File owner gets OWNER access, and
|
491
|
+
# allAuthenticatedUsers get READER access.
|
492
|
+
# * `owner_full`, `bucketOwnerFullControl` - File owner gets OWNER
|
493
|
+
# access, and project team owners get OWNER access.
|
494
|
+
# * `owner_read`, `bucketOwnerRead` - File owner gets OWNER access,
|
495
|
+
# and project team owners get READER access.
|
496
|
+
# * `private` - File owner gets OWNER access.
|
497
|
+
# * `project_private`, `projectPrivate` - File owner gets OWNER
|
498
|
+
# access, and project team members get access according to their
|
499
|
+
# roles.
|
500
|
+
# * `public`, `public_read`, `publicRead` - File owner gets OWNER
|
501
|
+
# access, and allUsers get READER access.
|
502
|
+
# @param [String] cache_control The
|
503
|
+
# [Cache-Control](https://tools.ietf.org/html/rfc7234#section-5.2)
|
504
|
+
# response header to be returned when the file is downloaded.
|
505
|
+
# @param [String] content_disposition The
|
506
|
+
# [Content-Disposition](https://tools.ietf.org/html/rfc6266)
|
507
|
+
# response header to be returned when the file is downloaded.
|
508
|
+
# @param [String] content_encoding The [Content-Encoding
|
509
|
+
# ](https://tools.ietf.org/html/rfc7231#section-3.1.2.2) response
|
510
|
+
# header to be returned when the file is downloaded.
|
511
|
+
# @param [String] content_language The
|
512
|
+
# [Content-Language](http://tools.ietf.org/html/bcp47) response
|
513
|
+
# header to be returned when the file is downloaded.
|
514
|
+
# @param [String] content_type The
|
515
|
+
# [Content-Type](https://tools.ietf.org/html/rfc2616#section-14.17)
|
516
|
+
# response header to be returned when the file is downloaded.
|
517
|
+
# @param [String] crc32c The CRC32c checksum of the file data, as
|
518
|
+
# described in [RFC 4960, Appendix
|
519
|
+
# B](http://tools.ietf.org/html/rfc4960#appendix-B).
|
520
|
+
# If provided, Cloud Storage will only create the file if the value
|
521
|
+
# matches the value calculated by the service. See
|
522
|
+
# [Validation](https://cloud.google.com/storage/docs/hashes-etags)
|
523
|
+
# for more information.
|
524
|
+
# @param [String] md5 The MD5 hash of the file data. If provided, Cloud
|
525
|
+
# Storage will only create the file if the value matches the value
|
526
|
+
# calculated by the service. See
|
527
|
+
# [Validation](https://cloud.google.com/storage/docs/hashes-etags) for
|
528
|
+
# more information.
|
529
|
+
# @param [Hash] metadata A hash of custom, user-provided web-safe keys
|
530
|
+
# and arbitrary string values that will returned with requests for the
|
531
|
+
# file as "x-goog-meta-" response headers.
|
532
|
+
# @param [String] encryption_key Optional. A customer-supplied, AES-256
|
533
|
+
# encryption key that will be used to encrypt the file. Must be
|
534
|
+
# provided if `encryption_key_sha256` is provided.
|
535
|
+
# @param [String] encryption_key_sha256 Optional. The SHA256 hash of the
|
536
|
+
# customer-supplied, AES-256 encryption key that will be used to
|
537
|
+
# encrypt the file. Must be provided if `encryption_key` is provided.
|
538
|
+
#
|
539
|
+
# @return [Google::Cloud::Storage::File]
|
540
|
+
#
|
541
|
+
# @example
|
542
|
+
# require "google/cloud"
|
543
|
+
#
|
544
|
+
# gcloud = Google::Cloud.new
|
545
|
+
# storage = gcloud.storage
|
546
|
+
#
|
547
|
+
# bucket = storage.bucket "my-bucket"
|
548
|
+
#
|
549
|
+
# bucket.create_file "path/to/local.file.ext"
|
550
|
+
#
|
551
|
+
# @example Specifying a destination path:
|
552
|
+
# require "google/cloud"
|
553
|
+
#
|
554
|
+
# gcloud = Google::Cloud.new
|
555
|
+
# storage = gcloud.storage
|
556
|
+
#
|
557
|
+
# bucket = storage.bucket "my-bucket"
|
558
|
+
#
|
559
|
+
# bucket.create_file "path/to/local.file.ext",
|
560
|
+
# "destination/path/file.ext"
|
561
|
+
#
|
562
|
+
# @example Providing a customer-supplied encryption key:
|
563
|
+
# require "google/cloud"
|
564
|
+
# require "digest/sha2"
|
565
|
+
#
|
566
|
+
# gcloud = Google::Cloud.new
|
567
|
+
# storage = gcloud.storage
|
568
|
+
# bucket = storage.bucket "my-bucket"
|
569
|
+
#
|
570
|
+
# # Key generation shown for example purposes only. Write your own.
|
571
|
+
# cipher = OpenSSL::Cipher.new "aes-256-cfb"
|
572
|
+
# cipher.encrypt
|
573
|
+
# key = cipher.random_key
|
574
|
+
# key_hash = Digest::SHA256.digest key
|
575
|
+
#
|
576
|
+
# bucket.create_file "path/to/local.file.ext",
|
577
|
+
# "destination/path/file.ext",
|
578
|
+
# encryption_key: key,
|
579
|
+
# encryption_key_sha256: key_hash
|
580
|
+
#
|
581
|
+
# # Store your key and hash securely for later use.
|
582
|
+
# file = bucket.file "destination/path/file.ext",
|
583
|
+
# encryption_key: key,
|
584
|
+
# encryption_key_sha256: key_hash
|
585
|
+
#
|
586
|
+
def create_file file, path = nil, acl: nil, cache_control: nil,
|
587
|
+
content_disposition: nil, content_encoding: nil,
|
588
|
+
content_language: nil, content_type: nil,
|
589
|
+
crc32c: nil, md5: nil, metadata: nil,
|
590
|
+
encryption_key: nil, encryption_key_sha256: nil
|
591
|
+
ensure_service!
|
592
|
+
options = { acl: File::Acl.predefined_rule_for(acl), md5: md5,
|
593
|
+
cache_control: cache_control, content_type: content_type,
|
594
|
+
content_disposition: content_disposition, crc32c: crc32c,
|
595
|
+
content_encoding: content_encoding,
|
596
|
+
content_language: content_language, metadata: metadata,
|
597
|
+
key: encryption_key, key_sha256: encryption_key_sha256 }
|
598
|
+
ensure_file_exists! file
|
599
|
+
# TODO: Handle file as an IO and path is missing more gracefully
|
600
|
+
path ||= Pathname(file).to_path
|
601
|
+
gapi = service.insert_file name, file, path, options
|
602
|
+
File.from_gapi gapi, service
|
603
|
+
end
|
604
|
+
alias_method :upload_file, :create_file
|
605
|
+
alias_method :new_file, :create_file
|
606
|
+
|
607
|
+
##
|
608
|
+
# The Bucket::Acl instance used to control access to the bucket.
|
609
|
+
#
|
610
|
+
# A bucket has owners, writers, and readers. Permissions can be granted
|
611
|
+
# to an individual user's email address, a group's email address, as
|
612
|
+
# well as many predefined lists.
|
613
|
+
#
|
614
|
+
# @see https://cloud.google.com/storage/docs/access-control Access
|
615
|
+
# Control guide
|
616
|
+
#
|
617
|
+
# @example Grant access to a user by prepending `"user-"` to an email:
|
618
|
+
# require "google/cloud"
|
619
|
+
#
|
620
|
+
# gcloud = Google::Cloud.new
|
621
|
+
# storage = gcloud.storage
|
622
|
+
#
|
623
|
+
# bucket = storage.bucket "my-todo-app"
|
624
|
+
#
|
625
|
+
# email = "heidi@example.net"
|
626
|
+
# bucket.acl.add_reader "user-#{email}"
|
627
|
+
#
|
628
|
+
# @example Grant access to a group by prepending `"group-"` to an email:
|
629
|
+
# require "google/cloud"
|
630
|
+
#
|
631
|
+
# gcloud = Google::Cloud.new
|
632
|
+
# storage = gcloud.storage
|
633
|
+
#
|
634
|
+
# bucket = storage.bucket "my-todo-app"
|
635
|
+
#
|
636
|
+
# email = "authors@example.net"
|
637
|
+
# bucket.acl.add_reader "group-#{email}"
|
638
|
+
#
|
639
|
+
# @example Or, grant access via a predefined permissions list:
|
640
|
+
# require "google/cloud"
|
641
|
+
#
|
642
|
+
# gcloud = Google::Cloud.new
|
643
|
+
# storage = gcloud.storage
|
644
|
+
#
|
645
|
+
# bucket = storage.bucket "my-todo-app"
|
646
|
+
#
|
647
|
+
# bucket.acl.public!
|
648
|
+
#
|
649
|
+
def acl
|
650
|
+
@acl ||= Bucket::Acl.new self
|
651
|
+
end
|
652
|
+
|
653
|
+
##
|
654
|
+
# The Bucket::DefaultAcl instance used to control access to the bucket's
|
655
|
+
# files.
|
656
|
+
#
|
657
|
+
# A bucket's files have owners, writers, and readers. Permissions can be
|
658
|
+
# granted to an individual user's email address, a group's email
|
659
|
+
# address, as well as many predefined lists.
|
660
|
+
#
|
661
|
+
# @see https://cloud.google.com/storage/docs/access-control Access
|
662
|
+
# Control guide
|
663
|
+
#
|
664
|
+
# @example Grant access to a user by prepending `"user-"` to an email:
|
665
|
+
# require "google/cloud"
|
666
|
+
#
|
667
|
+
# gcloud = Google::Cloud.new
|
668
|
+
# storage = gcloud.storage
|
669
|
+
#
|
670
|
+
# bucket = storage.bucket "my-todo-app"
|
671
|
+
#
|
672
|
+
# email = "heidi@example.net"
|
673
|
+
# bucket.default_acl.add_reader "user-#{email}"
|
674
|
+
#
|
675
|
+
# @example Grant access to a group by prepending `"group-"` to an email
|
676
|
+
# require "google/cloud"
|
677
|
+
#
|
678
|
+
# gcloud = Google::Cloud.new
|
679
|
+
# storage = gcloud.storage
|
680
|
+
#
|
681
|
+
# bucket = storage.bucket "my-todo-app"
|
682
|
+
#
|
683
|
+
# email = "authors@example.net"
|
684
|
+
# bucket.default_acl.add_reader "group-#{email}"
|
685
|
+
#
|
686
|
+
# @example Or, grant access via a predefined permissions list:
|
687
|
+
# require "google/cloud"
|
688
|
+
#
|
689
|
+
# gcloud = Google::Cloud.new
|
690
|
+
# storage = gcloud.storage
|
691
|
+
#
|
692
|
+
# bucket = storage.bucket "my-todo-app"
|
693
|
+
#
|
694
|
+
# bucket.default_acl.public!
|
695
|
+
#
|
696
|
+
def default_acl
|
697
|
+
@default_acl ||= Bucket::DefaultAcl.new self
|
698
|
+
end
|
699
|
+
|
700
|
+
##
|
701
|
+
# Reloads the bucket with current data from the Storage service.
|
702
|
+
def reload!
|
703
|
+
ensure_service!
|
704
|
+
@gapi = service.get_bucket name
|
705
|
+
end
|
706
|
+
alias_method :refresh!, :reload!
|
707
|
+
|
708
|
+
##
|
709
|
+
# @private New Bucket from a Google API Client object.
|
710
|
+
def self.from_gapi gapi, conn
|
711
|
+
new.tap do |f|
|
712
|
+
f.gapi = gapi
|
713
|
+
f.service = conn
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
protected
|
718
|
+
|
719
|
+
##
|
720
|
+
# Raise an error unless an active service is available.
|
721
|
+
def ensure_service!
|
722
|
+
fail "Must have active connection" unless service
|
723
|
+
end
|
724
|
+
|
725
|
+
def patch_gapi! *attributes
|
726
|
+
attributes.flatten!
|
727
|
+
return if attributes.empty?
|
728
|
+
ensure_service!
|
729
|
+
patch_args = Hash[attributes.map do |attr|
|
730
|
+
[attr, @gapi.send(attr)]
|
731
|
+
end]
|
732
|
+
patch_gapi = Google::Apis::StorageV1::Bucket.new patch_args
|
733
|
+
@gapi = service.patch_bucket name, patch_gapi
|
734
|
+
end
|
735
|
+
|
736
|
+
##
|
737
|
+
# Raise an error if the file is not found.
|
738
|
+
def ensure_file_exists! file
|
739
|
+
return if ::File.file? file
|
740
|
+
fail ArgumentError, "cannot find file #{file}"
|
741
|
+
end
|
742
|
+
|
743
|
+
##
|
744
|
+
# Yielded to a block to accumulate changes for a patch request.
|
745
|
+
class Updater < Bucket
|
746
|
+
attr_reader :updates
|
747
|
+
##
|
748
|
+
# Create an Updater object.
|
749
|
+
def initialize gapi
|
750
|
+
@updates = []
|
751
|
+
@gapi = gapi
|
752
|
+
@cors_builder = nil
|
753
|
+
end
|
754
|
+
|
755
|
+
def cors
|
756
|
+
# Same as Bucket#cors, but not frozen
|
757
|
+
@cors_builder ||= Bucket::Cors.from_gapi @gapi.cors_configurations
|
758
|
+
yield @cors_builder if block_given?
|
759
|
+
@cors_builder
|
760
|
+
end
|
761
|
+
|
762
|
+
##
|
763
|
+
# @private Make sure any cors changes are saved
|
764
|
+
def check_for_mutable_cors!
|
765
|
+
return if @cors_builder.nil?
|
766
|
+
return unless @cors_builder.changed?
|
767
|
+
@gapi.cors_configurations = @cors_builder.to_gapi
|
768
|
+
patch_gapi! :cors_configurations
|
769
|
+
end
|
770
|
+
|
771
|
+
protected
|
772
|
+
|
773
|
+
##
|
774
|
+
# Queue up all the updates instead of making them.
|
775
|
+
def patch_gapi! attribute
|
776
|
+
@updates << attribute
|
777
|
+
@updates.uniq!
|
778
|
+
end
|
779
|
+
end
|
780
|
+
end
|
781
|
+
end
|
782
|
+
end
|
783
|
+
end
|