gcloud 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MGI1YjI0MjIxZDhhNmI1YjY0ZWM2MjY0YTg5ZDY3OWZlMmVlYjhhNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzdkOGRmYTY3MmQ0YzU0ZGM4YmIwZGQwNDdmY2EzNDNjYTY4NjRlYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTU4ZGJkZmM4YTg2YWY2YWNiYjQyYmQxNDM3YzBhNTczZDViMzgzMGQyMGIz
|
10
|
+
ODVlY2JmNDJjNjljMmRlZTY5MmZhNzdiZTg3ZjUxMTI0MjM5ZTA5OWM4Njg4
|
11
|
+
NzdiNmE4ZTVjOTk3MzIwODliYjM0NTcyNmFmNDVmYWFhZDU3OWM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjNkMTAzNDI0YWE1ZWJjOTVjZGMzZjZlMGNhOTQ2NWNmYWZkZGE2NzFkMDY5
|
14
|
+
MGU3OTkxMGRlZWIzNjQzOGM4OTJhNWExY2MyM2E1NzQ1MDNhZTNjMjhkMjAz
|
15
|
+
ZjZkZGI2OGJkMjliYzQyNTkyMmFkNzU2MDRkNmNiYWQxYWE4ZmE=
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.4.1 / 2015-10-20
|
4
|
+
|
5
|
+
#### Changes
|
6
|
+
|
7
|
+
* Add support for Bucket attributes, including:
|
8
|
+
* CORS
|
9
|
+
* logging
|
10
|
+
* versioning
|
11
|
+
* location
|
12
|
+
* website
|
13
|
+
* storage class
|
14
|
+
* Add support for File attributes, including:
|
15
|
+
* cache_control
|
16
|
+
* content_dispostion
|
17
|
+
* content_encoding
|
18
|
+
* content_language
|
19
|
+
* content_type
|
20
|
+
* Add support for File upload validation with MD5 or CRC32c
|
21
|
+
* Add File#public_url
|
22
|
+
* Improve stability and error reporting of Storage ACL helpers
|
23
|
+
|
3
24
|
### 0.4.0 / 2015-10-12
|
4
25
|
|
5
26
|
#### Major changes
|
data/lib/gcloud/bigquery/view.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
require "gcloud/storage/bucket/acl"
|
17
17
|
require "gcloud/storage/bucket/list"
|
18
|
+
require "gcloud/storage/bucket/cors"
|
18
19
|
require "gcloud/storage/file"
|
19
20
|
require "gcloud/upload"
|
20
21
|
|
@@ -69,11 +70,80 @@ module Gcloud
|
|
69
70
|
end
|
70
71
|
|
71
72
|
##
|
72
|
-
#
|
73
|
-
def
|
73
|
+
# A URL that can be used to access the bucket using the REST API.
|
74
|
+
def api_url
|
74
75
|
@gapi["selfLink"]
|
75
76
|
end
|
76
77
|
|
78
|
+
##
|
79
|
+
# Creation time of the bucket.
|
80
|
+
def created_at
|
81
|
+
@gapi["timeCreated"]
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Returns the current CORS configuration for a static website served from
|
86
|
+
# the bucket. For more information, see {Cross-Origin Resource
|
87
|
+
# Sharing (CORS)}[https://cloud.google.com/storage/docs/cross-origin].
|
88
|
+
# The return value is a frozen (unmodifiable) array of hashes containing
|
89
|
+
# the attributes specified for the Bucket resource field
|
90
|
+
# {cors}[https://cloud.google.com/storage/docs/json_api/v1/buckets#cors].
|
91
|
+
#
|
92
|
+
# This method also accepts a block for updating the bucket's CORS rules.
|
93
|
+
# See Bucket::Cors for details.
|
94
|
+
#
|
95
|
+
# === Examples
|
96
|
+
#
|
97
|
+
# Retrieving the bucket's CORS rules.
|
98
|
+
#
|
99
|
+
# require "gcloud"
|
100
|
+
#
|
101
|
+
# gcloud = Gcloud.new
|
102
|
+
# storage = gcloud.storage
|
103
|
+
#
|
104
|
+
# bucket = storage.bucket "my-todo-app"
|
105
|
+
# bucket.cors #=> [{"origin"=>["http://example.org"],
|
106
|
+
# # "method"=>["GET","POST","DELETE"],
|
107
|
+
# # "responseHeader"=>["X-My-Custom-Header"],
|
108
|
+
# # "maxAgeSeconds"=>3600}]
|
109
|
+
#
|
110
|
+
# Updating the bucket's CORS rules inside a block.
|
111
|
+
#
|
112
|
+
# require "gcloud"
|
113
|
+
#
|
114
|
+
# gcloud = Gcloud.new
|
115
|
+
# storage = gcloud.storage
|
116
|
+
# bucket = storage.bucket "my-todo-app"
|
117
|
+
#
|
118
|
+
# bucket.update do |b|
|
119
|
+
# b.cors do |c|
|
120
|
+
# c.add_rule ["http://example.org", "https://example.org"],
|
121
|
+
# "*",
|
122
|
+
# response_headers: ["X-My-Custom-Header"],
|
123
|
+
# max_age: 3600
|
124
|
+
# end
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
def cors
|
128
|
+
if block_given?
|
129
|
+
cors_builder = Bucket::Cors.new @gapi["cors"]
|
130
|
+
yield cors_builder
|
131
|
+
self.cors = cors_builder if cors_builder.changed?
|
132
|
+
end
|
133
|
+
deep_dup_and_freeze @gapi["cors"]
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Updates the CORS configuration for a static website served from the
|
138
|
+
# bucket. For more information, see {Cross-Origin Resource
|
139
|
+
# Sharing (CORS)}[https://cloud.google.com/storage/docs/cross-origin].
|
140
|
+
# Accepts an array of hashes containing the attributes specified for the
|
141
|
+
# {resource description of
|
142
|
+
# cors}[https://cloud.google.com/storage/docs/json_api/v1/buckets#cors].
|
143
|
+
def cors= new_cors
|
144
|
+
patch_gapi! cors: new_cors
|
145
|
+
end
|
146
|
+
|
77
147
|
##
|
78
148
|
# The location of the bucket.
|
79
149
|
# Object data for objects in the bucket resides in physical
|
@@ -86,13 +156,150 @@ module Gcloud
|
|
86
156
|
end
|
87
157
|
|
88
158
|
##
|
89
|
-
#
|
90
|
-
|
91
|
-
|
159
|
+
# The destination bucket name for the bucket's logs. For more information,
|
160
|
+
# see {Access Logs}[https://cloud.google.com/storage/docs/access-logs].
|
161
|
+
def logging_bucket
|
162
|
+
@gapi["logging"]["logBucket"] if @gapi["logging"]
|
163
|
+
end
|
164
|
+
|
165
|
+
##
|
166
|
+
# Updates the destination bucket for the bucket's logs. For more
|
167
|
+
# information, see {Access
|
168
|
+
# Logs}[https://cloud.google.com/storage/docs/access-logs]. (+String+)
|
169
|
+
def logging_bucket= logging_bucket
|
170
|
+
patch_gapi! logging_bucket: logging_bucket
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# The logging object prefix for the bucket's logs. For more information,
|
175
|
+
# see {Access Logs}[https://cloud.google.com/storage/docs/access-logs].
|
176
|
+
def logging_prefix
|
177
|
+
@gapi["logging"]["logObjectPrefix"] if @gapi["logging"]
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Updates the logging object prefix. This prefix will be used to create
|
182
|
+
# log object names for the bucket. It can be at most 900 characters and
|
183
|
+
# must be a {valid object
|
184
|
+
# name}[https://cloud.google.com/storage/docs/bucket-naming#objectnames].
|
185
|
+
# By default, the object prefix is the name
|
186
|
+
# of the bucket for which the logs are enabled. For more information, see
|
187
|
+
# {Access Logs}[https://cloud.google.com/storage/docs/access-logs].
|
188
|
+
# (+String+)
|
189
|
+
def logging_prefix= logging_prefix
|
190
|
+
patch_gapi! logging_prefix: logging_prefix
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# The bucket's storage class. This defines how objects in the bucket are
|
195
|
+
# stored and determines the SLA and the cost of storage. Values include
|
196
|
+
# +STANDARD+, +NEARLINE+, and +DURABLE_REDUCED_AVAILABILITY+.
|
197
|
+
def storage_class
|
198
|
+
@gapi["storageClass"]
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Whether {Object
|
203
|
+
# Versioning}[https://cloud.google.com/storage/docs/object-versioning] is
|
204
|
+
# enabled for the bucket.
|
205
|
+
def versioning?
|
206
|
+
!@gapi["versioning"].nil? && @gapi["versioning"]["enabled"]
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Updates whether {Object
|
211
|
+
# Versioning}[https://cloud.google.com/storage/docs/object-versioning] is
|
212
|
+
# enabled for the bucket. (+Boolean+)
|
213
|
+
def versioning= new_versioning
|
214
|
+
patch_gapi! versioning: new_versioning
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# The index page returned from a static website served from the bucket
|
219
|
+
# when a site visitor requests the top level directory. For more
|
220
|
+
# information, see {How to Host a Static Website
|
221
|
+
# }[https://cloud.google.com/storage/docs/website-configuration#step4].
|
222
|
+
def website_main
|
223
|
+
@gapi["website"]["mainPageSuffix"] if @gapi["website"]
|
92
224
|
end
|
93
225
|
|
94
226
|
##
|
95
|
-
#
|
227
|
+
# Updates the index page returned from a static website served from the
|
228
|
+
# bucket when a site visitor requests the top level directory. For more
|
229
|
+
# information, see {How to Host a Static Website
|
230
|
+
# }[https://cloud.google.com/storage/docs/website-configuration#step4].
|
231
|
+
# (+String+)
|
232
|
+
def website_main= website_main
|
233
|
+
patch_gapi! website_main: website_main
|
234
|
+
end
|
235
|
+
|
236
|
+
##
|
237
|
+
# The page returned from a static website served from the bucket when a
|
238
|
+
# site visitor requests a resource that does not exist. For more
|
239
|
+
# information, see {How to Host a Static Website
|
240
|
+
# }[https://cloud.google.com/storage/docs/website-configuration#step4].
|
241
|
+
def website_404
|
242
|
+
@gapi["website"]["notFoundPage"] if @gapi["website"]
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Updates the page returned from a static website served from the bucket
|
247
|
+
# when a site visitor requests a resource that does not exist. For more
|
248
|
+
# information, see {How to Host a Static Website
|
249
|
+
# }[https://cloud.google.com/storage/docs/website-configuration#step4].
|
250
|
+
# (+String+)
|
251
|
+
def website_404= website_404
|
252
|
+
patch_gapi! website_404: website_404
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# Updates the bucket with changes made in the given block in a single
|
257
|
+
# PATCH request. The following attributes may be set: #cors=,
|
258
|
+
# #logging_bucket=, #logging_prefix=, #versioning=, #website_main=, and
|
259
|
+
# #website_404=. In addition, the #cors configuration accessible in the
|
260
|
+
# block is completely mutable and will be included in the request.
|
261
|
+
#
|
262
|
+
# === Examples
|
263
|
+
#
|
264
|
+
# require "gcloud"
|
265
|
+
#
|
266
|
+
# gcloud = Gcloud.new
|
267
|
+
# storage = gcloud.storage
|
268
|
+
#
|
269
|
+
# bucket = storage.bucket "my-bucket"
|
270
|
+
# bucket.update do |b|
|
271
|
+
# b.website_main = "index.html"
|
272
|
+
# b.website_404 = "not_found.html"
|
273
|
+
# b.cors[0]["method"] = ["GET","POST","DELETE"]
|
274
|
+
# b.cors[1]["responseHeader"] << "X-Another-Custom-Header"
|
275
|
+
# end
|
276
|
+
#
|
277
|
+
# New CORS rules can also be added in a nested block. See Bucket::Cors for
|
278
|
+
# details.
|
279
|
+
#
|
280
|
+
# require "gcloud"
|
281
|
+
#
|
282
|
+
# gcloud = Gcloud.new
|
283
|
+
# storage = gcloud.storage
|
284
|
+
# bucket = storage.bucket "my-todo-app"
|
285
|
+
#
|
286
|
+
# bucket.update do |b|
|
287
|
+
# b.cors do |c|
|
288
|
+
# c.add_rule ["http://example.org", "https://example.org"],
|
289
|
+
# "*",
|
290
|
+
# response_headers: ["X-My-Custom-Header"],
|
291
|
+
# max_age: 300
|
292
|
+
# end
|
293
|
+
# end
|
294
|
+
#
|
295
|
+
def update
|
296
|
+
updater = Updater.new @gapi["cors"]
|
297
|
+
yield updater
|
298
|
+
patch_gapi! updater.updates unless updater.updates.empty?
|
299
|
+
end
|
300
|
+
|
301
|
+
##
|
302
|
+
# Permanently deletes the bucket.
|
96
303
|
# The bucket must be empty before it can be deleted.
|
97
304
|
#
|
98
305
|
# === Parameters
|
@@ -279,6 +486,43 @@ module Gcloud
|
|
279
486
|
# and project team members get access according to their roles.
|
280
487
|
# * +public+, +public_read+, +publicRead+ - File owner gets OWNER
|
281
488
|
# access, and allUsers get READER access.
|
489
|
+
# <code>options[:cache_control]</code>::
|
490
|
+
# The {Cache-Control}[https://tools.ietf.org/html/rfc7234#section-5.2]
|
491
|
+
# response header to be returned when the file is downloaded. (+String+)
|
492
|
+
# <code>options[:content_disposition]</code>::
|
493
|
+
# The {Content-Disposition}[https://tools.ietf.org/html/rfc6266]
|
494
|
+
# response header to be returned when the file is downloaded. (+String+)
|
495
|
+
# <code>options[:content_encoding]</code>::
|
496
|
+
# The {Content-Encoding
|
497
|
+
# }[https://tools.ietf.org/html/rfc7231#section-3.1.2.2] response header
|
498
|
+
# to be returned when the file is downloaded. (+String+)
|
499
|
+
# <code>options[:content_language]</code>::
|
500
|
+
# The {Content-Language}[http://tools.ietf.org/html/bcp47] response
|
501
|
+
# header to be returned when the file is downloaded. (+String+)
|
502
|
+
# <code>options[:content_type]</code>::
|
503
|
+
# The {Content-Type}[https://tools.ietf.org/html/rfc2616#section-14.17]
|
504
|
+
# response header to be returned when the file is downloaded. (+String+)
|
505
|
+
# <code>options[:chunk_size]</code>::
|
506
|
+
# The number of bytes per chunk in a resumable upload. Must be divisible
|
507
|
+
# by 256KB. If it is not divisible by 265KB then it will be lowered to
|
508
|
+
# the nearest acceptable value. (+Integer+)
|
509
|
+
# <code>options[:crc32c]</code>::
|
510
|
+
# The CRC32c checksum of the file data, as described in
|
511
|
+
# {RFC 4960, Appendix B}[http://tools.ietf.org/html/rfc4960#appendix-B].
|
512
|
+
# If provided, Cloud Storage will only create the file if the value
|
513
|
+
# matches the value calculated by the service. See
|
514
|
+
# {Validation}[https://cloud.google.com/storage/docs/hashes-etags]
|
515
|
+
# for more information. (+String+)
|
516
|
+
# <code>options[:md5]</code>::
|
517
|
+
# The MD5 hash of the file data. If provided, Cloud Storage will only
|
518
|
+
# create the file if the value matches the value calculated by the
|
519
|
+
# service. See
|
520
|
+
# {Validation}[https://cloud.google.com/storage/docs/hashes-etags]
|
521
|
+
# for more information. (+String+)
|
522
|
+
# <code>options[:metadata]</code>::
|
523
|
+
# A hash of custom, user-provided web-safe keys and arbitrary string
|
524
|
+
# values that will returned with requests for the file as "x-goog-meta-"
|
525
|
+
# response headers. (+Hash+)
|
282
526
|
#
|
283
527
|
# === Returns
|
284
528
|
#
|
@@ -310,7 +554,7 @@ module Gcloud
|
|
310
554
|
# A chunk_size value can be provided in the options to be used
|
311
555
|
# in resumable uploads. This value is the number of bytes per
|
312
556
|
# chunk and must be divisible by 256KB. If it is not divisible
|
313
|
-
# by 265KB then it will be lowered to the nearest
|
557
|
+
# by 265KB then it will be lowered to the nearest acceptable
|
314
558
|
# value.
|
315
559
|
#
|
316
560
|
# require "gcloud"
|
@@ -353,13 +597,14 @@ module Gcloud
|
|
353
597
|
def create_file file, path = nil, options = {}
|
354
598
|
ensure_connection!
|
355
599
|
ensure_file_exists! file
|
356
|
-
|
357
600
|
options[:acl] = File::Acl.predefined_rule_for options[:acl]
|
601
|
+
resumable = resumable_upload?(file)
|
602
|
+
resp = @connection.upload_file resumable, name, file, path, options
|
358
603
|
|
359
|
-
if
|
360
|
-
|
604
|
+
if resp.success?
|
605
|
+
File.from_gapi resp.data, connection
|
361
606
|
else
|
362
|
-
|
607
|
+
fail ApiError.from_response(resp)
|
363
608
|
end
|
364
609
|
end
|
365
610
|
alias_method :upload_file, :create_file
|
@@ -503,6 +748,16 @@ module Gcloud
|
|
503
748
|
fail "Must have active connection" unless connection
|
504
749
|
end
|
505
750
|
|
751
|
+
def patch_gapi! options = {}
|
752
|
+
ensure_connection!
|
753
|
+
resp = connection.patch_bucket name, options
|
754
|
+
if resp.success?
|
755
|
+
@gapi = resp.data
|
756
|
+
else
|
757
|
+
fail ApiError.from_response(resp)
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
506
761
|
##
|
507
762
|
# Raise an error if the file is not found.
|
508
763
|
def ensure_file_exists! file
|
@@ -516,39 +771,53 @@ module Gcloud
|
|
516
771
|
::File.size?(file).to_i > Upload.resumable_threshold
|
517
772
|
end
|
518
773
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
774
|
+
##
|
775
|
+
# Given nil, empty array, a gapi array of hashes, or any value, returns a
|
776
|
+
# deeply dup'd and frozen array of simple hashes or values (not gapi
|
777
|
+
# objects.)
|
778
|
+
def deep_dup_and_freeze array
|
779
|
+
return [].freeze if array.nil? || array.empty?
|
780
|
+
array = Array(array.dup)
|
781
|
+
array = array.map do |h|
|
782
|
+
h = h.to_hash if h.respond_to? :to_hash
|
783
|
+
h.dup.freeze
|
526
784
|
end
|
785
|
+
array.freeze
|
527
786
|
end
|
528
787
|
|
529
|
-
|
530
|
-
|
788
|
+
##
|
789
|
+
# Yielded to a block to accumulate changes for a patch request.
|
790
|
+
class Updater
|
791
|
+
attr_reader :updates
|
792
|
+
##
|
793
|
+
# Create an Updater object.
|
794
|
+
def initialize cors
|
795
|
+
@cors = cors ? Array(cors.dup) : []
|
796
|
+
@cors = @cors.map { |x| x.to_hash if x.respond_to? :to_hash }
|
797
|
+
@updates = {}
|
798
|
+
end
|
531
799
|
|
532
|
-
|
533
|
-
|
800
|
+
ATTRS = [:cors, :logging_bucket, :logging_prefix, :versioning,
|
801
|
+
:website_main, :website_404]
|
534
802
|
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
803
|
+
ATTRS.each do |attr|
|
804
|
+
define_method "#{attr}=" do |arg|
|
805
|
+
updates[attr] = arg
|
806
|
+
end
|
539
807
|
end
|
540
|
-
end
|
541
808
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
809
|
+
##
|
810
|
+
# Return CORS for mutation. Also adds CORS to @updates so that it
|
811
|
+
# is included in the patch request.
|
812
|
+
def cors
|
813
|
+
updates[:cors] ||= @cors
|
814
|
+
if block_given?
|
815
|
+
cors_builder = Bucket::Cors.new updates[:cors]
|
816
|
+
yield cors_builder
|
817
|
+
updates[:cors] = cors_builder if cors_builder.changed?
|
818
|
+
end
|
819
|
+
updates[:cors]
|
549
820
|
end
|
550
|
-
return if chunk_size.zero?
|
551
|
-
chunk_size
|
552
821
|
end
|
553
822
|
end
|
554
823
|
end
|