gcloud 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +15 -0
- data/OVERVIEW.md +38 -5
- data/lib/gcloud.rb +55 -4
- data/lib/gcloud/bigquery/data.rb +2 -0
- data/lib/gcloud/bigquery/dataset.rb +1 -1
- data/lib/gcloud/bigquery/dataset/list.rb +2 -0
- data/lib/gcloud/bigquery/job/list.rb +2 -0
- data/lib/gcloud/bigquery/project.rb +2 -9
- data/lib/gcloud/bigquery/table/list.rb +2 -0
- data/lib/gcloud/datastore.rb +23 -28
- data/lib/gcloud/datastore/connection.rb +3 -1
- data/lib/gcloud/datastore/dataset.rb +167 -22
- data/lib/gcloud/datastore/dataset/lookup_results.rb +2 -0
- data/lib/gcloud/datastore/dataset/query_results.rb +2 -0
- data/lib/gcloud/datastore/entity.rb +11 -11
- data/lib/gcloud/datastore/key.rb +33 -16
- data/lib/gcloud/dns/change/list.rb +2 -0
- data/lib/gcloud/dns/project.rb +1 -1
- data/lib/gcloud/dns/record/list.rb +2 -0
- data/lib/gcloud/dns/zone.rb +2 -2
- data/lib/gcloud/dns/zone/list.rb +2 -0
- data/lib/gcloud/gce.rb +0 -5
- data/lib/gcloud/pubsub.rb +65 -62
- data/lib/gcloud/pubsub/connection.rb +20 -2
- data/lib/gcloud/pubsub/project.rb +233 -72
- data/lib/gcloud/pubsub/subscription.rb +45 -13
- data/lib/gcloud/pubsub/subscription/list.rb +2 -0
- data/lib/gcloud/pubsub/topic.rb +66 -85
- data/lib/gcloud/pubsub/topic/list.rb +2 -0
- data/lib/gcloud/resource_manager.rb +244 -0
- data/lib/gcloud/resource_manager/connection.rb +124 -0
- data/lib/gcloud/resource_manager/credentials.rb +30 -0
- data/lib/gcloud/resource_manager/errors.rb +64 -0
- data/lib/gcloud/resource_manager/manager.rb +319 -0
- data/lib/gcloud/resource_manager/project.rb +529 -0
- data/lib/gcloud/resource_manager/project/list.rb +91 -0
- data/lib/gcloud/resource_manager/project/updater.rb +137 -0
- data/lib/gcloud/storage/bucket.rb +1 -1
- data/lib/gcloud/storage/bucket/cors.rb +2 -0
- data/lib/gcloud/storage/bucket/list.rb +2 -0
- data/lib/gcloud/storage/file/list.rb +2 -0
- data/lib/gcloud/storage/project.rb +1 -1
- data/lib/gcloud/version.rb +1 -1
- metadata +10 -2
@@ -101,6 +101,14 @@ module Gcloud
|
|
101
101
|
)
|
102
102
|
end
|
103
103
|
|
104
|
+
def test_topic_permissions topic_name, permissions, options = {}
|
105
|
+
@client.execute(
|
106
|
+
api_method: @pubsub.projects.topics.test_iam_permissions,
|
107
|
+
parameters: { resource: topic_path(topic_name, options) },
|
108
|
+
body_object: { permissions: permissions }
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
104
112
|
##
|
105
113
|
# Creates a subscription on a given topic for a given subscriber.
|
106
114
|
def create_subscription topic, subscription_name, options = {}
|
@@ -177,6 +185,16 @@ module Gcloud
|
|
177
185
|
)
|
178
186
|
end
|
179
187
|
|
188
|
+
def test_subscription_permissions subscription_name,
|
189
|
+
permissions, options = {}
|
190
|
+
@client.execute(
|
191
|
+
api_method: @pubsub.projects.subscriptions.test_iam_permissions,
|
192
|
+
parameters: {
|
193
|
+
resource: subscription_path(subscription_name, options) },
|
194
|
+
body_object: { permissions: permissions }
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
180
198
|
##
|
181
199
|
# Adds one or more messages to the topic.
|
182
200
|
# Returns NOT_FOUND if the topic does not exist.
|
@@ -188,7 +206,7 @@ module Gcloud
|
|
188
206
|
end
|
189
207
|
@client.execute(
|
190
208
|
api_method: @pubsub.projects.topics.publish,
|
191
|
-
parameters: { topic: topic },
|
209
|
+
parameters: { topic: topic_path(topic) },
|
192
210
|
body_object: { messages: gapi_msgs }
|
193
211
|
)
|
194
212
|
end
|
@@ -264,7 +282,7 @@ module Gcloud
|
|
264
282
|
endpoint = options[:endpoint]
|
265
283
|
attributes = hashify options[:attributes]
|
266
284
|
|
267
|
-
data = { topic: topic }
|
285
|
+
data = { topic: topic_path(topic) }
|
268
286
|
data[:ackDeadlineSeconds] = deadline if deadline
|
269
287
|
if endpoint
|
270
288
|
data[:pushConfig] = { pushEndpoint: endpoint,
|
@@ -80,42 +80,6 @@ module Gcloud
|
|
80
80
|
|
81
81
|
##
|
82
82
|
# Retrieves topic by name.
|
83
|
-
# The difference between this method and Project#topic is that this
|
84
|
-
# method makes an API call to Pub/Sub to verify the topic exists.
|
85
|
-
#
|
86
|
-
# === Parameters
|
87
|
-
#
|
88
|
-
# +topic_name+::
|
89
|
-
# Name of a topic. (+String+)
|
90
|
-
#
|
91
|
-
# === Returns
|
92
|
-
#
|
93
|
-
# Gcloud::Pubsub::Topic or nil if topic does not exist
|
94
|
-
#
|
95
|
-
# === Example
|
96
|
-
#
|
97
|
-
# require "gcloud"
|
98
|
-
#
|
99
|
-
# gcloud = Gcloud.new
|
100
|
-
# pubsub = gcloud.pubsub
|
101
|
-
# topic = pubsub.get_topic "my-topic"
|
102
|
-
#
|
103
|
-
def get_topic topic_name
|
104
|
-
ensure_connection!
|
105
|
-
resp = connection.get_topic topic_name
|
106
|
-
if resp.success?
|
107
|
-
Topic.from_gapi resp.data, connection
|
108
|
-
else
|
109
|
-
return nil if resp.data["error"]["code"] == 404
|
110
|
-
fail ApiError.from_response(resp)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
alias_method :find_topic, :get_topic
|
114
|
-
|
115
|
-
##
|
116
|
-
# Retrieves topic by name.
|
117
|
-
# The difference between this method and Project#get_topic is that this
|
118
|
-
# method does not make an API call to Pub/Sub to verify the topic exists.
|
119
83
|
#
|
120
84
|
# === Parameters
|
121
85
|
#
|
@@ -124,16 +88,24 @@ module Gcloud
|
|
124
88
|
# +options+::
|
125
89
|
# An optional Hash for controlling additional behavior. (+Hash+)
|
126
90
|
# <code>options[:autocreate]</code>::
|
127
|
-
# Flag to control whether the topic
|
128
|
-
#
|
91
|
+
# Flag to control whether the requested topic will be created if it does
|
92
|
+
# not exist. Ignored if +skip_lookup+ is +true+. The default value is
|
93
|
+
# +false+. (+Boolean+)
|
129
94
|
# <code>options[:project]</code>::
|
130
95
|
# If the topic belongs to a project other than the one currently
|
131
96
|
# connected to, the alternate project ID can be specified here.
|
132
97
|
# (+String+)
|
98
|
+
# <code>options[:skip_lookup]</code>::
|
99
|
+
# Optionally create a Topic object without verifying the topic resource
|
100
|
+
# exists on the Pub/Sub service. Calls made on this object will raise
|
101
|
+
# errors if the topic resource does not exist. Default is +false+.
|
102
|
+
# (+Boolean+)
|
133
103
|
#
|
134
104
|
# === Returns
|
135
105
|
#
|
136
|
-
# Gcloud::Pubsub::Topic
|
106
|
+
# Gcloud::Pubsub::Topic or nil if topic does not exist. Will return a
|
107
|
+
# newly created Gcloud::Pubsub::Topic if the topic does not exist and
|
108
|
+
# +autocreate+ is set to +true+.
|
137
109
|
#
|
138
110
|
# === Examples
|
139
111
|
#
|
@@ -142,25 +114,24 @@ module Gcloud
|
|
142
114
|
# gcloud = Gcloud.new
|
143
115
|
# pubsub = gcloud.pubsub
|
144
116
|
# topic = pubsub.topic "existing-topic"
|
145
|
-
# msg = topic.publish "This is the first API call to Pub/Sub."
|
146
117
|
#
|
147
|
-
# By default
|
118
|
+
# By default +nil+ will be returned if the topic does not exist.
|
119
|
+
# the topic will be created in Pub/Sub when needed.
|
148
120
|
#
|
149
121
|
# require "gcloud"
|
150
122
|
#
|
151
123
|
# gcloud = Gcloud.new
|
152
124
|
# pubsub = gcloud.pubsub
|
153
|
-
# topic = pubsub.topic "non-existing-topic"
|
154
|
-
# msg = topic.publish "This will create the topic in Pub/Sub."
|
125
|
+
# topic = pubsub.topic "non-existing-topic" #=> nil
|
155
126
|
#
|
156
|
-
#
|
127
|
+
# The topic will be created if the topic does not exist and the
|
128
|
+
# +autocreate+ option is set to true.
|
157
129
|
#
|
158
130
|
# require "gcloud"
|
159
131
|
#
|
160
132
|
# gcloud = Gcloud.new
|
161
133
|
# pubsub = gcloud.pubsub
|
162
|
-
# topic = pubsub.topic "non-existing-topic"
|
163
|
-
# msg = topic.publish "This raises." #=> Gcloud::Pubsub::NotFoundError
|
134
|
+
# topic = pubsub.topic "non-existing-topic", autocreate: true
|
164
135
|
#
|
165
136
|
# A topic in a different project can be created using the +project+ flag.
|
166
137
|
#
|
@@ -170,11 +141,30 @@ module Gcloud
|
|
170
141
|
# pubsub = gcloud.pubsub
|
171
142
|
# topic = pubsub.topic "another-topic", project: "another-project"
|
172
143
|
#
|
144
|
+
# The lookup against the Pub/Sub service can be skipped using the
|
145
|
+
# +skip_lookup+ option:
|
146
|
+
#
|
147
|
+
# require "gcloud"
|
148
|
+
#
|
149
|
+
# gcloud = Gcloud.new
|
150
|
+
# pubsub = gcloud.pubsub
|
151
|
+
# topic = pubsub.topic "another-topic", skip_lookup: true
|
152
|
+
#
|
173
153
|
def topic topic_name, options = {}
|
174
154
|
ensure_connection!
|
175
|
-
|
176
|
-
|
155
|
+
if options[:skip_lookup]
|
156
|
+
return Topic.new_lazy(topic_name, connection, options)
|
157
|
+
end
|
158
|
+
resp = connection.get_topic topic_name
|
159
|
+
return Topic.from_gapi(resp.data, connection) if resp.success?
|
160
|
+
if resp.status == 404
|
161
|
+
return create_topic(topic_name) if options[:autocreate]
|
162
|
+
return nil
|
163
|
+
end
|
164
|
+
fail ApiError.from_response(resp)
|
177
165
|
end
|
166
|
+
alias_method :get_topic, :topic
|
167
|
+
alias_method :find_topic, :topic
|
178
168
|
|
179
169
|
##
|
180
170
|
# Creates a new topic.
|
@@ -224,7 +214,7 @@ module Gcloud
|
|
224
214
|
#
|
225
215
|
# === Returns
|
226
216
|
#
|
227
|
-
# Array of Gcloud::Pubsub::Topic (Gcloud::Pubsub::Topic::List)
|
217
|
+
# Array of Gcloud::Pubsub::Topic (See Gcloud::Pubsub::Topic::List)
|
228
218
|
#
|
229
219
|
# === Examples
|
230
220
|
#
|
@@ -271,46 +261,189 @@ module Gcloud
|
|
271
261
|
alias_method :list_topics, :topics
|
272
262
|
|
273
263
|
##
|
274
|
-
#
|
275
|
-
# The difference between this method and Project#get_subscription is
|
276
|
-
# that this method does not make an API call to Pub/Sub to verify the
|
277
|
-
# subscription exists.
|
264
|
+
# Publishes one or more messages to the given topic.
|
278
265
|
#
|
279
266
|
# === Parameters
|
280
267
|
#
|
268
|
+
# +topic_name+::
|
269
|
+
# Name of a topic. (+String+)
|
270
|
+
# +data+::
|
271
|
+
# The message data. (+String+)
|
272
|
+
# +attributes+::
|
273
|
+
# Optional attributes for the message. (+Hash+)
|
274
|
+
# <code>attributes[:autocreate]</code>::
|
275
|
+
# Flag to control whether the provided topic will be created if it does
|
276
|
+
# not exist.
|
277
|
+
#
|
278
|
+
# === Returns
|
279
|
+
#
|
280
|
+
# Message object when called without a block,
|
281
|
+
# Array of Message objects when called with a block
|
282
|
+
#
|
283
|
+
# === Examples
|
284
|
+
#
|
285
|
+
# require "gcloud"
|
286
|
+
#
|
287
|
+
# gcloud = Gcloud.new
|
288
|
+
# pubsub = gcloud.pubsub
|
289
|
+
#
|
290
|
+
# msg = pubsub.publish "my-topic", "new-message"
|
291
|
+
#
|
292
|
+
# Additionally, a message can be published with attributes:
|
293
|
+
#
|
294
|
+
# require "gcloud"
|
295
|
+
#
|
296
|
+
# gcloud = Gcloud.new
|
297
|
+
# pubsub = gcloud.pubsub
|
298
|
+
#
|
299
|
+
# msg = pubsub.publish "my-topic", "new-message", foo: :bar,
|
300
|
+
# this: :that
|
301
|
+
#
|
302
|
+
# Multiple messages can be published at the same time by passing a block:
|
303
|
+
#
|
304
|
+
# require "gcloud"
|
305
|
+
#
|
306
|
+
# gcloud = Gcloud.new
|
307
|
+
# pubsub = gcloud.pubsub
|
308
|
+
#
|
309
|
+
# msgs = pubsub.publish "my-topic" do |batch|
|
310
|
+
# batch.publish "new-message-1", foo: :bar
|
311
|
+
# batch.publish "new-message-2", foo: :baz
|
312
|
+
# batch.publish "new-message-3", foo: :bif
|
313
|
+
# end
|
314
|
+
#
|
315
|
+
# Additionally, the topic will be created if the topic does previously not
|
316
|
+
# exist and the +autocreate+ option is provided.
|
317
|
+
#
|
318
|
+
# require "gcloud"
|
319
|
+
#
|
320
|
+
# gcloud = Gcloud.new
|
321
|
+
# pubsub = gcloud.pubsub
|
322
|
+
#
|
323
|
+
# msg = pubsub.publish "new-topic", "new-message", autocreate: true
|
324
|
+
#
|
325
|
+
# A note about auto-creating the topic: Any message published to a topic
|
326
|
+
# without a subscription will be lost.
|
327
|
+
#
|
328
|
+
def publish topic_name, data = nil, attributes = {}
|
329
|
+
# Fix parameters
|
330
|
+
if data.is_a?(::Hash) && attributes.empty?
|
331
|
+
attributes = data
|
332
|
+
data = nil
|
333
|
+
end
|
334
|
+
# extract autocreate option
|
335
|
+
autocreate = attributes.delete :autocreate
|
336
|
+
ensure_connection!
|
337
|
+
batch = Topic::Batch.new data, attributes
|
338
|
+
yield batch if block_given?
|
339
|
+
return nil if batch.messages.count.zero?
|
340
|
+
publish_batch_messages topic_name, batch, autocreate
|
341
|
+
end
|
342
|
+
|
343
|
+
##
|
344
|
+
# Creates a new Subscription object for the provided topic.
|
345
|
+
#
|
346
|
+
# === Parameters
|
347
|
+
#
|
348
|
+
# +topic_name+::
|
349
|
+
# Name of a topic. (+String+)
|
281
350
|
# +subscription_name+::
|
282
|
-
# Name of
|
351
|
+
# Name of the new subscription. Must start with a letter, and contain
|
352
|
+
# only letters ([A-Za-z]), numbers ([0-9], dashes (-), underscores (_),
|
353
|
+
# periods (.), tildes (~), plus (+) or percent signs (%). It must be
|
354
|
+
# between 3 and 255 characters in length, and it must not start with
|
355
|
+
# "goog". (+String+)
|
356
|
+
# +options+::
|
357
|
+
# An optional Hash for controlling additional behavior. (+Hash+)
|
358
|
+
# <code>options[:deadline]</code>::
|
359
|
+
# The maximum number of seconds after a subscriber receives a message
|
360
|
+
# before the subscriber should acknowledge the message. (+Integer+)
|
361
|
+
# <code>options[:endpoint]</code>::
|
362
|
+
# A URL locating the endpoint to which messages should be pushed.
|
363
|
+
# e.g. "https://example.com/push" (+String+)
|
364
|
+
# <code>attributes[:autocreate]</code>::
|
365
|
+
# Flag to control whether the topic will be created if it does not
|
366
|
+
# exist.
|
283
367
|
#
|
284
368
|
# === Returns
|
285
369
|
#
|
286
370
|
# Gcloud::Pubsub::Subscription
|
287
371
|
#
|
288
|
-
# ===
|
372
|
+
# === Examples
|
289
373
|
#
|
290
374
|
# require "gcloud"
|
291
375
|
#
|
292
376
|
# gcloud = Gcloud.new
|
293
377
|
# pubsub = gcloud.pubsub
|
294
378
|
#
|
295
|
-
#
|
296
|
-
# puts
|
379
|
+
# sub = pubsub.subscribe "my-topic", "my-topic-sub"
|
380
|
+
# puts sub.name # => "my-topic-sub"
|
381
|
+
#
|
382
|
+
# The name is optional, and will be generated if not given.
|
383
|
+
#
|
384
|
+
# require "gcloud"
|
385
|
+
#
|
386
|
+
# gcloud = Gcloud.new
|
387
|
+
# pubsub = gcloud.pubsub
|
388
|
+
#
|
389
|
+
# sub = pubsub.subscribe "my-topic"
|
390
|
+
# puts sub.name # => "generated-sub-name"
|
391
|
+
#
|
392
|
+
# The subscription can be created that waits two minutes for
|
393
|
+
# acknowledgement and pushed all messages to an endpoint
|
394
|
+
#
|
395
|
+
# require "gcloud"
|
396
|
+
#
|
397
|
+
# gcloud = Gcloud.new
|
398
|
+
# pubsub = gcloud.pubsub
|
297
399
|
#
|
298
|
-
|
400
|
+
# sub = pubsub.subscribe "my-topic", "my-topic-sub",
|
401
|
+
# deadline: 120,
|
402
|
+
# endpoint: "https://example.com/push"
|
403
|
+
#
|
404
|
+
# Additionally, the topic will be created if the topic does previously not
|
405
|
+
# exist and the +autocreate+ option is provided.
|
406
|
+
#
|
407
|
+
# require "gcloud"
|
408
|
+
#
|
409
|
+
# gcloud = Gcloud.new
|
410
|
+
# pubsub = gcloud.pubsub
|
411
|
+
#
|
412
|
+
# sub = pubsub.subscribe "new-topic", "new-topic-sub", autocreate: true
|
413
|
+
#
|
414
|
+
def subscribe topic_name, subscription_name, options = {}
|
299
415
|
ensure_connection!
|
300
|
-
|
301
|
-
|
416
|
+
resp = connection.create_subscription topic_name,
|
417
|
+
subscription_name, options
|
418
|
+
return Subscription.from_gapi(resp.data, connection) if resp.success?
|
419
|
+
if options[:autocreate] && resp.status == 404
|
420
|
+
create_topic topic_name
|
421
|
+
return subscribe(topic_name, subscription_name,
|
422
|
+
options.merge(autocreate: false))
|
423
|
+
end
|
424
|
+
fail ApiError.from_response(resp)
|
302
425
|
end
|
426
|
+
alias_method :create_subscription, :subscribe
|
427
|
+
alias_method :new_subscription, :subscribe
|
303
428
|
|
304
429
|
##
|
305
430
|
# Retrieves subscription by name.
|
306
|
-
# The difference between this method and Project#subscription is that
|
307
|
-
# this method makes an API call to Pub/Sub to verify the subscription
|
308
|
-
# exists.
|
309
431
|
#
|
310
432
|
# === Parameters
|
311
433
|
#
|
312
434
|
# +subscription_name+::
|
313
435
|
# Name of a subscription. (+String+)
|
436
|
+
# +options+::
|
437
|
+
# An optional Hash for controlling additional behavior. (+Hash+)
|
438
|
+
# <code>options[:project]</code>::
|
439
|
+
# If the subscription belongs to a project other than the one currently
|
440
|
+
# connected to, the alternate project ID can be specified here.
|
441
|
+
# (+String+)
|
442
|
+
# <code>options[:skip_lookup]</code>::
|
443
|
+
# Optionally create a Subscription object without verifying the
|
444
|
+
# subscription resource exists on the Pub/Sub service. Calls made on
|
445
|
+
# this object will raise errors if the service resource does not exist.
|
446
|
+
# Default is +false+. (+Boolean+)
|
314
447
|
#
|
315
448
|
# === Returns
|
316
449
|
#
|
@@ -323,19 +456,33 @@ module Gcloud
|
|
323
456
|
# gcloud = Gcloud.new
|
324
457
|
# pubsub = gcloud.pubsub
|
325
458
|
#
|
326
|
-
# subscription = pubsub.
|
459
|
+
# subscription = pubsub.subscription "my-sub"
|
460
|
+
# puts subscription.name
|
461
|
+
#
|
462
|
+
# The lookup against the Pub/Sub service can be skipped using the
|
463
|
+
# +skip_lookup+ option:
|
464
|
+
#
|
465
|
+
# require "gcloud"
|
466
|
+
#
|
467
|
+
# gcloud = Gcloud.new
|
468
|
+
# pubsub = gcloud.pubsub
|
469
|
+
#
|
470
|
+
# # No API call is made to retrieve the subscription information.
|
471
|
+
# subscription = pubsub.subscription "my-sub", skip_lookup: true
|
327
472
|
# puts subscription.name
|
328
473
|
#
|
329
|
-
def
|
474
|
+
def subscription subscription_name, options = {}
|
330
475
|
ensure_connection!
|
331
|
-
|
332
|
-
|
333
|
-
Subscription.from_gapi resp.data, connection
|
334
|
-
else
|
335
|
-
nil
|
476
|
+
if options[:skip_lookup]
|
477
|
+
return Subscription.new_lazy(subscription_name, connection, options)
|
336
478
|
end
|
479
|
+
resp = connection.get_subscription subscription_name
|
480
|
+
return Subscription.from_gapi(resp.data, connection) if resp.success?
|
481
|
+
return nil if resp.status == 404
|
482
|
+
fail ApiError.from_response(resp)
|
337
483
|
end
|
338
|
-
alias_method :
|
484
|
+
alias_method :get_subscription, :subscription
|
485
|
+
alias_method :find_subscription, :subscription
|
339
486
|
|
340
487
|
##
|
341
488
|
# Retrieves a list of subscriptions for the given project.
|
@@ -356,7 +503,7 @@ module Gcloud
|
|
356
503
|
# === Returns
|
357
504
|
#
|
358
505
|
# Array of Gcloud::Pubsub::Subscription
|
359
|
-
# (Gcloud::Pubsub::Subscription::List)
|
506
|
+
# (See Gcloud::Pubsub::Subscription::List)
|
360
507
|
#
|
361
508
|
# === Examples
|
362
509
|
#
|
@@ -409,6 +556,20 @@ module Gcloud
|
|
409
556
|
def ensure_connection!
|
410
557
|
fail "Must have active connection" unless connection
|
411
558
|
end
|
559
|
+
|
560
|
+
##
|
561
|
+
# Call the publish API with arrays of data data and attrs.
|
562
|
+
def publish_batch_messages topic_name, batch, autocreate = false
|
563
|
+
resp = connection.publish topic_name, batch.messages
|
564
|
+
if resp.success?
|
565
|
+
batch.to_gcloud_messages resp.data["messageIds"]
|
566
|
+
elsif autocreate && resp.status == 404
|
567
|
+
create_topic topic_name
|
568
|
+
publish_batch_messages topic_name, batch, false
|
569
|
+
else
|
570
|
+
fail ApiError.from_response(resp)
|
571
|
+
end
|
572
|
+
end
|
412
573
|
end
|
413
574
|
end
|
414
575
|
end
|