gcloud 0.8.2 → 0.9.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 (55) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +26 -0
  3. data/OVERVIEW.md +10 -8
  4. data/lib/gcloud.rb +12 -13
  5. data/lib/gcloud/bigquery/dataset/list.rb +2 -4
  6. data/lib/gcloud/bigquery/job/list.rb +3 -5
  7. data/lib/gcloud/bigquery/table/list.rb +3 -5
  8. data/lib/gcloud/datastore.rb +326 -97
  9. data/lib/gcloud/datastore/commit.rb +73 -56
  10. data/lib/gcloud/datastore/credentials.rb +1 -12
  11. data/lib/gcloud/datastore/cursor.rb +76 -0
  12. data/lib/gcloud/datastore/dataset.rb +337 -134
  13. data/lib/gcloud/datastore/dataset/lookup_results.rb +12 -12
  14. data/lib/gcloud/datastore/dataset/query_results.rb +117 -27
  15. data/lib/gcloud/datastore/entity.rb +159 -93
  16. data/lib/gcloud/datastore/errors.rb +0 -21
  17. data/lib/gcloud/datastore/gql_query.rb +211 -0
  18. data/lib/gcloud/datastore/grpc_utils.rb +131 -0
  19. data/lib/gcloud/datastore/key.rb +74 -65
  20. data/lib/gcloud/datastore/properties.rb +14 -1
  21. data/lib/gcloud/datastore/query.rb +188 -52
  22. data/lib/gcloud/datastore/service.rb +161 -0
  23. data/lib/gcloud/datastore/transaction.rb +175 -60
  24. data/lib/gcloud/dns/change/list.rb +2 -4
  25. data/lib/gcloud/dns/record/list.rb +2 -4
  26. data/lib/gcloud/dns/zone/list.rb +2 -4
  27. data/lib/gcloud/grpc_utils.rb +11 -0
  28. data/lib/gcloud/logging/entry.rb +6 -17
  29. data/lib/gcloud/logging/entry/list.rb +8 -9
  30. data/lib/gcloud/logging/metric/list.rb +4 -5
  31. data/lib/gcloud/logging/resource.rb +1 -12
  32. data/lib/gcloud/logging/resource_descriptor.rb +9 -12
  33. data/lib/gcloud/logging/resource_descriptor/list.rb +4 -5
  34. data/lib/gcloud/logging/sink/list.rb +4 -5
  35. data/lib/gcloud/pubsub/message.rb +1 -3
  36. data/lib/gcloud/pubsub/subscription.rb +5 -7
  37. data/lib/gcloud/pubsub/topic.rb +1 -3
  38. data/lib/gcloud/resource_manager/project/list.rb +2 -4
  39. data/lib/gcloud/translate/api.rb +5 -3
  40. data/lib/gcloud/translate/connection.rb +4 -4
  41. data/lib/gcloud/version.rb +1 -1
  42. metadata +9 -20
  43. data/lib/gcloud/datastore/connection.rb +0 -203
  44. data/lib/gcloud/datastore/proto.rb +0 -266
  45. data/lib/gcloud/proto/datastore_v1.pb.rb +0 -377
  46. data/lib/google/protobuf/any.rb +0 -17
  47. data/lib/google/protobuf/api.rb +0 -31
  48. data/lib/google/protobuf/duration.rb +0 -17
  49. data/lib/google/protobuf/empty.rb +0 -15
  50. data/lib/google/protobuf/field_mask.rb +0 -16
  51. data/lib/google/protobuf/source_context.rb +0 -16
  52. data/lib/google/protobuf/struct.rb +0 -35
  53. data/lib/google/protobuf/timestamp.rb +0 -17
  54. data/lib/google/protobuf/type.rb +0 -79
  55. data/lib/google/protobuf/wrappers.rb +0 -48
@@ -21,14 +21,46 @@ module Gcloud
21
21
  # Special Connection instance for running transactions.
22
22
  #
23
23
  # See {Gcloud::Datastore::Dataset#transaction}
24
+ #
25
+ # @see https://cloud.google.com/datastore/docs/concepts/transactions
26
+ # Transactions
27
+ #
28
+ # @example Transactional update:
29
+ # def transfer_funds from_key, to_key, amount
30
+ # datastore.transaction do |tx|
31
+ # from = tx.find from_key
32
+ # from["balance"] -= amount
33
+ # to = tx.find to_key
34
+ # to["balance"] += amount
35
+ # tx.save from, to
36
+ # end
37
+ # end
38
+ #
39
+ # @example Retry logic using the transactional update example above:
40
+ # (1..5).each do |i|
41
+ # begin
42
+ # return transfer_funds from_key, to_key, amount
43
+ # rescue Gcloud::Error => e
44
+ # raise e if i == 5
45
+ # end
46
+ # end
47
+ #
48
+ # @example Transactional read:
49
+ # task_list_key = datastore.key "TaskList", "default"
50
+ # datastore.transaction do |tx|
51
+ # task_list = tx.find task_list_key
52
+ # query = tx.query("Task").ancestor(task_list)
53
+ # tasks_in_list = tx.run query
54
+ # end
55
+ #
24
56
  class Transaction < Dataset
25
57
  attr_reader :id
26
58
 
27
59
  ##
28
60
  # @private Creates a new Transaction instance.
29
- # Takes a Connection instead of project and Credentials.
30
- def initialize connection
31
- @connection = connection
61
+ # Takes a Connection and Service instead of project and Credentials.
62
+ def initialize service
63
+ @service = service
32
64
  reset!
33
65
  start
34
66
  end
@@ -36,16 +68,76 @@ module Gcloud
36
68
  ##
37
69
  # Persist entities in a transaction.
38
70
  #
39
- # @example
40
- # dataset.transaction do |tx|
41
- # if tx.find(user.key).nil?
42
- # tx.save task1, task2
71
+ # @example Transactional get or create:
72
+ # task_key = datastore.key "Task", "sampleTask"
73
+ #
74
+ # task = nil
75
+ # datastore.transaction do |tx|
76
+ # task = tx.find task_key
77
+ # if task.nil?
78
+ # task = datastore.entity task_key do |t|
79
+ # t["type"] = "Personal"
80
+ # t["done"] = false
81
+ # t["priority"] = 4
82
+ # t["description"] = "Learn Cloud Datastore"
83
+ # end
84
+ # tx.save task
43
85
  # end
44
86
  # end
45
87
  #
46
88
  def save *entities
47
89
  @commit.save(*entities)
48
- # Do not save or assign auto_ids yet
90
+ # Do not save yet
91
+ entities
92
+ end
93
+ alias_method :upsert, :save
94
+
95
+ ##
96
+ # Insert entities in a transaction. An InvalidArgumentError will raised if
97
+ # the entities cannot be inserted.
98
+ #
99
+ # @example Transactional insert:
100
+ # task_key = datastore.key "Task", "sampleTask"
101
+ #
102
+ # task = nil
103
+ # datastore.transaction do |tx|
104
+ # task = tx.find task_key
105
+ # if task.nil?
106
+ # task = datastore.entity task_key do |t|
107
+ # t["type"] = "Personal"
108
+ # t["done"] = false
109
+ # t["priority"] = 4
110
+ # t["description"] = "Learn Cloud Datastore"
111
+ # end
112
+ # tx.insert task
113
+ # end
114
+ # end
115
+ #
116
+ def insert *entities
117
+ @commit.insert(*entities)
118
+ # Do not insert yet
119
+ entities
120
+ end
121
+
122
+ ##
123
+ # Update entities in a transaction. An InvalidArgumentError will raised if
124
+ # the entities cannot be updated.
125
+ #
126
+ # @example Transactional update:
127
+ # task_key = datastore.key "Task", "sampleTask"
128
+ #
129
+ # task = nil
130
+ # datastore.transaction do |tx|
131
+ # task = tx.find task_key
132
+ # if task
133
+ # task["done"] = true
134
+ # tx.update task
135
+ # end
136
+ # end
137
+ #
138
+ def update *entities
139
+ @commit.update(*entities)
140
+ # Do not update yet
49
141
  entities
50
142
  end
51
143
 
@@ -53,8 +145,8 @@ module Gcloud
53
145
  # Remove entities in a transaction.
54
146
  #
55
147
  # @example
56
- # dataset.transaction do |tx|
57
- # if tx.find(user.key).nil?
148
+ # datastore.transaction do |tx|
149
+ # if tx.find(task_list.key).nil?
58
150
  # tx.delete task1, task2
59
151
  # end
60
152
  # end
@@ -74,11 +166,11 @@ module Gcloud
74
166
  # @return [Gcloud::Datastore::Entity, nil]
75
167
  #
76
168
  # @example Finding an entity with a key:
77
- # key = dataset.key "Task", 123456
78
- # task = dataset.find key
169
+ # task_key = datastore.key "Task", "sampleTask"
170
+ # task = datastore.find task_key
79
171
  #
80
172
  # @example Finding an entity with a `kind` and `id`/`name`:
81
- # task = dataset.find "Task", 123456
173
+ # task = datastore.find "Task", "sampleTask"
82
174
  #
83
175
  def find key_or_kind, id_or_name = nil
84
176
  key = key_or_kind
@@ -99,18 +191,21 @@ module Gcloud
99
191
  #
100
192
  # @example
101
193
  # gcloud = Gcloud.new
102
- # dataset = gcloud.datastore
103
- # key1 = dataset.key "Task", 123456
104
- # key2 = dataset.key "Task", 987654
105
- # tasks = dataset.find_all key1, key2
194
+ # datastore = gcloud.datastore
195
+ # task_key1 = datastore.key "Task", 123456
196
+ # task_key2 = datastore.key "Task", 987654
197
+ # tasks = datastore.find_all task_key1, task_key2
106
198
  #
107
199
  def find_all *keys
108
- response = connection.lookup(*keys.map(&:to_proto),
109
- transaction: @id)
110
- entities = to_gcloud_entities response.found
111
- deferred = to_gcloud_keys response.deferred
112
- missing = to_gcloud_entities response.missing
200
+ ensure_service!
201
+ lookup_res = service.lookup(*keys.map(&:to_grpc),
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
113
206
  LookupResults.new entities, deferred, missing
207
+ rescue GRPC::BadStatus => e
208
+ raise Gcloud::Error.from_error(e)
114
209
  end
115
210
  alias_method :lookup, :find_all
116
211
 
@@ -124,27 +219,29 @@ module Gcloud
124
219
  # @return [Gcloud::Datastore::Dataset::QueryResults]
125
220
  #
126
221
  # @example
127
- # query = dataset.query("Task").
128
- # where("completed", "=", true)
129
- # dataset.transaction do |tx|
222
+ # query = datastore.query("Task").
223
+ # where("done", "=", false)
224
+ # datastore.transaction do |tx|
130
225
  # tasks = tx.run query
131
226
  # end
132
227
  #
133
228
  # @example Run the query within a namespace with the `namespace` option:
134
229
  # query = Gcloud::Datastore::Query.new.kind("Task").
135
- # where("completed", "=", true)
136
- # dataset.transaction do |tx|
230
+ # where("done", "=", false)
231
+ # datastore.transaction do |tx|
137
232
  # tasks = tx.run query, namespace: "ns~todo-project"
138
233
  # end
139
234
  #
140
235
  def run query, namespace: nil
141
- partition = optional_partition_id namespace
142
- response = connection.run_query query.to_proto, partition,
143
- transaction: @id
144
- entities = to_gcloud_entities response.batch.entity_result
145
- cursor = Proto.encode_cursor response.batch.end_cursor
146
- more_results = Proto.to_more_results_string response.batch.more_results
147
- QueryResults.new entities, cursor, more_results
236
+ ensure_service!
237
+ unless query.is_a?(Query) || query.is_a?(GqlQuery)
238
+ fail ArgumentError, "Cannot run a #{query.class} object."
239
+ end
240
+ query_res = service.run_query query.to_grpc, namespace,
241
+ transaction: @id
242
+ QueryResults.from_grpc query_res, service, namespace, query.to_grpc.dup
243
+ rescue GRPC::BadStatus => e
244
+ raise Gcloud::Error.from_error(e)
148
245
  end
149
246
  alias_method :run_query, :run
150
247
 
@@ -154,8 +251,11 @@ module Gcloud
154
251
  def start
155
252
  fail TransactionError, "Transaction already opened." unless @id.nil?
156
253
 
157
- response = connection.begin_transaction
158
- @id = response.transaction
254
+ ensure_service!
255
+ tx_res = service.begin_transaction
256
+ @id = tx_res.transaction
257
+ rescue GRPC::BadStatus => e
258
+ raise Gcloud::Error.from_error(e)
159
259
  end
160
260
  alias_method :begin_transaction, :start
161
261
 
@@ -169,17 +269,19 @@ module Gcloud
169
269
  # require "gcloud"
170
270
  #
171
271
  # gcloud = Gcloud.new
172
- # dataset = gcloud.datastore
272
+ # datastore = gcloud.datastore
173
273
  #
174
- # user = dataset.entity "User", "heidi" do |u|
175
- # u["name"] = "Heidi Henderson"
176
- # u["email"] = "heidi@example.net"
274
+ # task = datastore.entity "Task" do |t|
275
+ # t["type"] = "Personal"
276
+ # t["done"] = false
277
+ # t["priority"] = 4
278
+ # t["description"] = "Learn Cloud Datastore"
177
279
  # end
178
280
  #
179
- # tx = dataset.transaction
281
+ # tx = datastore.transaction
180
282
  # begin
181
- # if tx.find(user.key).nil?
182
- # tx.save user
283
+ # if tx.find(task.key).nil?
284
+ # tx.save task
183
285
  # end
184
286
  # tx.commit
185
287
  # rescue
@@ -190,9 +292,9 @@ module Gcloud
190
292
  # require "gcloud"
191
293
  #
192
294
  # gcloud = Gcloud.new
193
- # dataset = gcloud.datastore
295
+ # datastore = gcloud.datastore
194
296
  #
195
- # tx = dataset.transaction
297
+ # tx = datastore.transaction
196
298
  # begin
197
299
  # tx.commit do |c|
198
300
  # c.save task1, task2
@@ -203,17 +305,25 @@ module Gcloud
203
305
  # end
204
306
  #
205
307
  def commit
206
- if @id.nil?
207
- fail TransactionError, "Cannot commit when not in a transaction."
208
- end
308
+ fail TransactionError,
309
+ "Cannot commit when not in a transaction." if @id.nil?
209
310
 
210
311
  yield @commit if block_given?
211
- response = connection.commit @commit.mutation, @id
212
- auto_id_assign_ids @commit.auto_id_entities,
213
- response.mutation_result.insert_auto_id_key
312
+
313
+ ensure_service!
314
+
315
+ commit_res = service.commit @commit.mutations, transaction: @id
316
+ entities = @commit.entities
317
+ returned_keys = commit_res.mutation_results.map(&:key)
318
+ returned_keys.each_with_index do |key, index|
319
+ next if entities[index].nil?
320
+ entities[index].key = Key.from_grpc(key) unless key.nil?
321
+ end
214
322
  # Make sure all entity keys are frozen so all show as persisted
215
- @commit.entities.each { |e| e.key.freeze unless e.persisted? }
323
+ entities.each { |e| e.key.freeze unless e.persisted? }
216
324
  true
325
+ rescue GRPC::BadStatus => e
326
+ raise Gcloud::Error.from_error(e)
217
327
  end
218
328
 
219
329
  ##
@@ -223,17 +333,19 @@ module Gcloud
223
333
  # require "gcloud"
224
334
  #
225
335
  # gcloud = Gcloud.new
226
- # dataset = gcloud.datastore
336
+ # datastore = gcloud.datastore
227
337
  #
228
- # user = dataset.entity "User", "heidi" do |u|
229
- # u["name"] = "Heidi Henderson"
230
- # u["email"] = "heidi@example.net"
338
+ # task = datastore.entity "Task" do |t|
339
+ # t["type"] = "Personal"
340
+ # t["done"] = false
341
+ # t["priority"] = 4
342
+ # t["description"] = "Learn Cloud Datastore"
231
343
  # end
232
344
  #
233
- # tx = dataset.transaction
345
+ # tx = datastore.transaction
234
346
  # begin
235
- # if tx.find(user.key).nil?
236
- # tx.save user
347
+ # if tx.find(task.key).nil?
348
+ # tx.save task
237
349
  # end
238
350
  # tx.commit
239
351
  # rescue
@@ -244,8 +356,11 @@ module Gcloud
244
356
  fail TransactionError, "Cannot rollback when not in a transaction."
245
357
  end
246
358
 
247
- connection.rollback @id
359
+ ensure_service!
360
+ service.rollback @id
248
361
  true
362
+ rescue GRPC::BadStatus => e
363
+ raise Gcloud::Error.from_error(e)
249
364
  end
250
365
 
251
366
  ##
@@ -52,10 +52,8 @@ module Gcloud
52
52
  changes = new(Array(resp.data["changes"]).map do |gapi_object|
53
53
  Change.from_gapi gapi_object, zone
54
54
  end)
55
- changes.instance_eval do
56
- @token = resp.data["nextPageToken"]
57
- @zone = zone
58
- end
55
+ changes.instance_variable_set "@token", resp.data["nextPageToken"]
56
+ changes.instance_variable_set "@zone", zone
59
57
  changes
60
58
  end
61
59
 
@@ -73,10 +73,8 @@ module Gcloud
73
73
  records = new(Array(resp.data["rrsets"]).map do |gapi_object|
74
74
  Record.from_gapi gapi_object
75
75
  end)
76
- records.instance_eval do
77
- @token = resp.data["nextPageToken"]
78
- @zone = zone
79
- end
76
+ records.instance_variable_set "@token", resp.data["nextPageToken"]
77
+ records.instance_variable_set "@zone", zone
80
78
  records
81
79
  end
82
80
 
@@ -57,10 +57,8 @@ module Gcloud
57
57
  zones = new(Array(resp.data["managedZones"]).map do |gapi_object|
58
58
  Zone.from_gapi gapi_object, conn
59
59
  end)
60
- zones.instance_eval do
61
- @token = resp.data["nextPageToken"]
62
- @connection = conn
63
- end
60
+ zones.instance_variable_set "@token", resp.data["nextPageToken"]
61
+ zones.instance_variable_set "@connection", conn
64
62
  zones
65
63
  end
66
64
 
@@ -72,5 +72,16 @@ module Gcloud
72
72
  Google::Protobuf::Value.new string_value: obj.to_s
73
73
  end
74
74
  end
75
+
76
+ ##
77
+ # @private Convert a Google::Protobuf::Map to a Hash
78
+ def self.map_to_hash map
79
+ if map.respond_to? :to_h
80
+ map.to_h
81
+ else
82
+ # Enumerable doesn't have to_h on ruby 2.0...
83
+ Hash[map.to_a]
84
+ end
85
+ end
75
86
  end
76
87
  end
@@ -226,24 +226,13 @@ module Gcloud
226
226
  e.timestamp = extract_timestamp(grpc)
227
227
  e.severity = grpc.severity
228
228
  e.insert_id = grpc.insert_id
229
- e.labels = map_to_hash(grpc.labels)
229
+ e.labels = GRPCUtils.map_to_hash(grpc.labels)
230
230
  e.payload = extract_payload(grpc)
231
- e.instance_eval do
232
- @resource = Resource.from_grpc grpc.resource
233
- @http_request = HttpRequest.from_grpc grpc.http_request
234
- @operation = Operation.from_grpc grpc.operation
235
- end
236
- end
237
- end
238
-
239
- ##
240
- # @private Convert a Google::Protobuf::Map to a Hash
241
- def self.map_to_hash map
242
- if map.respond_to? :to_h
243
- map.to_h
244
- else
245
- # Enumerable doesn't have to_h on ruby 2.0...
246
- Hash[map.to_a]
231
+ e.instance_variable_set "@resource", Resource.from_grpc(grpc.resource)
232
+ e.instance_variable_set "@http_request",
233
+ HttpRequest.from_grpc(grpc.http_request)
234
+ e.instance_variable_set "@operation",
235
+ Operation.from_grpc(grpc.operation)
247
236
  end
248
237
  end
249
238
 
@@ -85,15 +85,14 @@ module Gcloud
85
85
  entries = new(Array(grpc_list.entries).map do |grpc_entry|
86
86
  Entry.from_grpc grpc_entry
87
87
  end)
88
- entries.instance_eval do
89
- @token = grpc_list.next_page_token
90
- @token = nil if @token == ""
91
- @service = service
92
- @projects = projects
93
- @filter = filter
94
- @order = order
95
- @max = max
96
- end
88
+ token = grpc_list.next_page_token
89
+ token = nil if token == ""
90
+ entries.instance_variable_set "@token", token
91
+ entries.instance_variable_set "@service", service
92
+ entries.instance_variable_set "@projects", projects
93
+ entries.instance_variable_set "@filter", filter
94
+ entries.instance_variable_set "@order", order
95
+ entries.instance_variable_set "@max", max
97
96
  entries
98
97
  end
99
98