gcloud 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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