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
@@ -409,7 +409,7 @@ module Gcloud
409
409
  #
410
410
  # @return [Gcloud::Bigquery::Data]
411
411
  #
412
- # @example
412
+ # @example Paginate rows of data: (See {Data#next})
413
413
  # require "gcloud"
414
414
  #
415
415
  # gcloud = Gcloud.new
@@ -421,7 +421,22 @@ module Gcloud
421
421
  # data.each do |row|
422
422
  # puts row["first_name"]
423
423
  # end
424
- # more_data = table.data token: data.token
424
+ # if data.next?
425
+ # more_data = data.next if data.next?
426
+ # end
427
+ #
428
+ # @example Retrieve all rows of data: (See {Data#all})
429
+ # require "gcloud"
430
+ #
431
+ # gcloud = Gcloud.new
432
+ # bigquery = gcloud.bigquery
433
+ # dataset = bigquery.dataset "my_dataset"
434
+ # table = dataset.table "my_table"
435
+ #
436
+ # data = table.data
437
+ # data.all do |row|
438
+ # puts row["first_name"]
439
+ # end
425
440
  #
426
441
  # @!group Data
427
442
  #
@@ -29,26 +29,155 @@ module Gcloud
29
29
  # A hash of this page of results.
30
30
  attr_accessor :etag
31
31
 
32
- # Total number of jobs in this collection.
32
+ # Total number of tables in this collection.
33
33
  attr_accessor :total
34
34
 
35
35
  ##
36
- # Create a new Table::List with an array of jobs.
36
+ # @private Create a new Table::List with an array of tables.
37
37
  def initialize arr = []
38
38
  super arr
39
39
  end
40
40
 
41
+ ##
42
+ # Whether there is a next page of tables.
43
+ #
44
+ # @return [Boolean]
45
+ #
46
+ # @example
47
+ # require "gcloud"
48
+ #
49
+ # gcloud = Gcloud.new
50
+ # bigquery = gcloud.bigquery
51
+ # dataset = bigquery.dataset "my_dataset"
52
+ #
53
+ # tables = dataset.tables
54
+ # if tables.next?
55
+ # next_tables = tables.next
56
+ # end
57
+ #
58
+ def next?
59
+ !token.nil?
60
+ end
61
+
62
+ ##
63
+ # Retrieve the next page of tables.
64
+ #
65
+ # @return [Table::List]
66
+ #
67
+ # @example
68
+ # require "gcloud"
69
+ #
70
+ # gcloud = Gcloud.new
71
+ # bigquery = gcloud.bigquery
72
+ # dataset = bigquery.dataset "my_dataset"
73
+ #
74
+ # tables = dataset.tables
75
+ # if tables.next?
76
+ # next_tables = tables.next
77
+ # end
78
+ #
79
+ def next
80
+ return nil unless next?
81
+ ensure_connection!
82
+ options = { token: token, max: @max }
83
+ resp = @connection.list_tables @dataset_id, options
84
+ if resp.success?
85
+ self.class.from_response resp, @connection, @dataset_id, @max
86
+ else
87
+ fail ApiError.from_response(resp)
88
+ end
89
+ end
90
+
91
+ ##
92
+ # Retrieves all tables by repeatedly loading {#next} until {#next?}
93
+ # returns `false`. Calls the given block once for each table, which is
94
+ # passed as the parameter.
95
+ #
96
+ # An Enumerator is returned if no block is given.
97
+ #
98
+ # This method may make several API calls until all tables are retrieved.
99
+ # Be sure to use as narrow a search criteria as possible. Please use
100
+ # with caution.
101
+ #
102
+ # @param [Integer] request_limit The upper limit of API requests to make
103
+ # to load all tables. Default is no limit.
104
+ # @yield [table] The block for accessing each table.
105
+ # @yieldparam [Table] table The table object.
106
+ #
107
+ # @return [Enumerator]
108
+ #
109
+ # @example Iterating each result by passing a block:
110
+ # require "gcloud"
111
+ #
112
+ # gcloud = Gcloud.new
113
+ # bigquery = gcloud.bigquery
114
+ # dataset = bigquery.dataset "my_dataset"
115
+ #
116
+ # dataset.tables.all do |table|
117
+ # puts table.name
118
+ # end
119
+ #
120
+ # @example Using the enumerator by not passing a block:
121
+ # require "gcloud"
122
+ #
123
+ # gcloud = Gcloud.new
124
+ # bigquery = gcloud.bigquery
125
+ # dataset = bigquery.dataset "my_dataset"
126
+ #
127
+ # all_names = dataset.tables.all.map do |table|
128
+ # table.name
129
+ # end
130
+ #
131
+ # @example Limit the number of API requests made:
132
+ # require "gcloud"
133
+ #
134
+ # gcloud = Gcloud.new
135
+ # bigquery = gcloud.bigquery
136
+ # dataset = bigquery.dataset "my_dataset"
137
+ #
138
+ # dataset.tables.all(request_limit: 10) do |table|
139
+ # puts table.name
140
+ # end
141
+ #
142
+ def all request_limit: nil
143
+ request_limit = request_limit.to_i if request_limit
144
+ unless block_given?
145
+ return enum_for(:all, request_limit: request_limit)
146
+ end
147
+ results = self
148
+ loop do
149
+ results.each { |r| yield r }
150
+ if request_limit
151
+ request_limit -= 1
152
+ break if request_limit < 0
153
+ end
154
+ break unless results.next?
155
+ results = results.next
156
+ end
157
+ end
158
+
41
159
  ##
42
160
  # @private New Table::List from a response object.
43
- def self.from_response resp, conn
161
+ def self.from_response resp, conn, dataset_id = nil, max = nil
44
162
  tables = List.new(Array(resp.data["tables"]).map do |gapi_object|
45
163
  Table.from_gapi gapi_object, conn
46
164
  end)
47
165
  tables.instance_variable_set "@token", resp.data["nextPageToken"]
48
166
  tables.instance_variable_set "@etag", resp.data["etag"]
49
167
  tables.instance_variable_set "@total", resp.data["totalItems"]
168
+ tables.instance_variable_set "@connection", conn
169
+ tables.instance_variable_set "@dataset_id", dataset_id
170
+ tables.instance_variable_set "@max", max
50
171
  tables
51
172
  end
173
+
174
+ protected
175
+
176
+ ##
177
+ # Raise an error unless an active connection is available.
178
+ def ensure_connection!
179
+ fail "Must have active connection" unless @connection
180
+ end
52
181
  end
53
182
  end
54
183
  end
@@ -205,9 +205,8 @@ module Gcloud
205
205
  #
206
206
  # ### Paginating records
207
207
  #
208
- # All records may not return at once, requiring multiple calls to Datastore
209
- # to return them all. The returned records will have a <tt>cursor</tt> if
210
- # there are more available.
208
+ # All records may not return at once, but multiple calls can be made to
209
+ # Datastore to return them all.
211
210
  #
212
211
  # ```ruby
213
212
  # require "gcloud"
@@ -215,22 +214,10 @@ module Gcloud
215
214
  # gcloud = Gcloud.new
216
215
  # datastore = gcloud.datastore
217
216
  #
218
- # task_list_key = datastore.key "TaskList", "default"
219
- #
220
- # query = datastore.query("Task").
221
- # ancestor(task_list_key)
222
- # all_tasks = []
223
- # tmp_tasks = datastore.run query
224
- # while tmp_tasks.any? do
225
- # tmp_tasks.each do |task|
226
- # all_tasks << task
227
- # end
228
- # # break loop if no more tasks available
229
- # break if tmp_tasks.cursor.nil?
230
- # # set cursor on the query
231
- # query = query.cursor tmp_tasks.cursor
232
- # # query for more records
233
- # tmp_tasks = datastore.run query
217
+ # query = datastore.query("Task")
218
+ # tasks = datastore.run query
219
+ # tasks.all do |task|
220
+ # puts t["description"]
234
221
  # end
235
222
  # ```
236
223
  #
@@ -520,6 +507,30 @@ module Gcloud
520
507
  # end
521
508
  # ```
522
509
  #
510
+ # ## Configuring Backoff
511
+ #
512
+ # The {Gcloud::Backoff} class allows users to globally configure how Cloud API
513
+ # requests are automatically retried in the case of some errors, such as a
514
+ # `500` or `503` status code, or a specific internal error code such as
515
+ # `rateLimitExceeded`.
516
+ #
517
+ # If an API call fails, the response will be inspected to see if the call
518
+ # should be retried. If the response matches the criteria, then the request
519
+ # will be retried after a delay. If another error occurs, the delay will be
520
+ # increased incrementally before a subsequent attempt. The first retry will be
521
+ # delayed one second, the second retry two seconds, and so on.
522
+ #
523
+ # ```ruby
524
+ # require "gcloud"
525
+ # require "gcloud/backoff"
526
+ #
527
+ # Gcloud::Backoff.retries = 5 # Raise the maximum number of retries from 3
528
+ # ```
529
+ #
530
+ # See the [Datastore error
531
+ # codes](https://cloud.google.com/datastore/docs/concepts/errors#error_codes)
532
+ # for a list of error conditions.
533
+ #
523
534
  # ## The Datastore Emulator
524
535
  #
525
536
  # As of this release, the Datastore emulator that is part of the gcloud SDK is
@@ -339,12 +339,9 @@ module Gcloud
339
339
  def find_all *keys, consistency: nil
340
340
  ensure_service!
341
341
  check_consistency! consistency
342
- lookup_res = service.lookup(*keys.map(&:to_grpc),
342
+ lookup_res = service.lookup(*Array(keys).flatten.map(&:to_grpc),
343
343
  consistency: consistency)
344
- entities = to_gcloud_entities lookup_res.found
345
- deferred = to_gcloud_keys lookup_res.deferred
346
- missing = to_gcloud_entities lookup_res.missing
347
- LookupResults.new entities, deferred, missing
344
+ LookupResults.from_grpc lookup_res, service, consistency
348
345
  rescue GRPC::BadStatus => e
349
346
  raise Gcloud::Error.from_error(e)
350
347
  end
@@ -663,23 +660,6 @@ module Gcloud
663
660
  fail "Must have active connection to service" unless service
664
661
  end
665
662
 
666
- ##
667
- # Convenience method to convert GRPC entities to Gcloud entities.
668
- def to_gcloud_entities grpc_entity_results
669
- # Entities are nested in an object.
670
- Array(grpc_entity_results).map do |result|
671
- # TODO: Make this return an EntityResult with cursor...
672
- Entity.from_grpc result.entity
673
- end
674
- end
675
-
676
- ##
677
- # Convenience method to convert GRPC keys to Gcloud keys.
678
- def to_gcloud_keys grpc_keys
679
- # Keys are not nested in an object like entities are.
680
- Array(grpc_keys).map { |key| Key.from_grpc key }
681
- end
682
-
683
663
  def check_consistency! consistency
684
664
  fail(ArgumentError,
685
665
  format("Consistency must be :eventual or :strong, not %s.",
@@ -53,11 +53,167 @@ module Gcloud
53
53
  attr_accessor :missing
54
54
 
55
55
  ##
56
- # Create a new LookupResults with an array of values.
57
- def initialize arr = [], deferred = [], missing = []
56
+ # @private Create a new LookupResults with an array of values.
57
+ def initialize arr = []
58
58
  super arr
59
- @deferred = deferred
60
- @missing = missing
59
+ end
60
+
61
+ ##
62
+ # Whether there are more results available.
63
+ #
64
+ # @return [Boolean]
65
+ #
66
+ # @example
67
+ # gcloud = Gcloud.new
68
+ # datastore = gcloud.datastore
69
+ #
70
+ # task_key1 = datastore.key "Task", "sampleTask1"
71
+ # task_key2 = datastore.key "Task", "sampleTask2"
72
+ # tasks = datastore.find_all task_key1, task_key2
73
+ # if tasks.next?
74
+ # next_tasks = tasks.next
75
+ # end
76
+ #
77
+ def next?
78
+ Array(@deferred).any?
79
+ end
80
+
81
+ ##
82
+ # Retrieve the next page of results.
83
+ #
84
+ # @return [LookupResults]
85
+ #
86
+ # @example
87
+ # gcloud = Gcloud.new
88
+ # datastore = gcloud.datastore
89
+ #
90
+ # task_key1 = datastore.key "Task", "sampleTask1"
91
+ # task_key2 = datastore.key "Task", "sampleTask2"
92
+ # tasks = datastore.find_all task_key1, task_key2
93
+ # if tasks.next?
94
+ # next_tasks = tasks.next
95
+ # end
96
+ #
97
+ def next
98
+ return nil unless next?
99
+ ensure_service!
100
+ lookup_res = @service.lookup(*Array(@deferred).flatten.map(&:to_grpc),
101
+ consistency: @consistency,
102
+ transaction: @transaction)
103
+ self.class.from_grpc lookup_res, @service, @consistency
104
+ rescue GRPC::BadStatus => e
105
+ raise Gcloud::Error.from_error(e)
106
+ end
107
+
108
+ ##
109
+ # Retrieves all lookup results by repeatedly loading {#next} until
110
+ # {#next?} returns `false`. Calls the given block once for each result,
111
+ # which is passed as the parameter.
112
+ #
113
+ # An Enumerator is returned if no block is given.
114
+ #
115
+ # This method may make several API calls until all lookup results are
116
+ # retrieved. Be sure to use as narrow a search criteria as possible.
117
+ # Please use with caution.
118
+ #
119
+ # @param [Integer] request_limit The upper limit of API requests to make
120
+ # to load all lookup results. Default is no limit.
121
+ # @yield [result] The block for accessing each lookup result.
122
+ # @yieldparam [Entity] result The lookup result object.
123
+ #
124
+ # @return [Enumerator]
125
+ #
126
+ # @example Iterating each result by passing a block:
127
+ # gcloud = Gcloud.new
128
+ # datastore = gcloud.datastore
129
+ #
130
+ # task_key1 = datastore.key "Task", "sampleTask1"
131
+ # task_key2 = datastore.key "Task", "sampleTask2"
132
+ # tasks = datastore.find_all task_key1, task_key2
133
+ # tasks.all do |task|
134
+ # puts "Task #{task.key.id} (#cursor)"
135
+ # end
136
+ #
137
+ # @example Using the enumerator by not passing a block:
138
+ # gcloud = Gcloud.new
139
+ # datastore = gcloud.datastore
140
+ #
141
+ # task_key1 = datastore.key "Task", "sampleTask1"
142
+ # task_key2 = datastore.key "Task", "sampleTask2"
143
+ # tasks = datastore.find_all task_key1, task_key2
144
+ # all_keys = tasks.all.map(&:key).each do |task|
145
+ # task.key
146
+ # end
147
+ #
148
+ # @example Limit the number of API calls made:
149
+ # gcloud = Gcloud.new
150
+ # datastore = gcloud.datastore
151
+ #
152
+ # task_key1 = datastore.key "Task", "sampleTask1"
153
+ # task_key2 = datastore.key "Task", "sampleTask2"
154
+ # tasks = datastore.find_all task_key1, task_key2
155
+ # tasks.all(request_limit: 10) do |task|
156
+ # puts "Task #{task.key.id} (#cursor)"
157
+ # end
158
+ #
159
+ def all request_limit: nil
160
+ request_limit = request_limit.to_i if request_limit
161
+ unless block_given?
162
+ return enum_for(:all, request_limit: request_limit)
163
+ end
164
+ results = self
165
+ loop do
166
+ results.each { |r| yield r }
167
+ if request_limit
168
+ request_limit -= 1
169
+ break if request_limit < 0
170
+ end
171
+ break unless results.next?
172
+ results = results.next
173
+ end
174
+ end
175
+
176
+ ##
177
+ # @private New Dataset::LookupResults from a
178
+ # Google::Dataset::V1beta3::LookupResponse object.
179
+ def self.from_grpc lookup_res, service, consistency = nil, tx = nil
180
+ entities = to_gcloud_entities lookup_res.found
181
+ deferred = to_gcloud_keys lookup_res.deferred
182
+ missing = to_gcloud_entities lookup_res.missing
183
+ new(entities).tap do |lr|
184
+ lr.instance_variable_set :@service, service
185
+ lr.instance_variable_set :@consistency, consistency
186
+ lr.instance_variable_set :@transaction, tx
187
+ lr.instance_variable_set :@deferred, deferred
188
+ lr.instance_variable_set :@missing, missing
189
+ end
190
+ end
191
+
192
+ protected
193
+
194
+ ##
195
+ # @private Raise an error unless an active connection to the service is
196
+ # available.
197
+ def ensure_service!
198
+ msg = "Must have active connection to datastore service to get next"
199
+ fail msg if @service.nil?
200
+ end
201
+
202
+ ##
203
+ # Convenience method to convert GRPC entities to Gcloud entities.
204
+ def self.to_gcloud_entities grpc_entity_results
205
+ # Entities are nested in an object.
206
+ Array(grpc_entity_results).map do |result|
207
+ # TODO: Make this return an EntityResult with cursor...
208
+ Entity.from_grpc result.entity
209
+ end
210
+ end
211
+
212
+ ##
213
+ # Convenience method to convert GRPC keys to Gcloud keys.
214
+ def self.to_gcloud_keys grpc_keys
215
+ # Keys are not nested in an object like entities are.
216
+ Array(grpc_keys).map { |key| Key.from_grpc key }
61
217
  end
62
218
  end
63
219
  end