gcloud 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +21 -0
- data/lib/gcloud/bigquery/dataset.rb +1 -1
- data/lib/gcloud/bigquery/table.rb +1 -1
- data/lib/gcloud/bigquery/view.rb +1 -1
- data/lib/gcloud/storage/bucket.rb +305 -36
- data/lib/gcloud/storage/bucket/acl.rb +24 -6
- data/lib/gcloud/storage/bucket/cors.rb +112 -0
- data/lib/gcloud/storage/connection.rb +134 -73
- data/lib/gcloud/storage/file.rb +246 -6
- data/lib/gcloud/storage/file/acl.rb +12 -3
- data/lib/gcloud/storage/project.rb +89 -5
- data/lib/gcloud/version.rb +1 -1
- metadata +3 -2
data/lib/gcloud/storage/file.rb
CHANGED
@@ -22,7 +22,16 @@ module Gcloud
|
|
22
22
|
##
|
23
23
|
# = File
|
24
24
|
#
|
25
|
-
# Represents
|
25
|
+
# Represents a File
|
26
|
+
# ({Object}[https://cloud.google.com/storage/docs/json_api/v1/objects]) that
|
27
|
+
# belongs to a Bucket. Files (Objects) are
|
28
|
+
# the individual pieces of data that you store in Google Cloud Storage. A
|
29
|
+
# file can be up to 5 TB in size. Files have two components:
|
30
|
+
# data and metadata. The data component is the data from an external file or
|
31
|
+
# other data source that you want to store in Google Cloud Storage. The
|
32
|
+
# metadata component is a collection of name-value pairs that describe
|
33
|
+
# various qualities of the data. For more information, see {Concepts and
|
34
|
+
# Techniques}[https://cloud.google.com/storage/docs/concepts-techniques].
|
26
35
|
#
|
27
36
|
# require "gcloud"
|
28
37
|
#
|
@@ -92,17 +101,29 @@ module Gcloud
|
|
92
101
|
end
|
93
102
|
|
94
103
|
##
|
95
|
-
#
|
96
|
-
def
|
104
|
+
# A URL that can be used to access the file using the REST API.
|
105
|
+
def api_url
|
97
106
|
@gapi["selfLink"]
|
98
107
|
end
|
99
108
|
|
109
|
+
##
|
110
|
+
# A URL that can be used to download the file using the REST API.
|
111
|
+
def media_url
|
112
|
+
@gapi["mediaLink"]
|
113
|
+
end
|
114
|
+
|
100
115
|
##
|
101
116
|
# Content-Length of the data in bytes.
|
102
117
|
def size
|
103
118
|
@gapi["size"]
|
104
119
|
end
|
105
120
|
|
121
|
+
##
|
122
|
+
# Creation time of the file.
|
123
|
+
def created_at
|
124
|
+
@gapi["timeCreated"]
|
125
|
+
end
|
126
|
+
|
106
127
|
##
|
107
128
|
# The creation or modification time of the file.
|
108
129
|
# For buckets with versioning enabled, changing an object's
|
@@ -118,8 +139,9 @@ module Gcloud
|
|
118
139
|
end
|
119
140
|
|
120
141
|
##
|
121
|
-
# CRC32c checksum, as described in
|
122
|
-
#
|
142
|
+
# The CRC32c checksum of the data, as described in
|
143
|
+
# {RFC 4960, Appendix B}[http://tools.ietf.org/html/rfc4960#appendix-B].
|
144
|
+
# Encoded using base64 in big-endian byte order.
|
123
145
|
def crc32c
|
124
146
|
@gapi["crc32c"]
|
125
147
|
end
|
@@ -130,6 +152,130 @@ module Gcloud
|
|
130
152
|
@gapi["etag"]
|
131
153
|
end
|
132
154
|
|
155
|
+
##
|
156
|
+
# The {Cache-Control}[https://tools.ietf.org/html/rfc7234#section-5.2]
|
157
|
+
# directive for the file data.
|
158
|
+
def cache_control
|
159
|
+
@gapi["cacheControl"]
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Updates the
|
164
|
+
# {Cache-Control}[https://tools.ietf.org/html/rfc7234#section-5.2]
|
165
|
+
# directive for the file data.
|
166
|
+
def cache_control= cache_control
|
167
|
+
patch_gapi! cache_control: cache_control
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# The {Content-Disposition}[https://tools.ietf.org/html/rfc6266] of the
|
172
|
+
# file data.
|
173
|
+
def content_disposition
|
174
|
+
@gapi["contentDisposition"]
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# Updates the {Content-Disposition}[https://tools.ietf.org/html/rfc6266]
|
179
|
+
# of the file data.
|
180
|
+
def content_disposition= content_disposition
|
181
|
+
patch_gapi! content_disposition: content_disposition
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# The {Content-Encoding
|
186
|
+
# }[https://tools.ietf.org/html/rfc7231#section-3.1.2.2] of the file data.
|
187
|
+
def content_encoding
|
188
|
+
@gapi["contentEncoding"]
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Updates the {Content-Encoding
|
193
|
+
# }[https://tools.ietf.org/html/rfc7231#section-3.1.2.2] of the file data.
|
194
|
+
def content_encoding= content_encoding
|
195
|
+
patch_gapi! content_encoding: content_encoding
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# The {Content-Language}[http://tools.ietf.org/html/bcp47] of the file
|
200
|
+
# data.
|
201
|
+
def content_language
|
202
|
+
@gapi["contentLanguage"]
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Updates the {Content-Language}[http://tools.ietf.org/html/bcp47] of the
|
207
|
+
# file data.
|
208
|
+
def content_language= content_language
|
209
|
+
patch_gapi! content_language: content_language
|
210
|
+
end
|
211
|
+
|
212
|
+
##
|
213
|
+
# The {Content-Type}[https://tools.ietf.org/html/rfc2616#section-14.17] of
|
214
|
+
# the file data.
|
215
|
+
def content_type
|
216
|
+
@gapi["contentType"]
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Updates the
|
221
|
+
# {Content-Type}[https://tools.ietf.org/html/rfc2616#section-14.17] of the
|
222
|
+
# file data.
|
223
|
+
def content_type= content_type
|
224
|
+
patch_gapi! content_type: content_type
|
225
|
+
end
|
226
|
+
|
227
|
+
##
|
228
|
+
# A hash of custom, user-provided web-safe keys and arbitrary string
|
229
|
+
# values that will returned with requests for the file as "x-goog-meta-"
|
230
|
+
# response headers.
|
231
|
+
def metadata
|
232
|
+
m = @gapi["metadata"]
|
233
|
+
m = m.to_hash if m.respond_to? :to_hash
|
234
|
+
m.freeze
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# Updates the hash of custom, user-provided web-safe keys and arbitrary
|
239
|
+
# string values that will returned with requests for the file as
|
240
|
+
# "x-goog-meta-" response headers.
|
241
|
+
def metadata= metadata
|
242
|
+
patch_gapi! metadata: metadata
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Updates the file with changes made in the given block in a single
|
247
|
+
# PATCH request. The following attributes may be set: #cache_control=,
|
248
|
+
# #content_disposition=, #content_encoding=, #content_language=,
|
249
|
+
# #content_type=, and #metadata=. The #metadata hash accessible in the
|
250
|
+
# block is completely mutable and will be included in the request.
|
251
|
+
#
|
252
|
+
# === Examples
|
253
|
+
#
|
254
|
+
# require "gcloud"
|
255
|
+
#
|
256
|
+
# gcloud = Gcloud.new
|
257
|
+
# storage = gcloud.storage
|
258
|
+
#
|
259
|
+
# bucket = storage.bucket "my-bucket"
|
260
|
+
#
|
261
|
+
# file = bucket.file "path/to/my-file.ext"
|
262
|
+
#
|
263
|
+
# file.update do |f|
|
264
|
+
# f.cache_control = "private, max-age=0, no-cache"
|
265
|
+
# f.content_disposition = "inline; filename=filename.ext"
|
266
|
+
# f.content_encoding = "deflate"
|
267
|
+
# f.content_language = "de"
|
268
|
+
# f.content_type = "application/json"
|
269
|
+
# f.metadata["player"] = "Bob"
|
270
|
+
# f.metadata["score"] = "10"
|
271
|
+
# end
|
272
|
+
#
|
273
|
+
def update
|
274
|
+
updater = Updater.new metadata
|
275
|
+
yield updater
|
276
|
+
patch_gapi! updater.updates unless updater.updates.empty?
|
277
|
+
end
|
278
|
+
|
133
279
|
##
|
134
280
|
# Download the file's contents to a local file.
|
135
281
|
#
|
@@ -229,6 +375,9 @@ module Gcloud
|
|
229
375
|
# path to copy the file to in the given bucket. (+String+)
|
230
376
|
# +options+::
|
231
377
|
# An optional Hash for controlling additional behavior. (+Hash+)
|
378
|
+
# <code>options[:generation]</code>::
|
379
|
+
# Select a specific revision of the file to copy. The default is the
|
380
|
+
# latest version. (+Integer+)
|
232
381
|
# <code>options[:acl]</code>::
|
233
382
|
# A predefined set of access controls to apply to new file.
|
234
383
|
# (+String+)
|
@@ -278,6 +427,11 @@ module Gcloud
|
|
278
427
|
# file.copy "new-destination-bucket",
|
279
428
|
# "path/to/destination/file.ext"
|
280
429
|
#
|
430
|
+
# The file can also be copied by specifying a generation:
|
431
|
+
#
|
432
|
+
# file.copy "copy/of/previous/generation/file.ext",
|
433
|
+
# generation: 123456
|
434
|
+
#
|
281
435
|
def copy dest_bucket_or_path, dest_path = nil, options = {}
|
282
436
|
ensure_connection!
|
283
437
|
dest_bucket, dest_path, options = fix_copy_args dest_bucket_or_path,
|
@@ -293,7 +447,7 @@ module Gcloud
|
|
293
447
|
end
|
294
448
|
|
295
449
|
##
|
296
|
-
#
|
450
|
+
# Permanently deletes the file.
|
297
451
|
#
|
298
452
|
# === Returns
|
299
453
|
#
|
@@ -321,6 +475,50 @@ module Gcloud
|
|
321
475
|
end
|
322
476
|
end
|
323
477
|
|
478
|
+
##
|
479
|
+
# Public URL to access the file. If the file is not public, requests to
|
480
|
+
# the URL will return an error. (See File::Acl#public! and
|
481
|
+
# Bucket::DefaultAcl#public!) For more information, read [Accessing Public
|
482
|
+
# Data]{https://cloud.google.com/storage/docs/access-public-data}.
|
483
|
+
#
|
484
|
+
# To share a file that is not public see #signed_url.
|
485
|
+
#
|
486
|
+
# === Parameters
|
487
|
+
#
|
488
|
+
# +options+::
|
489
|
+
# An optional Hash for controlling additional behavior. (+Hash+)
|
490
|
+
# <code>options[:protocol]</code>::
|
491
|
+
# The protocol to use for the URL. Default is +HTTPS+. (+String+)
|
492
|
+
#
|
493
|
+
# === Examples
|
494
|
+
#
|
495
|
+
# require "gcloud"
|
496
|
+
#
|
497
|
+
# gcloud = Gcloud.new
|
498
|
+
# storage = gcloud.storage
|
499
|
+
#
|
500
|
+
# bucket = storage.bucket "my-todo-app"
|
501
|
+
# file = bucket.file "avatars/heidi/400x400.png"
|
502
|
+
# public_url = file.public_url
|
503
|
+
#
|
504
|
+
# To generate the URL with a protocol other than HTTPS, use the +protocol+
|
505
|
+
# option:
|
506
|
+
#
|
507
|
+
# require "gcloud"
|
508
|
+
#
|
509
|
+
# gcloud = Gcloud.new
|
510
|
+
# storage = gcloud.storage
|
511
|
+
#
|
512
|
+
# bucket = storage.bucket "my-todo-app"
|
513
|
+
# file = bucket.file "avatars/heidi/400x400.png"
|
514
|
+
# public_url = file.public_url protocol: "http"
|
515
|
+
#
|
516
|
+
def public_url options = {}
|
517
|
+
protocol = options[:protocol] || :https
|
518
|
+
"#{protocol}://storage.googleapis.com/#{bucket}/#{name}"
|
519
|
+
end
|
520
|
+
alias_method :url, :public_url
|
521
|
+
|
324
522
|
##
|
325
523
|
# Access without authentication can be granted to a File for a specified
|
326
524
|
# period of time. This URL uses a cryptographic signature
|
@@ -500,6 +698,16 @@ module Gcloud
|
|
500
698
|
fail "Must have active connection" unless connection
|
501
699
|
end
|
502
700
|
|
701
|
+
def patch_gapi! options = {}
|
702
|
+
ensure_connection!
|
703
|
+
resp = connection.patch_file bucket, name, options
|
704
|
+
if resp.success?
|
705
|
+
@gapi = resp.data
|
706
|
+
else
|
707
|
+
fail ApiError.from_response(resp)
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
503
711
|
def fix_copy_args dest_bucket, dest_path, options = {}
|
504
712
|
if dest_path.respond_to?(:to_hash) && options.empty?
|
505
713
|
options, dest_path = dest_path, nil
|
@@ -587,6 +795,38 @@ module Gcloud
|
|
587
795
|
"&Signature=#{CGI.escape signature}"
|
588
796
|
end
|
589
797
|
end
|
798
|
+
|
799
|
+
##
|
800
|
+
# Yielded to a block to accumulate changes for a patch request.
|
801
|
+
class Updater
|
802
|
+
attr_reader :updates
|
803
|
+
##
|
804
|
+
# Create an Updater object.
|
805
|
+
def initialize metadata
|
806
|
+
@metadata = if metadata.nil?
|
807
|
+
{}
|
808
|
+
else
|
809
|
+
metadata.dup
|
810
|
+
end
|
811
|
+
@updates = {}
|
812
|
+
end
|
813
|
+
|
814
|
+
ATTRS = [:cache_control, :content_disposition, :content_encoding,
|
815
|
+
:content_language, :content_type, :metadata]
|
816
|
+
|
817
|
+
ATTRS.each do |attr|
|
818
|
+
define_method "#{attr}=" do |arg|
|
819
|
+
updates[attr] = arg
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
##
|
824
|
+
# Return metadata for mutation. Also adds metadata to @updates so that
|
825
|
+
# it is included in the patch request.
|
826
|
+
def metadata
|
827
|
+
updates[:metadata] ||= @metadata
|
828
|
+
end
|
829
|
+
end
|
590
830
|
end
|
591
831
|
end
|
592
832
|
end
|
@@ -352,7 +352,7 @@ module Gcloud
|
|
352
352
|
end
|
353
353
|
|
354
354
|
##
|
355
|
-
#
|
355
|
+
# Permanently deletes the entity from the file's access control list.
|
356
356
|
#
|
357
357
|
# === Parameters
|
358
358
|
#
|
@@ -536,11 +536,20 @@ module Gcloud
|
|
536
536
|
|
537
537
|
protected
|
538
538
|
|
539
|
+
def clear!
|
540
|
+
@owners = nil
|
541
|
+
@writers = nil
|
542
|
+
@readers = nil
|
543
|
+
self
|
544
|
+
end
|
545
|
+
|
539
546
|
def update_predefined_acl! acl_role
|
540
547
|
resp = @connection.patch_file @bucket, @file,
|
541
|
-
|
548
|
+
predefined_acl: acl_role,
|
549
|
+
acl: []
|
542
550
|
|
543
|
-
resp.success?
|
551
|
+
return clear! if resp.success?
|
552
|
+
fail Gcloud::Storage::ApiError.from_response(resp)
|
544
553
|
end
|
545
554
|
|
546
555
|
def entities_from_acls acls, role
|
@@ -18,6 +18,7 @@ require "gcloud/storage/errors"
|
|
18
18
|
require "gcloud/storage/connection"
|
19
19
|
require "gcloud/storage/credentials"
|
20
20
|
require "gcloud/storage/bucket"
|
21
|
+
require "gcloud/storage/bucket/cors"
|
21
22
|
require "gcloud/storage/file"
|
22
23
|
|
23
24
|
module Gcloud
|
@@ -190,7 +191,13 @@ module Gcloud
|
|
190
191
|
alias_method :find_bucket, :bucket
|
191
192
|
|
192
193
|
##
|
193
|
-
# Creates a new bucket.
|
194
|
+
# Creates a new bucket with optional attributes. Also accepts a block for
|
195
|
+
# defining the CORS configuration for a static website served from the
|
196
|
+
# bucket. See Bucket::Cors for details. For more information about
|
197
|
+
# configuring buckets as static websites, see {How to Host a Static
|
198
|
+
# Website }[https://cloud.google.com/storage/docs/website-configuration].
|
199
|
+
# For more information about CORS, see {Cross-Origin Resource Sharing
|
200
|
+
# (CORS)}[https://cloud.google.com/storage/docs/cross-origin].
|
194
201
|
#
|
195
202
|
# === Parameters
|
196
203
|
#
|
@@ -198,9 +205,53 @@ module Gcloud
|
|
198
205
|
# Name of a bucket. (+String+)
|
199
206
|
# +options+::
|
200
207
|
# An optional Hash for controlling additional behavior. (+Hash+)
|
208
|
+
# <code>options[:cors]</code>::
|
209
|
+
# The CORS rules for the bucket. Accepts an array of hashes containing
|
210
|
+
# the attributes specified for the {resource description of
|
211
|
+
# cors}[https://cloud.google.com/storage/docs/json_api/v1/buckets#cors].
|
212
|
+
# <code>options[:location]</code>::
|
213
|
+
# The location of the bucket. Object data for objects in the bucket
|
214
|
+
# resides in physical storage within this region. Possible values
|
215
|
+
# include +ASIA+, +EU+, and +US+.(See the {developer's
|
216
|
+
# guide}[https://cloud.google.com/storage/docs/bucket-locations] for the
|
217
|
+
# authoritative list. The default value is +US+. (+String+)
|
218
|
+
# <code>options[:logging_bucket]</code>::
|
219
|
+
# The destination bucket for the bucket's logs. For more information,
|
220
|
+
# see {Access
|
221
|
+
# Logs}[https://cloud.google.com/storage/docs/access-logs]. (+String+)
|
222
|
+
# <code>options[:logging_prefix]</code>::
|
223
|
+
# The prefix used to create log object names for the bucket. It can be
|
224
|
+
# at most 900 characters and must be a {valid object
|
225
|
+
# name}[https://cloud.google.com/storage/docs/bucket-naming#objectnames]
|
226
|
+
# . By default, the object prefix is the name
|
227
|
+
# of the bucket for which the logs are enabled. For more information,
|
228
|
+
# see {Access Logs}[https://cloud.google.com/storage/docs/access-logs].
|
229
|
+
# (+String+)
|
201
230
|
# <code>options[:retries]</code>::
|
202
231
|
# The number of times the API call should be retried.
|
203
232
|
# Default is Gcloud::Backoff.retries. (+Integer+)
|
233
|
+
# <code>options[:storage_class]</code>::
|
234
|
+
# Defines how objects in the bucket are stored and determines the SLA
|
235
|
+
# and the cost of storage. Values include +:standard+, +:nearline+, and
|
236
|
+
# +:dra+ (Durable Reduced Availability), as well as the strings returned
|
237
|
+
# by Bucket#storage_class. For more information, see {Storage
|
238
|
+
# Classes}[https://cloud.google.com/storage/docs/storage-classes].
|
239
|
+
# The default value is +:standard+. (+Symbol+ or +String+)
|
240
|
+
# <code>options[:versioning]</code>::
|
241
|
+
# Whether {Object
|
242
|
+
# Versioning}[https://cloud.google.com/storage/docs/object-versioning]
|
243
|
+
# is to be enabled for the bucket. The default value is +false+.
|
244
|
+
# (+Boolean+)
|
245
|
+
# <code>options[:website_main]</code>::
|
246
|
+
# The index page returned from a static website served from the bucket
|
247
|
+
# when a site visitor requests the top level directory. For more
|
248
|
+
# information, see {How to Host a Static Website
|
249
|
+
# }[https://cloud.google.com/storage/docs/website-configuration#step4].
|
250
|
+
# <code>options[:website_404]</code>::
|
251
|
+
# The page returned from a static website served from the bucket when a
|
252
|
+
# site visitor requests a resource that does not exist. For more
|
253
|
+
# information, see {How to Host a Static Website
|
254
|
+
# }[https://cloud.google.com/storage/docs/website-configuration#step4].
|
204
255
|
#
|
205
256
|
# === Returns
|
206
257
|
#
|
@@ -226,12 +277,45 @@ module Gcloud
|
|
226
277
|
#
|
227
278
|
# bucket = storage.create_bucket "my-bucket", retries: 5
|
228
279
|
#
|
280
|
+
# You can pass {website
|
281
|
+
# settings}[https://cloud.google.com/storage/docs/website-configuration]
|
282
|
+
# for the bucket, including a block that defines CORS rule. See
|
283
|
+
# Bucket::Cors for details.
|
284
|
+
#
|
285
|
+
# require "gcloud"
|
286
|
+
#
|
287
|
+
# gcloud = Gcloud.new
|
288
|
+
# storage = gcloud.storage
|
289
|
+
#
|
290
|
+
# options = {
|
291
|
+
# website_main: "index.html"
|
292
|
+
# website_404: "not_found.html"
|
293
|
+
# }
|
294
|
+
# bucket = storage.create_bucket "my-bucket", options do |c|
|
295
|
+
# c.add_rule ["http://example.org", "https://example.org"],
|
296
|
+
# "*",
|
297
|
+
# response_headers: ["X-My-Custom-Header"],
|
298
|
+
# max_age: 300
|
299
|
+
# end
|
300
|
+
#
|
229
301
|
def create_bucket bucket_name, options = {}
|
230
|
-
options[:acl] =
|
231
|
-
default_acl = options[:default_acl]
|
232
|
-
|
233
|
-
|
302
|
+
options[:acl] = acl_rule options[:acl]
|
303
|
+
options[:default_acl] = acl_rule options[:default_acl]
|
304
|
+
if block_given?
|
305
|
+
cors_builder = Bucket::Cors.new
|
306
|
+
yield cors_builder
|
307
|
+
options[:cors] = cors_builder if cors_builder.changed?
|
308
|
+
end
|
309
|
+
insert_bucket bucket_name, options
|
310
|
+
end
|
311
|
+
|
312
|
+
protected
|
313
|
+
|
314
|
+
def acl_rule option_name
|
315
|
+
Bucket::Acl.predefined_rule_for option_name
|
316
|
+
end
|
234
317
|
|
318
|
+
def insert_bucket bucket_name, options
|
235
319
|
resp = connection.insert_bucket bucket_name, options
|
236
320
|
if resp.success?
|
237
321
|
Bucket.from_gapi resp.data, connection
|