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.
Files changed (121) hide show
  1. checksums.yaml +8 -8
  2. data/AUTHENTICATION.md +3 -3
  3. data/CHANGELOG.md +92 -0
  4. data/OVERVIEW.md +3 -3
  5. data/lib/gcloud.rb +75 -25
  6. data/lib/gcloud/backoff.rb +5 -1
  7. data/lib/gcloud/bigquery.rb +25 -43
  8. data/lib/gcloud/bigquery/copy_job.rb +13 -13
  9. data/lib/gcloud/bigquery/data.rb +20 -16
  10. data/lib/gcloud/bigquery/dataset.rb +202 -177
  11. data/lib/gcloud/bigquery/dataset/access.rb +118 -104
  12. data/lib/gcloud/bigquery/dataset/list.rb +14 -18
  13. data/lib/gcloud/bigquery/extract_job.rb +12 -12
  14. data/lib/gcloud/bigquery/insert_response.rb +12 -14
  15. data/lib/gcloud/bigquery/job.rb +45 -57
  16. data/lib/gcloud/bigquery/job/list.rb +18 -24
  17. data/lib/gcloud/bigquery/load_job.rb +35 -27
  18. data/lib/gcloud/bigquery/project.rb +53 -73
  19. data/lib/gcloud/bigquery/query_data.rb +28 -35
  20. data/lib/gcloud/bigquery/query_job.rb +18 -18
  21. data/lib/gcloud/bigquery/schema.rb +359 -0
  22. data/lib/gcloud/bigquery/service.rb +506 -0
  23. data/lib/gcloud/bigquery/table.rb +185 -266
  24. data/lib/gcloud/bigquery/table/list.rb +15 -19
  25. data/lib/gcloud/bigquery/view.rb +126 -81
  26. data/lib/gcloud/datastore.rb +39 -27
  27. data/lib/gcloud/datastore/commit.rb +2 -2
  28. data/lib/gcloud/datastore/dataset.rb +8 -19
  29. data/lib/gcloud/datastore/dataset/lookup_results.rb +2 -4
  30. data/lib/gcloud/datastore/dataset/query_results.rb +0 -2
  31. data/lib/gcloud/datastore/entity.rb +7 -1
  32. data/lib/gcloud/datastore/errors.rb +5 -27
  33. data/lib/gcloud/datastore/grpc_utils.rb +4 -3
  34. data/lib/gcloud/datastore/key.rb +6 -0
  35. data/lib/gcloud/datastore/service.rb +18 -12
  36. data/lib/gcloud/datastore/transaction.rb +0 -10
  37. data/lib/gcloud/dns.rb +29 -19
  38. data/lib/gcloud/dns/change.rb +10 -15
  39. data/lib/gcloud/dns/change/list.rb +4 -4
  40. data/lib/gcloud/dns/importer.rb +1 -1
  41. data/lib/gcloud/dns/project.rb +32 -49
  42. data/lib/gcloud/dns/record.rb +8 -2
  43. data/lib/gcloud/dns/record/list.rb +4 -4
  44. data/lib/gcloud/dns/service.rb +167 -0
  45. data/lib/gcloud/dns/zone.rb +33 -52
  46. data/lib/gcloud/dns/zone/list.rb +12 -16
  47. data/lib/gcloud/errors.rb +31 -19
  48. data/lib/gcloud/logging.rb +50 -39
  49. data/lib/gcloud/logging/entry.rb +197 -24
  50. data/lib/gcloud/logging/entry/list.rb +0 -2
  51. data/lib/gcloud/logging/logger.rb +1 -1
  52. data/lib/gcloud/logging/metric.rb +3 -9
  53. data/lib/gcloud/logging/metric/list.rb +0 -2
  54. data/lib/gcloud/logging/project.rb +58 -54
  55. data/lib/gcloud/logging/resource_descriptor.rb +2 -2
  56. data/lib/gcloud/logging/resource_descriptor/list.rb +0 -2
  57. data/lib/gcloud/logging/service.rb +32 -23
  58. data/lib/gcloud/logging/sink.rb +8 -14
  59. data/lib/gcloud/logging/sink/list.rb +0 -2
  60. data/lib/gcloud/pubsub.rb +21 -16
  61. data/lib/gcloud/pubsub/policy.rb +204 -0
  62. data/lib/gcloud/pubsub/project.rb +26 -38
  63. data/lib/gcloud/pubsub/service.rb +39 -31
  64. data/lib/gcloud/pubsub/subscription.rb +56 -59
  65. data/lib/gcloud/pubsub/subscription/list.rb +4 -4
  66. data/lib/gcloud/pubsub/topic.rb +69 -66
  67. data/lib/gcloud/pubsub/topic/list.rb +0 -2
  68. data/lib/gcloud/pubsub/topic/{batch.rb → publisher.rb} +15 -2
  69. data/lib/gcloud/resource_manager.rb +27 -26
  70. data/lib/gcloud/resource_manager/manager.rb +19 -39
  71. data/lib/gcloud/resource_manager/policy.rb +211 -0
  72. data/lib/gcloud/resource_manager/project.rb +97 -121
  73. data/lib/gcloud/resource_manager/project/list.rb +7 -7
  74. data/lib/gcloud/resource_manager/project/updater.rb +4 -9
  75. data/lib/gcloud/resource_manager/service.rb +127 -0
  76. data/lib/gcloud/storage.rb +24 -42
  77. data/lib/gcloud/storage/bucket.rb +104 -192
  78. data/lib/gcloud/storage/bucket/acl.rb +47 -143
  79. data/lib/gcloud/storage/bucket/cors.rb +55 -11
  80. data/lib/gcloud/storage/bucket/list.rb +14 -14
  81. data/lib/gcloud/storage/errors.rb +3 -43
  82. data/lib/gcloud/storage/file.rb +114 -111
  83. data/lib/gcloud/storage/file/acl.rb +27 -113
  84. data/lib/gcloud/storage/file/list.rb +21 -21
  85. data/lib/gcloud/storage/project.rb +49 -59
  86. data/lib/gcloud/storage/service.rb +347 -0
  87. data/lib/gcloud/translate.rb +24 -14
  88. data/lib/gcloud/translate/api.rb +12 -21
  89. data/lib/gcloud/translate/detection.rb +5 -5
  90. data/lib/gcloud/translate/language.rb +1 -1
  91. data/lib/gcloud/translate/service.rb +80 -0
  92. data/lib/gcloud/translate/translation.rb +6 -6
  93. data/lib/gcloud/version.rb +1 -1
  94. data/lib/gcloud/vision.rb +24 -15
  95. data/lib/gcloud/vision/annotate.rb +24 -21
  96. data/lib/gcloud/vision/annotation.rb +9 -9
  97. data/lib/gcloud/vision/annotation/entity.rb +11 -11
  98. data/lib/gcloud/vision/annotation/face.rb +25 -25
  99. data/lib/gcloud/vision/annotation/properties.rb +8 -8
  100. data/lib/gcloud/vision/annotation/safe_search.rb +4 -4
  101. data/lib/gcloud/vision/annotation/text.rb +7 -7
  102. data/lib/gcloud/vision/annotation/vertex.rb +1 -1
  103. data/lib/gcloud/vision/image.rb +11 -11
  104. data/lib/gcloud/vision/location.rb +5 -2
  105. data/lib/gcloud/vision/project.rb +14 -16
  106. data/lib/gcloud/vision/service.rb +66 -0
  107. data/lib/google/api_client.rb +0 -0
  108. metadata +27 -24
  109. data/lib/gcloud/bigquery/connection.rb +0 -624
  110. data/lib/gcloud/bigquery/errors.rb +0 -68
  111. data/lib/gcloud/bigquery/table/schema.rb +0 -234
  112. data/lib/gcloud/dns/connection.rb +0 -173
  113. data/lib/gcloud/dns/errors.rb +0 -68
  114. data/lib/gcloud/resource_manager/connection.rb +0 -134
  115. data/lib/gcloud/resource_manager/errors.rb +0 -68
  116. data/lib/gcloud/storage/connection.rb +0 -444
  117. data/lib/gcloud/translate/connection.rb +0 -85
  118. data/lib/gcloud/translate/errors.rb +0 -68
  119. data/lib/gcloud/upload.rb +0 -95
  120. data/lib/gcloud/vision/connection.rb +0 -63
  121. 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
- @connection = file.connection
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
- resp = @connection.list_file_acls @bucket, @file
81
- acls = resp.data["items"]
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
- resp = @connection.insert_file_acl @bucket, @file, entity,
196
- "OWNER", options
197
- if resp.success?
198
- entity = resp.data["entity"]
199
- @owners.push entity unless @owners.nil?
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
- resp = @connection.insert_file_acl @bucket, @file, entity,
304
- "READER", options
305
- if resp.success?
306
- entity = resp.data["entity"]
307
- @readers.push entity unless @readers.nil?
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
- resp = @connection.delete_file_acl @bucket, @file, entity, options
346
- if resp.success?
347
- @owners.delete entity unless @owners.nil?
348
- @writers.delete entity unless @writers.nil?
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
- resp = @connection.patch_file @bucket, @file,
496
- predefined_acl: acl_role,
497
- acl: []
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["role"] == role }
505
- entities = selected.map { |acl| acl["entity"] }
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
- ensure_connection!
80
+ ensure_service!
81
81
  options = {
82
82
  prefix: @prefix, delimiter: @delimiter, token: @token, max: @max,
83
83
  versions: @versions
84
84
  }
85
- resp = @connection.list_files @bucket, options
86
- fail ApiError.from_response(resp) unless resp.success?
87
- File::List.from_response resp, @connection, @bucket, @prefix,
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 response object.
165
- def self.from_response resp, conn, bucket = nil, prefix = nil,
166
- delimiter = nil, max = nil, versions = nil
167
- files = new(Array(resp.data["items"]).map do |gapi_object|
168
- File.from_gapi gapi_object, conn
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 "@token", resp.data["nextPageToken"]
171
- files.instance_variable_set "@prefixes", Array(resp.data["prefixes"])
172
- files.instance_variable_set "@connection", conn
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
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 connection is available.
185
- def ensure_connection!
186
- fail "Must have active connection" unless @connection
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/connection"
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 Connection object.
52
- attr_accessor :connection
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 project, credentials
59
- project = project.to_s # Always cast to a string
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
- connection.project
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
- resp = connection.list_buckets options
137
- if resp.success?
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
- resp = connection.get_bucket bucket_name
164
- if resp.success?
165
- Bucket.from_gapi resp.data, connection
166
- else
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::Backoff} to control this behavior.
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 [cors] a block for setting CORS rules
264
- # @yieldparam [Bucket::Cors] cors the object accepting CORS rules
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 Add CORS rules in a block:
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
- # options = {
283
- # website_main: "index.html"
284
- # website_404: "not_found.html"
285
- # }
286
- # bucket = storage.create_bucket "my-bucket", options do |c|
287
- # c.add_rule ["http://example.org", "https://example.org"],
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, cors: nil,
294
- location: nil, logging_bucket: nil, logging_prefix: nil,
295
- storage_class: nil, versioning: nil, website_main: nil,
296
- website_404: nil
297
- opts = { acl: acl_rule(acl), default_acl: acl_rule(default_acl),
298
- cors: cors, location: location, logging_bucket: logging_bucket,
299
- logging_prefix: logging_prefix, storage_class: storage_class,
300
- versioning: versioning, website_main: website_main,
301
- website_404: website_404 }
302
- if block_given?
303
- cors_builder = Bucket::Cors.new
304
- yield cors_builder
305
- opts[:cors] = cors_builder if cors_builder.changed?
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
- insert_bucket bucket_name, opts
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 insert_bucket bucket_name, options
317
- resp = connection.insert_bucket bucket_name, options
318
- if resp.success?
319
- Bucket.from_gapi resp.data, connection
320
- else
321
- fail ApiError.from_response(resp)
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