gcloud 0.10.0 → 0.11.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 (59) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +36 -0
  3. data/lib/gcloud/backoff.rb +5 -5
  4. data/lib/gcloud/bigquery.rb +24 -0
  5. data/lib/gcloud/bigquery/connection.rb +32 -25
  6. data/lib/gcloud/bigquery/data.rb +99 -1
  7. data/lib/gcloud/bigquery/dataset.rb +5 -13
  8. data/lib/gcloud/bigquery/dataset/list.rb +124 -2
  9. data/lib/gcloud/bigquery/job/list.rb +125 -2
  10. data/lib/gcloud/bigquery/project.rb +30 -27
  11. data/lib/gcloud/bigquery/query_data.rb +102 -1
  12. data/lib/gcloud/bigquery/table.rb +17 -2
  13. data/lib/gcloud/bigquery/table/list.rb +132 -3
  14. data/lib/gcloud/datastore.rb +30 -19
  15. data/lib/gcloud/datastore/dataset.rb +2 -22
  16. data/lib/gcloud/datastore/dataset/lookup_results.rb +160 -4
  17. data/lib/gcloud/datastore/dataset/query_results.rb +229 -23
  18. data/lib/gcloud/datastore/transaction.rb +2 -5
  19. data/lib/gcloud/dns.rb +20 -0
  20. data/lib/gcloud/dns/change/list.rb +109 -6
  21. data/lib/gcloud/dns/connection.rb +18 -9
  22. data/lib/gcloud/dns/project.rb +4 -8
  23. data/lib/gcloud/dns/record/list.rb +96 -13
  24. data/lib/gcloud/dns/zone.rb +9 -24
  25. data/lib/gcloud/dns/zone/list.rb +102 -5
  26. data/lib/gcloud/dns/zone/transaction.rb +1 -1
  27. data/lib/gcloud/logging.rb +19 -0
  28. data/lib/gcloud/logging/entry/list.rb +83 -14
  29. data/lib/gcloud/logging/metric/list.rb +89 -12
  30. data/lib/gcloud/logging/project.rb +18 -30
  31. data/lib/gcloud/logging/resource_descriptor/list.rb +105 -6
  32. data/lib/gcloud/logging/sink/list.rb +89 -12
  33. data/lib/gcloud/pubsub.rb +23 -0
  34. data/lib/gcloud/pubsub/project.rb +21 -29
  35. data/lib/gcloud/pubsub/service.rb +1 -3
  36. data/lib/gcloud/pubsub/subscription/list.rb +167 -13
  37. data/lib/gcloud/pubsub/topic.rb +15 -13
  38. data/lib/gcloud/pubsub/topic/batch.rb +10 -4
  39. data/lib/gcloud/pubsub/topic/list.rb +134 -8
  40. data/lib/gcloud/resource_manager.rb +24 -0
  41. data/lib/gcloud/resource_manager/connection.rb +18 -9
  42. data/lib/gcloud/resource_manager/manager.rb +7 -4
  43. data/lib/gcloud/resource_manager/project/list.rb +93 -14
  44. data/lib/gcloud/storage.rb +63 -0
  45. data/lib/gcloud/storage/bucket.rb +100 -61
  46. data/lib/gcloud/storage/bucket/list.rb +132 -8
  47. data/lib/gcloud/storage/connection.rb +68 -44
  48. data/lib/gcloud/storage/errors.rb +9 -3
  49. data/lib/gcloud/storage/file.rb +48 -4
  50. data/lib/gcloud/storage/file/list.rb +151 -15
  51. data/lib/gcloud/storage/file/verifier.rb +3 -3
  52. data/lib/gcloud/storage/project.rb +15 -30
  53. data/lib/gcloud/translate.rb +20 -0
  54. data/lib/gcloud/translate/connection.rb +12 -3
  55. data/lib/gcloud/version.rb +1 -1
  56. data/lib/gcloud/vision.rb +20 -0
  57. data/lib/gcloud/vision/connection.rb +10 -1
  58. data/lib/gcloud/vision/image.rb +15 -18
  59. metadata +16 -2
@@ -28,12 +28,26 @@ module Gcloud
28
28
  # Many common Array methods will return a new Array instance.
29
29
  #
30
30
  # @example
31
+ # require "gcloud"
32
+ #
33
+ # gcloud = Gcloud.new
34
+ # datastore = gcloud.datastore
35
+ #
36
+ # query = datastore.query("Task")
31
37
  # tasks = datastore.run query
38
+ #
32
39
  # tasks.size #=> 3
33
40
  # tasks.cursor #=> Gcloud::Datastore::Cursor(c3VwZXJhd2Vzb21lIQ)
34
41
  #
35
42
  # @example Caution, many Array methods will return a new Array instance:
43
+ # require "gcloud"
44
+ #
45
+ # gcloud = Gcloud.new
46
+ # datastore = gcloud.datastore
47
+ #
48
+ # query = datastore.query("Task")
36
49
  # tasks = datastore.run query
50
+ #
37
51
  # tasks.size #=> 3
38
52
  # tasks.end_cursor #=> Gcloud::Datastore::Cursor(c3VwZXJhd2Vzb21lIQ)
39
53
  # descriptions = tasks.map { |task| task["description"] }
@@ -61,7 +75,7 @@ module Gcloud
61
75
 
62
76
  ##
63
77
  # @private
64
- attr_accessor :service, :namespace, :query
78
+ attr_accessor :service, :namespace, :cursors, :query
65
79
 
66
80
  ##
67
81
  # @private
@@ -96,19 +110,49 @@ module Gcloud
96
110
  end
97
111
 
98
112
  ##
99
- # Create a new QueryResults with an array of values.
113
+ # @private Create a new QueryResults with an array of values.
100
114
  def initialize arr = []
101
115
  super arr
102
116
  end
103
117
 
104
118
  ##
105
119
  # Whether there are more results available.
120
+ #
121
+ # @return [Boolean]
122
+ #
123
+ # @example
124
+ # require "gcloud"
125
+ #
126
+ # gcloud = Gcloud.new
127
+ # datastore = gcloud.datastore
128
+ # query = datastore.query "Task"
129
+ # tasks = datastore.run query
130
+ #
131
+ # if tasks.next?
132
+ # next_tasks = tasks.next
133
+ # end
134
+ #
106
135
  def next?
107
136
  !no_more?
108
137
  end
109
138
 
110
139
  ##
111
140
  # Retrieve the next page of results.
141
+ #
142
+ # @return [QueryResults]
143
+ #
144
+ # @example
145
+ # require "gcloud"
146
+ #
147
+ # gcloud = Gcloud.new
148
+ # datastore = gcloud.datastore
149
+ # query = datastore.query "Task"
150
+ # tasks = datastore.run query
151
+ #
152
+ # if tasks.next?
153
+ # next_tasks = tasks.next
154
+ # end
155
+ #
112
156
  def next
113
157
  return nil unless next?
114
158
  return nil if end_cursor.nil?
@@ -120,45 +164,207 @@ module Gcloud
120
164
  raise Gcloud::Error.from_error(e)
121
165
  end
122
166
 
167
+ ##
168
+ # Retrieve the {Cursor} for the provided result.
169
+ #
170
+ # @param [Entity] result The entity object to get a cursor for.
171
+ #
172
+ # @return [Cursor]
173
+ #
174
+ # @example
175
+ # require "gcloud"
176
+ #
177
+ # gcloud = Gcloud.new
178
+ # datastore = gcloud.datastore
179
+ # query = datastore.query "Task"
180
+ # tasks = datastore.run query
181
+ #
182
+ # first_task = tasks.first
183
+ # first_cursor = tasks.cursor_for first_task
184
+ #
185
+ def cursor_for result
186
+ cursor_index = index result
187
+ return nil if cursor_index.nil?
188
+ cursors[cursor_index]
189
+ end
190
+
191
+ ##
192
+ # Calls the given block once for each result and cursor combination,
193
+ # which are passed as parameters.
194
+ #
195
+ # An Enumerator is returned if no block is given.
196
+ #
197
+ # @yield [result, cursor] The block for accessing each query result and
198
+ # cursor.
199
+ # @yieldparam [Entity] result The query result object.
200
+ # @yieldparam [Cursor] cursor The cursor object.
201
+ #
202
+ # @return [Enumerator]
203
+ #
204
+ # @example
205
+ # require "gcloud"
206
+ #
207
+ # gcloud = Gcloud.new
208
+ # datastore = gcloud.datastore
209
+ # query = datastore.query "Task"
210
+ # tasks = datastore.run query
211
+ # tasks.each_with_cursor do |task, cursor|
212
+ # puts "Task #{task.key.id} (#cursor)"
213
+ # end
214
+ #
215
+ def each_with_cursor
216
+ return enum_for(:each_with_cursor) unless block_given?
217
+ zip(cursors).each { |r, c| yield [r, c] }
218
+ end
219
+
123
220
  ##
124
221
  # Retrieves all query results by repeatedly loading {#next} until
125
- # {#next?} returns `false`. Returns the list instance for method
126
- # chaining.
222
+ # {#next?} returns `false`. Calls the given block once for each query
223
+ # result, which is passed as the parameter.
224
+ #
225
+ # An Enumerator is returned if no block is given.
127
226
  #
128
227
  # This method may make several API calls until all query results are
129
228
  # retrieved. Be sure to use as narrow a search criteria as possible.
130
229
  # Please use with caution.
131
230
  #
132
- # @example
231
+ # @param [Integer] request_limit The upper limit of API requests to make
232
+ # to load all query results. Default is no limit.
233
+ # @yield [result] The block for accessing each query result.
234
+ # @yieldparam [Entity] result The query result object.
235
+ #
236
+ # @return [Enumerator]
237
+ #
238
+ # @example Iterating each query result by passing a block:
239
+ # require "gcloud"
240
+ #
241
+ # gcloud = Gcloud.new
242
+ # datastore = gcloud.datastore
243
+ # query = datastore.query "Task"
244
+ # tasks = datastore.run query
245
+ # tasks.all do |task|
246
+ # puts "Task #{task.key.id} (#cursor)"
247
+ # end
248
+ #
249
+ # @example Using the enumerator by not passing a block:
250
+ # require "gcloud"
251
+ #
252
+ # gcloud = Gcloud.new
253
+ # datastore = gcloud.datastore
254
+ # query = datastore.query "Task"
255
+ # tasks = datastore.run query
256
+ # tasks.all.map(&:key).each do |key|
257
+ # puts "Key #{key.id}"
258
+ # end
259
+ #
260
+ # @example Limit the number of API calls made:
261
+ # require "gcloud"
262
+ #
263
+ # gcloud = Gcloud.new
264
+ # datastore = gcloud.datastore
265
+ # query = datastore.query "Task"
266
+ # tasks = datastore.run query
267
+ # tasks.all(request_limit: 10) do |task|
268
+ # puts "Task #{task.key.id} (#cursor)"
269
+ # end
270
+ #
271
+ def all request_limit: nil
272
+ request_limit = request_limit.to_i if request_limit
273
+ unless block_given?
274
+ return enum_for(:all, request_limit: request_limit)
275
+ end
276
+ results = self
277
+ loop do
278
+ results.each { |r| yield r }
279
+ if request_limit
280
+ request_limit -= 1
281
+ break if request_limit < 0
282
+ end
283
+ break unless results.next?
284
+ results = results.next
285
+ end
286
+ end
287
+
288
+ ##
289
+ # Retrieves all query results and cursors by repeatedly loading {#next}
290
+ # until {#next?} returns `false`. Calls the given block once for each
291
+ # result and cursor combination, which are passed as parameters.
292
+ #
293
+ # An Enumerator is returned if no block is given.
294
+ #
295
+ # This method may make several API calls until all query results are
296
+ # retrieved. Be sure to use as narrow a search criteria as possible.
297
+ # Please use with caution.
298
+ #
299
+ # @param [Integer] request_limit The upper limit of API requests to make
300
+ # to load all tables. Default is no limit.
301
+ # @yield [result, cursor] The block for accessing each query result and
302
+ # cursor.
303
+ # @yieldparam [Entity] result The query result object.
304
+ # @yieldparam [Cursor] cursor The cursor object.
305
+ #
306
+ # @return [Enumerator]
307
+ #
308
+ # @example Iterating all results and cursors by passing a block:
309
+ # require "gcloud"
310
+ #
311
+ # gcloud = Gcloud.new
312
+ # datastore = gcloud.datastore
313
+ # query = datastore.query "Task"
314
+ # tasks = datastore.run query
315
+ # tasks.all_with_cursor do |task, cursor|
316
+ # puts "Task #{task.key.id} (#cursor)"
317
+ # end
318
+ #
319
+ # @example Using the enumerator by not passing a block:
320
+ # require "gcloud"
321
+ #
322
+ # gcloud = Gcloud.new
323
+ # datastore = gcloud.datastore
324
+ # query = datastore.query "Task"
325
+ # tasks = datastore.run query
326
+ # tasks.all_with_cursor.count #=> number of result/cursor pairs
327
+ #
328
+ # @example Limit the number of API calls made:
133
329
  # require "gcloud"
134
330
  #
135
331
  # gcloud = Gcloud.new
136
332
  # datastore = gcloud.datastore
137
- # query = datastore.query("Tasks")
138
- # all_tasks = datastore.run(query).all
139
- #
140
- def all
141
- while next?
142
- next_records = self.next
143
- push(*next_records)
144
- self.end_cursor = next_records.end_cursor
145
- self.more_results = next_records.more_results
146
- self.service = next_records.service
147
- self.namespace = next_records.namespace
148
- self.query = next_records.query
333
+ # query = datastore.query "Task"
334
+ # tasks = datastore.run query
335
+ # tasks.all_with_cursor(request_limit: 10) do |task, cursor|
336
+ # puts "Task #{task.key.id} (#cursor)"
337
+ # end
338
+ #
339
+ def all_with_cursor request_limit: nil
340
+ request_limit = request_limit.to_i if request_limit
341
+ unless block_given?
342
+ return enum_for(:all_with_cursor, request_limit: request_limit)
343
+ end
344
+ results = self
345
+
346
+ loop do
347
+ results.zip(results.cursors).each { |r, c| yield r, c }
348
+ if request_limit
349
+ request_limit -= 1
350
+ break if request_limit < 0
351
+ end
352
+ break unless results.next?
353
+ results = results.next
149
354
  end
150
- self
151
355
  end
152
356
 
153
357
  ##
154
358
  # @private New Dataset::QueryResults from a
155
359
  # Google::Dataset::V1beta3::RunQueryResponse object.
156
360
  def self.from_grpc query_res, service, namespace, query
157
- entities = Array(query_res.batch.entity_results).map do |result|
158
- # TODO: Make this return an EntityResult with cursor...
159
- Entity.from_grpc result.entity
160
- end
161
- new(entities).tap do |qr|
361
+ r, c = Array(query_res.batch.entity_results).map do |result|
362
+ [Entity.from_grpc(result.entity), Cursor.from_grpc(result.cursor)]
363
+ end.transpose
364
+ r ||= []
365
+ c ||= []
366
+ new(r).tap do |qr|
367
+ qr.cursors = c
162
368
  qr.end_cursor = Cursor.from_grpc query_res.batch.end_cursor
163
369
  qr.more_results = query_res.batch.more_results
164
370
  qr.service = service
@@ -198,12 +198,9 @@ module Gcloud
198
198
  #
199
199
  def find_all *keys
200
200
  ensure_service!
201
- lookup_res = service.lookup(*keys.map(&:to_grpc),
201
+ lookup_res = service.lookup(*Array(keys).flatten.map(&:to_grpc),
202
202
  transaction: @id)
203
- entities = to_gcloud_entities lookup_res.found
204
- deferred = to_gcloud_keys lookup_res.deferred
205
- missing = to_gcloud_entities lookup_res.missing
206
- LookupResults.new entities, deferred, missing
203
+ LookupResults.from_grpc lookup_res, service, nil, @id
207
204
  rescue GRPC::BadStatus => e
208
205
  raise Gcloud::Error.from_error(e)
209
206
  end
data/lib/gcloud/dns.rb CHANGED
@@ -301,6 +301,26 @@ module Gcloud
301
301
  # zone.export "path/to/db.example.com"
302
302
  # ```
303
303
  #
304
+ # ## Configuring Backoff
305
+ #
306
+ # The {Gcloud::Backoff} class allows users to globally configure how Cloud API
307
+ # requests are automatically retried in the case of some errors, such as a
308
+ # `500` or `503` status code, or a specific internal error code such as
309
+ # `rateLimitExceeded`.
310
+ #
311
+ # If an API call fails, the response will be inspected to see if the call
312
+ # should be retried. If the response matches the criteria, then the request
313
+ # will be retried after a delay. If another error occurs, the delay will be
314
+ # increased incrementally before a subsequent attempt. The first retry will be
315
+ # delayed one second, the second retry two seconds, and so on.
316
+ #
317
+ # ```ruby
318
+ # require "gcloud"
319
+ # require "gcloud/backoff"
320
+ #
321
+ # Gcloud::Backoff.retries = 5 # Raise the maximum number of retries from 3
322
+ # ```
323
+ #
304
324
  module Dns
305
325
  end
306
326
  end
@@ -22,38 +22,141 @@ module Gcloud
22
22
  # Change::List is a special case Array with additional values.
23
23
  class List < DelegateClass(::Array)
24
24
  ##
25
- # If not empty, indicates that there are more records that match
25
+ # If not empty, indicates that there are more changes that match
26
26
  # the request and this value should be passed to continue.
27
27
  attr_accessor :token
28
28
 
29
29
  ##
30
- # Create a new Change::List with an array of Change instances.
30
+ # @private Create a new Change::List with an array of Change instances.
31
31
  def initialize arr = []
32
32
  super arr
33
33
  end
34
34
 
35
35
  ##
36
- # Whether there a next page of zones.
36
+ # Whether there a next page of changes.
37
+ #
38
+ # @return [Boolean]
39
+ #
40
+ # @example
41
+ # require "gcloud"
42
+ #
43
+ # gcloud = Gcloud.new
44
+ # dns = gcloud.dns
45
+ # zone = dns.zone "example-com"
46
+ #
47
+ # changes = zone.changes
48
+ # if changes.next?
49
+ # next_changes = changes.next
50
+ # end
51
+ #
37
52
  def next?
38
53
  !token.nil?
39
54
  end
40
55
 
41
56
  ##
42
- # Retrieve the next page of zones.
57
+ # Retrieve the next page of changes.
58
+ #
59
+ # @return [Change::List]
60
+ #
61
+ # @example
62
+ # require "gcloud"
63
+ #
64
+ # gcloud = Gcloud.new
65
+ # dns = gcloud.dns
66
+ # zone = dns.zone "example-com"
67
+ #
68
+ # changes = zone.changes
69
+ # if changes.next?
70
+ # next_changes = changes.next
71
+ # end
72
+ #
43
73
  def next
44
74
  return nil unless next?
45
75
  ensure_zone!
46
- @zone.changes token: token
76
+ @zone.changes token: token, max: @max, order: @order
77
+ end
78
+
79
+ ##
80
+ # Retrieves all changes by repeatedly loading {#next} until {#next?}
81
+ # returns `false`. Calls the given block once for each change, which is
82
+ # passed as the parameter.
83
+ #
84
+ # An Enumerator is returned if no block is given.
85
+ #
86
+ # This method may make several API calls until all changes are
87
+ # retrieved. Be sure to use as narrow a search criteria as possible.
88
+ # Please use with caution.
89
+ #
90
+ # @param [Integer] request_limit The upper limit of API requests to make
91
+ # to load all changes. Default is no limit.
92
+ # @yield [change] The block for accessing each change.
93
+ # @yieldparam [Change] change The change object.
94
+ #
95
+ # @return [Enumerator]
96
+ #
97
+ # @example Iterating each change by passing a block:
98
+ # require "gcloud"
99
+ #
100
+ # gcloud = Gcloud.new
101
+ # dns = gcloud.dns
102
+ # zone = dns.zone "example-com"
103
+ # changes = zone.changes
104
+ #
105
+ # changes.all do |change|
106
+ # puts change.name
107
+ # end
108
+ #
109
+ # @example Using the enumerator by not passing a block:
110
+ # require "gcloud"
111
+ #
112
+ # gcloud = Gcloud.new
113
+ # dns = gcloud.dns
114
+ # zone = dns.zone "example-com"
115
+ # changes = zone.changes
116
+ #
117
+ # all_names = changes.all.map do |change|
118
+ # change.name
119
+ # end
120
+ #
121
+ # @example Limit the number of API calls made:
122
+ # require "gcloud"
123
+ #
124
+ # gcloud = Gcloud.new
125
+ # dns = gcloud.dns
126
+ # zone = dns.zone "example-com"
127
+ # changes = zone.changes
128
+ #
129
+ # changes.all(request_limit: 10) do |change|
130
+ # puts change.name
131
+ # end
132
+ #
133
+ def all request_limit: nil
134
+ request_limit = request_limit.to_i if request_limit
135
+ unless block_given?
136
+ return enum_for(:all, request_limit: request_limit)
137
+ end
138
+ results = self
139
+ loop do
140
+ results.each { |r| yield r }
141
+ if request_limit
142
+ request_limit -= 1
143
+ break if request_limit < 0
144
+ end
145
+ break unless results.next?
146
+ results = results.next
147
+ end
47
148
  end
48
149
 
49
150
  ##
50
151
  # @private New Changes::List from a response object.
51
- def self.from_response resp, zone
152
+ def self.from_response resp, zone, max = nil, order = nil
52
153
  changes = new(Array(resp.data["changes"]).map do |gapi_object|
53
154
  Change.from_gapi gapi_object, zone
54
155
  end)
55
156
  changes.instance_variable_set "@token", resp.data["nextPageToken"]
56
157
  changes.instance_variable_set "@zone", zone
158
+ changes.instance_variable_set "@max", max
159
+ changes.instance_variable_set "@order", order
57
160
  changes
58
161
  end
59
162