gcloud 0.11.0 → 0.12.0
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/AUTHENTICATION.md +3 -3
- data/CHANGELOG.md +92 -0
- data/OVERVIEW.md +3 -3
- data/lib/gcloud.rb +75 -25
- data/lib/gcloud/backoff.rb +5 -1
- data/lib/gcloud/bigquery.rb +25 -43
- data/lib/gcloud/bigquery/copy_job.rb +13 -13
- data/lib/gcloud/bigquery/data.rb +20 -16
- data/lib/gcloud/bigquery/dataset.rb +202 -177
- data/lib/gcloud/bigquery/dataset/access.rb +118 -104
- data/lib/gcloud/bigquery/dataset/list.rb +14 -18
- data/lib/gcloud/bigquery/extract_job.rb +12 -12
- data/lib/gcloud/bigquery/insert_response.rb +12 -14
- data/lib/gcloud/bigquery/job.rb +45 -57
- data/lib/gcloud/bigquery/job/list.rb +18 -24
- data/lib/gcloud/bigquery/load_job.rb +35 -27
- data/lib/gcloud/bigquery/project.rb +53 -73
- data/lib/gcloud/bigquery/query_data.rb +28 -35
- data/lib/gcloud/bigquery/query_job.rb +18 -18
- data/lib/gcloud/bigquery/schema.rb +359 -0
- data/lib/gcloud/bigquery/service.rb +506 -0
- data/lib/gcloud/bigquery/table.rb +185 -266
- data/lib/gcloud/bigquery/table/list.rb +15 -19
- data/lib/gcloud/bigquery/view.rb +126 -81
- data/lib/gcloud/datastore.rb +39 -27
- data/lib/gcloud/datastore/commit.rb +2 -2
- data/lib/gcloud/datastore/dataset.rb +8 -19
- data/lib/gcloud/datastore/dataset/lookup_results.rb +2 -4
- data/lib/gcloud/datastore/dataset/query_results.rb +0 -2
- data/lib/gcloud/datastore/entity.rb +7 -1
- data/lib/gcloud/datastore/errors.rb +5 -27
- data/lib/gcloud/datastore/grpc_utils.rb +4 -3
- data/lib/gcloud/datastore/key.rb +6 -0
- data/lib/gcloud/datastore/service.rb +18 -12
- data/lib/gcloud/datastore/transaction.rb +0 -10
- data/lib/gcloud/dns.rb +29 -19
- data/lib/gcloud/dns/change.rb +10 -15
- data/lib/gcloud/dns/change/list.rb +4 -4
- data/lib/gcloud/dns/importer.rb +1 -1
- data/lib/gcloud/dns/project.rb +32 -49
- data/lib/gcloud/dns/record.rb +8 -2
- data/lib/gcloud/dns/record/list.rb +4 -4
- data/lib/gcloud/dns/service.rb +167 -0
- data/lib/gcloud/dns/zone.rb +33 -52
- data/lib/gcloud/dns/zone/list.rb +12 -16
- data/lib/gcloud/errors.rb +31 -19
- data/lib/gcloud/logging.rb +50 -39
- data/lib/gcloud/logging/entry.rb +197 -24
- data/lib/gcloud/logging/entry/list.rb +0 -2
- data/lib/gcloud/logging/logger.rb +1 -1
- data/lib/gcloud/logging/metric.rb +3 -9
- data/lib/gcloud/logging/metric/list.rb +0 -2
- data/lib/gcloud/logging/project.rb +58 -54
- data/lib/gcloud/logging/resource_descriptor.rb +2 -2
- data/lib/gcloud/logging/resource_descriptor/list.rb +0 -2
- data/lib/gcloud/logging/service.rb +32 -23
- data/lib/gcloud/logging/sink.rb +8 -14
- data/lib/gcloud/logging/sink/list.rb +0 -2
- data/lib/gcloud/pubsub.rb +21 -16
- data/lib/gcloud/pubsub/policy.rb +204 -0
- data/lib/gcloud/pubsub/project.rb +26 -38
- data/lib/gcloud/pubsub/service.rb +39 -31
- data/lib/gcloud/pubsub/subscription.rb +56 -59
- data/lib/gcloud/pubsub/subscription/list.rb +4 -4
- data/lib/gcloud/pubsub/topic.rb +69 -66
- data/lib/gcloud/pubsub/topic/list.rb +0 -2
- data/lib/gcloud/pubsub/topic/{batch.rb → publisher.rb} +15 -2
- data/lib/gcloud/resource_manager.rb +27 -26
- data/lib/gcloud/resource_manager/manager.rb +19 -39
- data/lib/gcloud/resource_manager/policy.rb +211 -0
- data/lib/gcloud/resource_manager/project.rb +97 -121
- data/lib/gcloud/resource_manager/project/list.rb +7 -7
- data/lib/gcloud/resource_manager/project/updater.rb +4 -9
- data/lib/gcloud/resource_manager/service.rb +127 -0
- data/lib/gcloud/storage.rb +24 -42
- data/lib/gcloud/storage/bucket.rb +104 -192
- data/lib/gcloud/storage/bucket/acl.rb +47 -143
- data/lib/gcloud/storage/bucket/cors.rb +55 -11
- data/lib/gcloud/storage/bucket/list.rb +14 -14
- data/lib/gcloud/storage/errors.rb +3 -43
- data/lib/gcloud/storage/file.rb +114 -111
- data/lib/gcloud/storage/file/acl.rb +27 -113
- data/lib/gcloud/storage/file/list.rb +21 -21
- data/lib/gcloud/storage/project.rb +49 -59
- data/lib/gcloud/storage/service.rb +347 -0
- data/lib/gcloud/translate.rb +24 -14
- data/lib/gcloud/translate/api.rb +12 -21
- data/lib/gcloud/translate/detection.rb +5 -5
- data/lib/gcloud/translate/language.rb +1 -1
- data/lib/gcloud/translate/service.rb +80 -0
- data/lib/gcloud/translate/translation.rb +6 -6
- data/lib/gcloud/version.rb +1 -1
- data/lib/gcloud/vision.rb +24 -15
- data/lib/gcloud/vision/annotate.rb +24 -21
- data/lib/gcloud/vision/annotation.rb +9 -9
- data/lib/gcloud/vision/annotation/entity.rb +11 -11
- data/lib/gcloud/vision/annotation/face.rb +25 -25
- data/lib/gcloud/vision/annotation/properties.rb +8 -8
- data/lib/gcloud/vision/annotation/safe_search.rb +4 -4
- data/lib/gcloud/vision/annotation/text.rb +7 -7
- data/lib/gcloud/vision/annotation/vertex.rb +1 -1
- data/lib/gcloud/vision/image.rb +11 -11
- data/lib/gcloud/vision/location.rb +5 -2
- data/lib/gcloud/vision/project.rb +14 -16
- data/lib/gcloud/vision/service.rb +66 -0
- data/lib/google/api_client.rb +0 -0
- metadata +27 -24
- data/lib/gcloud/bigquery/connection.rb +0 -624
- data/lib/gcloud/bigquery/errors.rb +0 -68
- data/lib/gcloud/bigquery/table/schema.rb +0 -234
- data/lib/gcloud/dns/connection.rb +0 -173
- data/lib/gcloud/dns/errors.rb +0 -68
- data/lib/gcloud/resource_manager/connection.rb +0 -134
- data/lib/gcloud/resource_manager/errors.rb +0 -68
- data/lib/gcloud/storage/connection.rb +0 -444
- data/lib/gcloud/translate/connection.rb +0 -85
- data/lib/gcloud/translate/errors.rb +0 -68
- data/lib/gcloud/upload.rb +0 -95
- data/lib/gcloud/vision/connection.rb +0 -63
- data/lib/gcloud/vision/errors.rb +0 -69
|
@@ -56,9 +56,8 @@ module Gcloud
|
|
|
56
56
|
def initialize file
|
|
57
57
|
@bucket = file.bucket
|
|
58
58
|
@file = file.name
|
|
59
|
-
@
|
|
59
|
+
@service = file.service
|
|
60
60
|
@owners = nil
|
|
61
|
-
@writers = nil
|
|
62
61
|
@readers = nil
|
|
63
62
|
end
|
|
64
63
|
|
|
@@ -77,10 +76,13 @@ module Gcloud
|
|
|
77
76
|
# file.acl.reload!
|
|
78
77
|
#
|
|
79
78
|
def reload!
|
|
80
|
-
|
|
81
|
-
acls =
|
|
79
|
+
gapi = @service.list_file_acls @bucket, @file
|
|
80
|
+
acls = Array(gapi.items).map do |acl|
|
|
81
|
+
return acl if acl.is_a? Google::Apis::StorageV1::ObjectAccessControl
|
|
82
|
+
fail "Unknown ACL format: #{acl.class}" unless acl.is_a? Hash
|
|
83
|
+
Google::Apis::StorageV1::ObjectAccessControl.from_json acl.to_json
|
|
84
|
+
end
|
|
82
85
|
@owners = entities_from_acls acls, "OWNER"
|
|
83
|
-
@writers = entities_from_acls acls, "WRITER"
|
|
84
86
|
@readers = entities_from_acls acls, "READER"
|
|
85
87
|
end
|
|
86
88
|
alias_method :refresh!, :reload!
|
|
@@ -106,27 +108,6 @@ module Gcloud
|
|
|
106
108
|
@owners
|
|
107
109
|
end
|
|
108
110
|
|
|
109
|
-
##
|
|
110
|
-
# Lists the owners of the file.
|
|
111
|
-
#
|
|
112
|
-
# @return [Array<String>]
|
|
113
|
-
#
|
|
114
|
-
# @example
|
|
115
|
-
# require "gcloud"
|
|
116
|
-
#
|
|
117
|
-
# gcloud = Gcloud.new
|
|
118
|
-
# storage = gcloud.storage
|
|
119
|
-
#
|
|
120
|
-
# bucket = storage.bucket "my-bucket"
|
|
121
|
-
#
|
|
122
|
-
# file = bucket.file "path/to/my-file.ext"
|
|
123
|
-
# file.acl.writers.each { |writer| puts writer }
|
|
124
|
-
#
|
|
125
|
-
def writers
|
|
126
|
-
reload! if @writers.nil?
|
|
127
|
-
@writers
|
|
128
|
-
end
|
|
129
|
-
|
|
130
111
|
##
|
|
131
112
|
# Lists the readers of the file.
|
|
132
113
|
#
|
|
@@ -192,68 +173,11 @@ module Gcloud
|
|
|
192
173
|
#
|
|
193
174
|
def add_owner entity, generation: nil
|
|
194
175
|
options = { generation: generation }
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return entity
|
|
201
|
-
end
|
|
202
|
-
nil
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
##
|
|
206
|
-
# Grants writer permission to the file.
|
|
207
|
-
#
|
|
208
|
-
# @param [String] entity The entity holding the permission, in one of
|
|
209
|
-
# the following forms:
|
|
210
|
-
#
|
|
211
|
-
# * user-userId
|
|
212
|
-
# * user-email
|
|
213
|
-
# * group-groupId
|
|
214
|
-
# * group-email
|
|
215
|
-
# * domain-domain
|
|
216
|
-
# * project-team-projectId
|
|
217
|
-
# * allUsers
|
|
218
|
-
# * allAuthenticatedUsers
|
|
219
|
-
#
|
|
220
|
-
# @param [Integer] generation When present, selects a specific revision
|
|
221
|
-
# of this object. Default is the latest version.
|
|
222
|
-
#
|
|
223
|
-
# @example Grant access to a user by pre-pending `"user-"` to an email:
|
|
224
|
-
# require "gcloud"
|
|
225
|
-
#
|
|
226
|
-
# gcloud = Gcloud.new
|
|
227
|
-
# storage = gcloud.storage
|
|
228
|
-
#
|
|
229
|
-
# bucket = storage.bucket "my-bucket"
|
|
230
|
-
#
|
|
231
|
-
# file = bucket.file "path/to/my-file.ext"
|
|
232
|
-
# email = "heidi@example.net"
|
|
233
|
-
# file.acl.add_writer "user-#{email}"
|
|
234
|
-
#
|
|
235
|
-
# @example Grant access to a group by pre-pending `"group-"` to an email
|
|
236
|
-
# require "gcloud"
|
|
237
|
-
#
|
|
238
|
-
# gcloud = Gcloud.new
|
|
239
|
-
# storage = gcloud.storage
|
|
240
|
-
#
|
|
241
|
-
# bucket = storage.bucket "my-bucket"
|
|
242
|
-
#
|
|
243
|
-
# file = bucket.file "path/to/my-file.ext"
|
|
244
|
-
# email = "authors@example.net"
|
|
245
|
-
# file.acl.add_writer "group-#{email}"
|
|
246
|
-
#
|
|
247
|
-
def add_writer entity, generation: nil
|
|
248
|
-
options = { generation: generation }
|
|
249
|
-
resp = @connection.insert_file_acl @bucket, @file, entity,
|
|
250
|
-
"WRITER", options
|
|
251
|
-
if resp.success?
|
|
252
|
-
entity = resp.data["entity"]
|
|
253
|
-
@writers.push entity unless @writers.nil?
|
|
254
|
-
return entity
|
|
255
|
-
end
|
|
256
|
-
nil
|
|
176
|
+
gapi = @service.insert_file_acl @bucket, @file, entity, "OWNER",
|
|
177
|
+
options
|
|
178
|
+
entity = gapi.entity
|
|
179
|
+
@owners.push entity unless @owners.nil?
|
|
180
|
+
entity
|
|
257
181
|
end
|
|
258
182
|
|
|
259
183
|
##
|
|
@@ -300,14 +224,11 @@ module Gcloud
|
|
|
300
224
|
#
|
|
301
225
|
def add_reader entity, generation: nil
|
|
302
226
|
options = { generation: generation }
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
return entity
|
|
309
|
-
end
|
|
310
|
-
nil
|
|
227
|
+
gapi = @service.insert_file_acl @bucket, @file, entity, "READER",
|
|
228
|
+
options
|
|
229
|
+
entity = gapi.entity
|
|
230
|
+
@readers.push entity unless @readers.nil?
|
|
231
|
+
entity
|
|
311
232
|
end
|
|
312
233
|
|
|
313
234
|
##
|
|
@@ -342,14 +263,10 @@ module Gcloud
|
|
|
342
263
|
#
|
|
343
264
|
def delete entity, generation: nil
|
|
344
265
|
options = { generation: generation }
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
@readers.delete entity unless @readers.nil?
|
|
350
|
-
return true
|
|
351
|
-
end
|
|
352
|
-
false
|
|
266
|
+
@service.delete_file_acl @bucket, @file, entity, options
|
|
267
|
+
@owners.delete entity unless @owners.nil?
|
|
268
|
+
@readers.delete entity unless @readers.nil?
|
|
269
|
+
true
|
|
353
270
|
end
|
|
354
271
|
|
|
355
272
|
# @private
|
|
@@ -486,23 +403,20 @@ module Gcloud
|
|
|
486
403
|
|
|
487
404
|
def clear!
|
|
488
405
|
@owners = nil
|
|
489
|
-
@writers = nil
|
|
490
406
|
@readers = nil
|
|
491
407
|
self
|
|
492
408
|
end
|
|
493
409
|
|
|
494
410
|
def update_predefined_acl! acl_role
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
return clear! if resp.success?
|
|
500
|
-
fail Gcloud::Storage::ApiError.from_response(resp)
|
|
411
|
+
patched_file = Google::Apis::StorageV1::Object.new acl: nil
|
|
412
|
+
@service.patch_file \
|
|
413
|
+
@bucket, @file, patched_file, predefined_acl: acl_role
|
|
414
|
+
clear!
|
|
501
415
|
end
|
|
502
416
|
|
|
503
417
|
def entities_from_acls acls, role
|
|
504
|
-
selected = acls.select { |acl| acl
|
|
505
|
-
entities = selected.map
|
|
418
|
+
selected = acls.select { |acl| acl.role == role }
|
|
419
|
+
entities = selected.map(&:entity)
|
|
506
420
|
entities
|
|
507
421
|
end
|
|
508
422
|
end
|
|
@@ -77,15 +77,14 @@ module Gcloud
|
|
|
77
77
|
#
|
|
78
78
|
def next
|
|
79
79
|
return nil unless next?
|
|
80
|
-
|
|
80
|
+
ensure_service!
|
|
81
81
|
options = {
|
|
82
82
|
prefix: @prefix, delimiter: @delimiter, token: @token, max: @max,
|
|
83
83
|
versions: @versions
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
@delimiter, @max, @versions
|
|
85
|
+
gapi = @service.list_files @bucket, options
|
|
86
|
+
File::List.from_gapi gapi, @service, @bucket, @prefix,
|
|
87
|
+
@delimiter, @max, @versions
|
|
89
88
|
end
|
|
90
89
|
|
|
91
90
|
##
|
|
@@ -161,29 +160,30 @@ module Gcloud
|
|
|
161
160
|
end
|
|
162
161
|
|
|
163
162
|
##
|
|
164
|
-
# @private New File::List from a
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
163
|
+
# @private New File::List from a Google API Client
|
|
164
|
+
# Google::Apis::StorageV1::Objects object.
|
|
165
|
+
def self.from_gapi gapi_list, service, bucket = nil, prefix = nil,
|
|
166
|
+
delimiter = nil, max = nil, versions = nil
|
|
167
|
+
files = new(Array(gapi_list.items).map do |gapi_object|
|
|
168
|
+
File.from_gapi gapi_object, service
|
|
169
169
|
end)
|
|
170
|
-
files.instance_variable_set
|
|
171
|
-
files.instance_variable_set
|
|
172
|
-
files.instance_variable_set
|
|
173
|
-
files.instance_variable_set
|
|
174
|
-
files.instance_variable_set
|
|
175
|
-
files.instance_variable_set
|
|
176
|
-
files.instance_variable_set
|
|
177
|
-
files.instance_variable_set
|
|
170
|
+
files.instance_variable_set :@token, gapi_list.next_page_token
|
|
171
|
+
files.instance_variable_set :@prefixes, Array(gapi_list.prefixes)
|
|
172
|
+
files.instance_variable_set :@service, service
|
|
173
|
+
files.instance_variable_set :@bucket, bucket
|
|
174
|
+
files.instance_variable_set :@prefix, prefix
|
|
175
|
+
files.instance_variable_set :@delimiter, delimiter
|
|
176
|
+
files.instance_variable_set :@max, max
|
|
177
|
+
files.instance_variable_set :@versions, versions
|
|
178
178
|
files
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
protected
|
|
182
182
|
|
|
183
183
|
##
|
|
184
|
-
# Raise an error unless an active
|
|
185
|
-
def
|
|
186
|
-
fail "Must have active connection" unless @
|
|
184
|
+
# Raise an error unless an active service is available.
|
|
185
|
+
def ensure_service!
|
|
186
|
+
fail "Must have active connection" unless @service
|
|
187
187
|
end
|
|
188
188
|
end
|
|
189
189
|
end
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
require "gcloud/gce"
|
|
17
17
|
require "gcloud/storage/errors"
|
|
18
|
-
require "gcloud/storage/
|
|
18
|
+
require "gcloud/storage/service"
|
|
19
19
|
require "gcloud/storage/credentials"
|
|
20
20
|
require "gcloud/storage/bucket"
|
|
21
21
|
require "gcloud/storage/bucket/cors"
|
|
@@ -48,17 +48,15 @@ module Gcloud
|
|
|
48
48
|
#
|
|
49
49
|
class Project
|
|
50
50
|
##
|
|
51
|
-
# @private The
|
|
52
|
-
attr_accessor :
|
|
51
|
+
# @private The Service object.
|
|
52
|
+
attr_accessor :service
|
|
53
53
|
|
|
54
54
|
##
|
|
55
55
|
# @private Creates a new Project instance.
|
|
56
56
|
#
|
|
57
57
|
# See {Gcloud#storage}
|
|
58
|
-
def initialize
|
|
59
|
-
|
|
60
|
-
fail ArgumentError, "project is missing" if project.empty?
|
|
61
|
-
@connection = Connection.new project, credentials
|
|
58
|
+
def initialize service
|
|
59
|
+
@service = service
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
##
|
|
@@ -74,7 +72,7 @@ module Gcloud
|
|
|
74
72
|
# storage.project #=> "my-todo-project"
|
|
75
73
|
#
|
|
76
74
|
def project
|
|
77
|
-
|
|
75
|
+
service.project
|
|
78
76
|
end
|
|
79
77
|
|
|
80
78
|
##
|
|
@@ -133,12 +131,8 @@ module Gcloud
|
|
|
133
131
|
#
|
|
134
132
|
def buckets prefix: nil, token: nil, max: nil
|
|
135
133
|
options = { prefix: prefix, token: token, max: max }
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
Bucket::List.from_response resp, connection, prefix, max
|
|
139
|
-
else
|
|
140
|
-
fail ApiError.from_response(resp)
|
|
141
|
-
end
|
|
134
|
+
gapi = service.list_buckets options
|
|
135
|
+
Bucket::List.from_gapi gapi, service, prefix, max
|
|
142
136
|
end
|
|
143
137
|
alias_method :find_buckets, :buckets
|
|
144
138
|
|
|
@@ -160,13 +154,10 @@ module Gcloud
|
|
|
160
154
|
# puts bucket.name
|
|
161
155
|
#
|
|
162
156
|
def bucket bucket_name
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return nil if resp.data["error"]["code"] == 404
|
|
168
|
-
fail ApiError.from_response(resp)
|
|
169
|
-
end
|
|
157
|
+
gapi = service.get_bucket bucket_name
|
|
158
|
+
Bucket.from_gapi gapi, service
|
|
159
|
+
rescue Gcloud::NotFoundError
|
|
160
|
+
nil
|
|
170
161
|
end
|
|
171
162
|
alias_method :find_bucket, :bucket
|
|
172
163
|
|
|
@@ -176,7 +167,7 @@ module Gcloud
|
|
|
176
167
|
# bucket. See {Bucket::Cors} for details.
|
|
177
168
|
#
|
|
178
169
|
# The API call to create the bucket may be retried under certain
|
|
179
|
-
# conditions. See {Gcloud
|
|
170
|
+
# conditions. See {Gcloud#storage} to control this behavior.
|
|
180
171
|
#
|
|
181
172
|
# You can pass [website
|
|
182
173
|
# settings](https://cloud.google.com/storage/docs/website-configuration)
|
|
@@ -221,10 +212,6 @@ module Gcloud
|
|
|
221
212
|
# and project team members get access according to their roles.
|
|
222
213
|
# * `public`, `public_read`, `publicRead` - File owner gets OWNER
|
|
223
214
|
# access, and allUsers get READER access.
|
|
224
|
-
# @param [String] cors The CORS rules for the bucket. Accepts an array of
|
|
225
|
-
# hashes containing the attributes specified for the [resource
|
|
226
|
-
# description of
|
|
227
|
-
# cors](https://cloud.google.com/storage/docs/json_api/v1/buckets#cors).
|
|
228
215
|
# @param [String] location The location of the bucket. Object data for
|
|
229
216
|
# objects in the bucket resides in physical storage within this region.
|
|
230
217
|
# Possible values include `ASIA`, `EU`, and `US`. (See the [developer's
|
|
@@ -260,8 +247,8 @@ module Gcloud
|
|
|
260
247
|
# does not exist. For more information, see [How to Host a Static
|
|
261
248
|
# Website
|
|
262
249
|
# ](https://cloud.google.com/storage/docs/website-configuration#step4).
|
|
263
|
-
# @yield [
|
|
264
|
-
# @yieldparam [Bucket
|
|
250
|
+
# @yield [bucket] a block for configuring the bucket before it is created
|
|
251
|
+
# @yieldparam [Bucket] cors the bucket object to be configured
|
|
265
252
|
#
|
|
266
253
|
# @return [Gcloud::Storage::Bucket]
|
|
267
254
|
#
|
|
@@ -273,38 +260,42 @@ module Gcloud
|
|
|
273
260
|
#
|
|
274
261
|
# bucket = storage.create_bucket "my-bucket"
|
|
275
262
|
#
|
|
276
|
-
# @example
|
|
263
|
+
# @example Configure the bucket in a block:
|
|
277
264
|
# require "gcloud"
|
|
278
265
|
#
|
|
279
266
|
# gcloud = Gcloud.new
|
|
280
267
|
# storage = gcloud.storage
|
|
281
268
|
#
|
|
282
|
-
#
|
|
283
|
-
# website_main
|
|
284
|
-
# website_404
|
|
285
|
-
#
|
|
286
|
-
#
|
|
287
|
-
#
|
|
288
|
-
#
|
|
289
|
-
# response_headers: ["X-My-Custom-Header"],
|
|
290
|
-
# max_age: 300
|
|
269
|
+
# bucket = storage.create_bucket "my-bucket" do |b|
|
|
270
|
+
# b.website_main = "index.html"
|
|
271
|
+
# b.website_404 = "not_found.html"
|
|
272
|
+
# b.cors.add_rule ["http://example.org", "https://example.org"],
|
|
273
|
+
# "*",
|
|
274
|
+
# response_headers: ["X-My-Custom-Header"],
|
|
275
|
+
# max_age: 300
|
|
291
276
|
# end
|
|
292
277
|
#
|
|
293
|
-
def create_bucket bucket_name, acl: nil, default_acl: nil,
|
|
294
|
-
location: nil,
|
|
295
|
-
|
|
296
|
-
website_404: nil
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
278
|
+
def create_bucket bucket_name, acl: nil, default_acl: nil,
|
|
279
|
+
location: nil, storage_class: nil, logging_bucket: nil,
|
|
280
|
+
logging_prefix: nil, website_main: nil,
|
|
281
|
+
website_404: nil, versioning: nil
|
|
282
|
+
new_bucket = Google::Apis::StorageV1::Bucket.new({
|
|
283
|
+
name: bucket_name,
|
|
284
|
+
location: location,
|
|
285
|
+
storage_class: storage_class_for(storage_class)
|
|
286
|
+
}.delete_if { |_, v| v.nil? })
|
|
287
|
+
updater = Bucket::Updater.new(new_bucket).tap do |b|
|
|
288
|
+
b.logging_bucket = logging_bucket unless logging_bucket.nil?
|
|
289
|
+
b.logging_prefix = logging_prefix unless logging_prefix.nil?
|
|
290
|
+
b.website_main = website_main unless website_main.nil?
|
|
291
|
+
b.website_404 = website_404 unless website_404.nil?
|
|
292
|
+
b.versioning = versioning unless versioning.nil?
|
|
306
293
|
end
|
|
307
|
-
|
|
294
|
+
yield updater if block_given?
|
|
295
|
+
updater.check_for_mutable_cors!
|
|
296
|
+
gapi = service.insert_bucket \
|
|
297
|
+
new_bucket, acl: acl_rule(acl), default_acl: acl_rule(default_acl)
|
|
298
|
+
Bucket.from_gapi gapi, service
|
|
308
299
|
end
|
|
309
300
|
|
|
310
301
|
protected
|
|
@@ -313,13 +304,12 @@ module Gcloud
|
|
|
313
304
|
Bucket::Acl.predefined_rule_for option_name
|
|
314
305
|
end
|
|
315
306
|
|
|
316
|
-
def
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
end
|
|
307
|
+
def storage_class_for str
|
|
308
|
+
{ "durable_reduced_availability" => "DURABLE_REDUCED_AVAILABILITY",
|
|
309
|
+
"dra" => "DURABLE_REDUCED_AVAILABILITY",
|
|
310
|
+
"durable" => "DURABLE_REDUCED_AVAILABILITY",
|
|
311
|
+
"nearline" => "NEARLINE",
|
|
312
|
+
"standard" => "STANDARD" }[str.to_s.downcase]
|
|
323
313
|
end
|
|
324
314
|
end
|
|
325
315
|
end
|
|
@@ -0,0 +1,347 @@
|
|
|
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 "gcloud/version"
|
|
17
|
+
require "gcloud/backoff"
|
|
18
|
+
require "google/apis/storage_v1"
|
|
19
|
+
require "digest"
|
|
20
|
+
require "mime/types"
|
|
21
|
+
require "pathname"
|
|
22
|
+
|
|
23
|
+
module Gcloud
|
|
24
|
+
module Storage
|
|
25
|
+
##
|
|
26
|
+
# @private Represents the connection to Storage,
|
|
27
|
+
# as well as expose the API calls.
|
|
28
|
+
class Service
|
|
29
|
+
##
|
|
30
|
+
# Alias to the Google Client API module
|
|
31
|
+
API = Google::Apis::StorageV1
|
|
32
|
+
|
|
33
|
+
# @private
|
|
34
|
+
attr_accessor :project
|
|
35
|
+
|
|
36
|
+
# @private
|
|
37
|
+
attr_accessor :credentials
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Creates a new Service instance.
|
|
41
|
+
def initialize project, credentials, retries: nil, timeout: nil
|
|
42
|
+
@project = project
|
|
43
|
+
@credentials = credentials
|
|
44
|
+
@credentials = credentials
|
|
45
|
+
@service = API::StorageService.new
|
|
46
|
+
@service.client_options.application_name = "gcloud-ruby"
|
|
47
|
+
@service.client_options.application_version = Gcloud::VERSION
|
|
48
|
+
@service.request_options.retries = retries || 3
|
|
49
|
+
@service.request_options.timeout_sec = timeout if timeout
|
|
50
|
+
@service.authorization = @credentials.client
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def service
|
|
54
|
+
return mocked_service if mocked_service
|
|
55
|
+
@service
|
|
56
|
+
end
|
|
57
|
+
attr_accessor :mocked_service
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# Retrieves a list of buckets for the given project.
|
|
61
|
+
def list_buckets prefix: nil, token: nil, max: nil
|
|
62
|
+
service.list_buckets @project, prefix: prefix, page_token: token,
|
|
63
|
+
max_results: max
|
|
64
|
+
rescue Google::Apis::Error => e
|
|
65
|
+
raise Gcloud::Error.from_error(e)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# Retrieves bucket by name.
|
|
70
|
+
# Returns Google::Apis::StorageV1::Bucket.
|
|
71
|
+
def get_bucket bucket_name
|
|
72
|
+
service.get_bucket bucket_name
|
|
73
|
+
rescue Google::Apis::Error => e
|
|
74
|
+
raise Gcloud::Error.from_error(e)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
##
|
|
78
|
+
# Creates a new bucket.
|
|
79
|
+
# Returns Google::Apis::StorageV1::Bucket.
|
|
80
|
+
def insert_bucket bucket_gapi, options = {}
|
|
81
|
+
service.insert_bucket \
|
|
82
|
+
@project, bucket_gapi,
|
|
83
|
+
predefined_acl: options[:acl],
|
|
84
|
+
predefined_default_object_acl: options[:default_acl]
|
|
85
|
+
rescue Google::Apis::Error => e
|
|
86
|
+
raise Gcloud::Error.from_error(e)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
##
|
|
90
|
+
# Updates a bucket, including its ACL metadata.
|
|
91
|
+
def patch_bucket bucket_name, bucket_gapi = nil, predefined_acl: nil,
|
|
92
|
+
predefined_default_acl: nil
|
|
93
|
+
bucket_gapi ||= Google::Apis::StorageV1::Bucket.new
|
|
94
|
+
bucket_gapi.acl = nil if predefined_acl
|
|
95
|
+
bucket_gapi.default_object_acl = nil if predefined_default_acl
|
|
96
|
+
|
|
97
|
+
service.patch_bucket \
|
|
98
|
+
bucket_name, bucket_gapi,
|
|
99
|
+
predefined_acl: predefined_acl,
|
|
100
|
+
predefined_default_object_acl: predefined_default_acl
|
|
101
|
+
rescue Google::Apis::Error => e
|
|
102
|
+
raise Gcloud::Error.from_error(e)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
##
|
|
106
|
+
# Permanently deletes an empty bucket.
|
|
107
|
+
def delete_bucket bucket_name
|
|
108
|
+
service.delete_bucket bucket_name
|
|
109
|
+
rescue Google::Apis::Error => e
|
|
110
|
+
raise Gcloud::Error.from_error(e)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# Retrieves a list of ACLs for the given bucket.
|
|
115
|
+
def list_bucket_acls bucket_name
|
|
116
|
+
service.list_bucket_access_controls bucket_name
|
|
117
|
+
rescue Google::Apis::Error => e
|
|
118
|
+
raise Gcloud::Error.from_error(e)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Creates a new bucket ACL.
|
|
123
|
+
def insert_bucket_acl bucket_name, entity, role
|
|
124
|
+
new_acl = Google::Apis::StorageV1::BucketAccessControl.new \
|
|
125
|
+
entity: entity, role: role
|
|
126
|
+
service.insert_bucket_access_control bucket_name, new_acl
|
|
127
|
+
rescue Google::Apis::Error => e
|
|
128
|
+
raise Gcloud::Error.from_error(e)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# Permanently deletes a bucket ACL.
|
|
133
|
+
def delete_bucket_acl bucket_name, entity
|
|
134
|
+
service.delete_bucket_access_control bucket_name, entity
|
|
135
|
+
rescue Google::Apis::Error => e
|
|
136
|
+
raise Gcloud::Error.from_error(e)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
##
|
|
140
|
+
# Retrieves a list of default ACLs for the given bucket.
|
|
141
|
+
def list_default_acls bucket_name
|
|
142
|
+
service.list_default_object_access_controls bucket_name
|
|
143
|
+
rescue Google::Apis::Error => e
|
|
144
|
+
raise Gcloud::Error.from_error(e)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# Creates a new default ACL.
|
|
149
|
+
def insert_default_acl bucket_name, entity, role
|
|
150
|
+
new_acl = Google::Apis::StorageV1::ObjectAccessControl.new \
|
|
151
|
+
entity: entity, role: role
|
|
152
|
+
service.insert_default_object_access_control bucket_name, new_acl
|
|
153
|
+
rescue Google::Apis::Error => e
|
|
154
|
+
raise Gcloud::Error.from_error(e)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
##
|
|
158
|
+
# Permanently deletes a default ACL.
|
|
159
|
+
def delete_default_acl bucket_name, entity
|
|
160
|
+
service.delete_default_object_access_control bucket_name, entity
|
|
161
|
+
rescue Google::Apis::Error => e
|
|
162
|
+
raise Gcloud::Error.from_error(e)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
##
|
|
166
|
+
# Retrieves a list of files matching the criteria.
|
|
167
|
+
def list_files bucket_name, options = {}
|
|
168
|
+
service.list_objects \
|
|
169
|
+
bucket_name, delimiter: options[:delimiter],
|
|
170
|
+
max_results: options[:max], page_token: options[:token],
|
|
171
|
+
prefix: options[:prefix], versions: options[:versions]
|
|
172
|
+
rescue Google::Apis::Error => e
|
|
173
|
+
raise Gcloud::Error.from_error(e)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
##
|
|
177
|
+
# Inserts a new file for the given bucket
|
|
178
|
+
def insert_file bucket_name, source, path = nil, acl: nil,
|
|
179
|
+
cache_control: nil, content_disposition: nil,
|
|
180
|
+
content_encoding: nil, content_language: nil,
|
|
181
|
+
content_type: nil, crc32c: nil, md5: nil, metadata: nil,
|
|
182
|
+
key: nil, key_sha256: nil
|
|
183
|
+
file_obj = Google::Apis::StorageV1::Object.new \
|
|
184
|
+
cache_control: cache_control, content_type: content_type,
|
|
185
|
+
content_disposition: content_disposition, md5_hash: md5,
|
|
186
|
+
content_encoding: content_encoding, crc32c: crc32c,
|
|
187
|
+
content_language: content_language, metadata: metadata
|
|
188
|
+
content_type ||= mime_type_for(Pathname(source).to_path)
|
|
189
|
+
service.insert_object \
|
|
190
|
+
bucket_name, file_obj,
|
|
191
|
+
name: path, predefined_acl: acl, upload_source: source,
|
|
192
|
+
content_encoding: content_encoding, content_type: content_type,
|
|
193
|
+
options: key_options(key: key, key_sha256: key_sha256)
|
|
194
|
+
rescue Google::Apis::Error => e
|
|
195
|
+
raise Gcloud::Error.from_error(e)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
##
|
|
199
|
+
# Retrieves an object or its metadata.
|
|
200
|
+
def get_file bucket_name, file_path, generation: nil, key: nil,
|
|
201
|
+
key_sha256: nil
|
|
202
|
+
service.get_object \
|
|
203
|
+
bucket_name, file_path,
|
|
204
|
+
generation: generation,
|
|
205
|
+
options: key_options(key: key, key_sha256: key_sha256)
|
|
206
|
+
rescue Google::Apis::Error => e
|
|
207
|
+
raise Gcloud::Error.from_error(e)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
## Copy a file from source bucket/object to a
|
|
211
|
+
# destination bucket/object.
|
|
212
|
+
def copy_file source_bucket_name, source_file_path,
|
|
213
|
+
destination_bucket_name, destination_file_path, options = {}
|
|
214
|
+
service.copy_object \
|
|
215
|
+
source_bucket_name, source_file_path,
|
|
216
|
+
destination_bucket_name, destination_file_path,
|
|
217
|
+
destination_predefined_acl: options[:acl],
|
|
218
|
+
source_generation: options[:generation],
|
|
219
|
+
options: key_options(key: options[:key],
|
|
220
|
+
key_sha256: options[:key_sha256])
|
|
221
|
+
rescue Google::Apis::Error => e
|
|
222
|
+
raise Gcloud::Error.from_error(e)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
##
|
|
226
|
+
# Download contents of a file.
|
|
227
|
+
def download_file bucket_name, file_path, target_path, generation: nil,
|
|
228
|
+
key: nil, key_sha256: nil
|
|
229
|
+
service.get_object \
|
|
230
|
+
bucket_name, file_path,
|
|
231
|
+
download_dest: target_path, generation: generation,
|
|
232
|
+
options: key_options(key: key, key_sha256: key_sha256)
|
|
233
|
+
rescue Google::Apis::Error => e
|
|
234
|
+
raise Gcloud::Error.from_error(e)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
##
|
|
238
|
+
# Updates a file's metadata.
|
|
239
|
+
def patch_file bucket_name, file_path, file_gapi = nil,
|
|
240
|
+
predefined_acl: nil
|
|
241
|
+
file_gapi ||= Google::Apis::StorageV1::Object.new
|
|
242
|
+
service.patch_object \
|
|
243
|
+
bucket_name, file_path, file_gapi,
|
|
244
|
+
predefined_acl: predefined_acl
|
|
245
|
+
rescue Google::Apis::Error => e
|
|
246
|
+
raise Gcloud::Error.from_error(e)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
##
|
|
250
|
+
# Permanently deletes a file.
|
|
251
|
+
def delete_file bucket_name, file_path
|
|
252
|
+
service.delete_object bucket_name, file_path
|
|
253
|
+
rescue Google::Apis::Error => e
|
|
254
|
+
raise Gcloud::Error.from_error(e)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
##
|
|
258
|
+
# Retrieves a list of ACLs for the given file.
|
|
259
|
+
def list_file_acls bucket_name, file_name
|
|
260
|
+
service.list_object_access_controls bucket_name, file_name
|
|
261
|
+
rescue Google::Apis::Error => e
|
|
262
|
+
raise Gcloud::Error.from_error(e)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
##
|
|
266
|
+
# Creates a new file ACL.
|
|
267
|
+
def insert_file_acl bucket_name, file_name, entity, role, options = {}
|
|
268
|
+
new_acl = Google::Apis::StorageV1::ObjectAccessControl.new \
|
|
269
|
+
entity: entity, role: role
|
|
270
|
+
service.insert_object_access_control \
|
|
271
|
+
bucket_name, file_name, new_acl, generation: options[:generation]
|
|
272
|
+
rescue Google::Apis::Error => e
|
|
273
|
+
raise Gcloud::Error.from_error(e)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
##
|
|
277
|
+
# Permanently deletes a file ACL.
|
|
278
|
+
def delete_file_acl bucket_name, file_name, entity, options = {}
|
|
279
|
+
service.delete_object_access_control \
|
|
280
|
+
bucket_name, file_name, entity, generation: options[:generation]
|
|
281
|
+
rescue Google::Apis::Error => e
|
|
282
|
+
raise Gcloud::Error.from_error(e)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
##
|
|
286
|
+
# Retrieves the mime-type for a file path.
|
|
287
|
+
# An empty string is returned if no mime-type can be found.
|
|
288
|
+
def mime_type_for path
|
|
289
|
+
MIME::Types.of(path).first.to_s
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# @private
|
|
293
|
+
def inspect
|
|
294
|
+
"#{self.class}(#{@project})"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
protected
|
|
298
|
+
|
|
299
|
+
def key_options key: nil, key_sha256: nil
|
|
300
|
+
options = {}
|
|
301
|
+
if key
|
|
302
|
+
headers = {}
|
|
303
|
+
headers["x-goog-encryption-algorithm"] = "AES256"
|
|
304
|
+
headers["x-goog-encryption-key"] = Base64.strict_encode64 key
|
|
305
|
+
key_sha256 ||= Digest::SHA256.digest key
|
|
306
|
+
headers["x-goog-encryption-key-sha256"] = \
|
|
307
|
+
Base64.strict_encode64 key_sha256
|
|
308
|
+
options[:header] = headers
|
|
309
|
+
end
|
|
310
|
+
options
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def patch_bucket_request options = {}
|
|
314
|
+
{
|
|
315
|
+
"cors" => options[:cors],
|
|
316
|
+
"logging" => logging_config(options),
|
|
317
|
+
"versioning" => versioning_config(options[:versioning]),
|
|
318
|
+
"website" => website_config(options),
|
|
319
|
+
"acl" => options[:acl],
|
|
320
|
+
"defaultObjectAcl" => options[:default_acl]
|
|
321
|
+
}.delete_if { |_, v| v.nil? }
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def versioning_config enabled
|
|
325
|
+
{ "enabled" => enabled } unless enabled.nil?
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def logging_config options
|
|
329
|
+
bucket = options[:logging_bucket]
|
|
330
|
+
prefix = options[:logging_prefix]
|
|
331
|
+
{
|
|
332
|
+
log_bucket: bucket,
|
|
333
|
+
log_object_prefix: prefix
|
|
334
|
+
}.delete_if { |_, v| v.nil? } if bucket || prefix
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def website_config options
|
|
338
|
+
website_main = options[:website_main]
|
|
339
|
+
website_404 = options[:website_404]
|
|
340
|
+
{
|
|
341
|
+
main_page_suffix: website_main,
|
|
342
|
+
not_found_page: website_404
|
|
343
|
+
}.delete_if { |_, v| v.nil? } if website_main || website_404
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|