google-gax 0.8.4 → 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.
- checksums.yaml +4 -4
- data/lib/google/gax/api_callable.rb +20 -41
- data/lib/google/gax/errors.rb +5 -0
- data/lib/google/gax/grpc.rb +70 -11
- data/lib/google/gax/util.rb +34 -6
- data/lib/google/gax/version.rb +1 -1
- data/lib/google/longrunning/operations_client.rb +62 -31
- data/lib/google/longrunning/operations_client_config.json +1 -3
- data/spec/fixtures/fixture.proto +1 -0
- data/spec/fixtures/fixture_pb.rb +1 -0
- data/spec/google/gax/grpc_spec.rb +150 -0
- data/spec/google/gax/util_spec.rb +34 -0
- metadata +23 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fddb2e602722db6f4c4aa081c4660a6a3291214c
|
|
4
|
+
data.tar.gz: 6be83a2a050318833068ccef972ae886668a5484
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7d6f35c2dcc528491d6a58dd6bf32813708995b20317363cc3eea067ae2358ffdb76da2809a4f12cb1968a1c2361c7cc6235a271c63dcb67e315fbff1a1a9de4
|
|
7
|
+
data.tar.gz: b9e48955378a15a297f967334ed6d7ff629a0a983acfc7e7e61b25bf6e58d87b7340717585aebe70f234973a86b2e86c79fbb1e4fd445f2dea2b010c0a6dfb19
|
|
@@ -32,8 +32,6 @@ require 'time'
|
|
|
32
32
|
require 'google/gax/errors'
|
|
33
33
|
require 'google/gax/bundling'
|
|
34
34
|
|
|
35
|
-
# rubocop:disable Metrics/ModuleLength
|
|
36
|
-
|
|
37
35
|
module Google
|
|
38
36
|
module Gax
|
|
39
37
|
# A class to provide the Enumerable interface for page-streaming method.
|
|
@@ -246,21 +244,9 @@ module Google
|
|
|
246
244
|
add_timeout_arg(func, this_settings.timeout,
|
|
247
245
|
this_settings.kwargs)
|
|
248
246
|
end
|
|
249
|
-
api_call = catch_errors(api_call, settings.errors)
|
|
250
|
-
api_caller.call(api_call, request, this_settings)
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
# Updates a_func to wrap exceptions with GaxError
|
|
255
|
-
#
|
|
256
|
-
# @param a_func [Proc]
|
|
257
|
-
# @param errors [Array<Exception>] Configures the exceptions to wrap.
|
|
258
|
-
# @return [Proc] A proc that will wrap certain exceptions with GaxError.
|
|
259
|
-
def catch_errors(a_func, errors)
|
|
260
|
-
proc do |request|
|
|
261
247
|
begin
|
|
262
|
-
|
|
263
|
-
rescue *errors
|
|
248
|
+
api_caller.call(api_call, request, this_settings)
|
|
249
|
+
rescue *settings.errors
|
|
264
250
|
raise GaxError, 'RPC failed'
|
|
265
251
|
end
|
|
266
252
|
end
|
|
@@ -312,8 +298,6 @@ module Google
|
|
|
312
298
|
enumerable.method(:start)
|
|
313
299
|
end
|
|
314
300
|
|
|
315
|
-
# rubocop:disable Metrics/MethodLength
|
|
316
|
-
|
|
317
301
|
# Creates a proc equivalent to a_func, but that retries on certain
|
|
318
302
|
# exceptions.
|
|
319
303
|
#
|
|
@@ -336,29 +320,24 @@ module Google
|
|
|
336
320
|
delay = retry_options.backoff_settings.initial_retry_delay_millis
|
|
337
321
|
timeout = (retry_options.backoff_settings.initial_rpc_timeout_millis /
|
|
338
322
|
MILLIS_PER_SECOND)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
delay = [delay * delay_mult, max_delay].min
|
|
355
|
-
timeout = [timeout * timeout_mult, max_timeout, deadline - now].min
|
|
356
|
-
if now >= deadline
|
|
357
|
-
raise RetryError, 'Retry total timeout exceeded with exception'
|
|
358
|
-
end
|
|
323
|
+
deadline = Time.now + total_timeout
|
|
324
|
+
begin
|
|
325
|
+
a_func.call(request, deadline: Time.now + timeout, metadata: kwargs)
|
|
326
|
+
rescue => exception
|
|
327
|
+
unless exception.respond_to?(:code) &&
|
|
328
|
+
retry_options.retry_codes.include?(exception.code)
|
|
329
|
+
raise RetryError, 'Exception occurred in retry method that ' \
|
|
330
|
+
'was not classified as transient'
|
|
331
|
+
end
|
|
332
|
+
sleep(rand(delay) / MILLIS_PER_SECOND)
|
|
333
|
+
now = Time.now
|
|
334
|
+
delay = [delay * delay_mult, max_delay].min
|
|
335
|
+
timeout = [timeout * timeout_mult, max_timeout, deadline - now].min
|
|
336
|
+
if now >= deadline
|
|
337
|
+
raise RetryError, 'Retry total timeout exceeded with exception'
|
|
359
338
|
end
|
|
339
|
+
retry
|
|
360
340
|
end
|
|
361
|
-
result
|
|
362
341
|
end
|
|
363
342
|
end
|
|
364
343
|
|
|
@@ -377,9 +356,9 @@ module Google
|
|
|
377
356
|
end
|
|
378
357
|
end
|
|
379
358
|
|
|
380
|
-
module_function :create_api_call, :
|
|
359
|
+
module_function :create_api_call, :bundleable,
|
|
381
360
|
:page_streamable, :retryable, :add_timeout_arg
|
|
382
|
-
private_class_method :
|
|
361
|
+
private_class_method :bundleable, :page_streamable,
|
|
383
362
|
:retryable, :add_timeout_arg
|
|
384
363
|
end
|
|
385
364
|
end
|
data/lib/google/gax/errors.rb
CHANGED
|
@@ -29,16 +29,21 @@
|
|
|
29
29
|
|
|
30
30
|
require 'English'
|
|
31
31
|
|
|
32
|
+
require 'google/gax/grpc'
|
|
33
|
+
|
|
32
34
|
module Google
|
|
33
35
|
module Gax
|
|
34
36
|
# Common base class for exceptions raised by GAX.
|
|
35
37
|
class GaxError < StandardError
|
|
38
|
+
attr_reader :details
|
|
39
|
+
|
|
36
40
|
# @param msg [String] describes the error that occurred.
|
|
37
41
|
def initialize(msg)
|
|
38
42
|
msg = "GaxError #{msg}"
|
|
39
43
|
msg += ", caused by #{$ERROR_INFO}" if $ERROR_INFO
|
|
40
44
|
super(msg)
|
|
41
45
|
@cause = $ERROR_INFO
|
|
46
|
+
@details = Google::Gax::Grpc.deserialize_error_status_details(@cause)
|
|
42
47
|
end
|
|
43
48
|
|
|
44
49
|
# cause is a new method introduced in 2.1.0, bring this
|
data/lib/google/gax/grpc.rb
CHANGED
|
@@ -28,7 +28,12 @@
|
|
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
30
|
require 'grpc'
|
|
31
|
+
require 'grpc/google_rpc_status_utils'
|
|
31
32
|
require 'googleauth'
|
|
33
|
+
require 'google/gax/errors'
|
|
34
|
+
require 'google/protobuf/well_known_types'
|
|
35
|
+
# Required in order to deserialize common error detail proto types
|
|
36
|
+
require 'google/rpc/error_details_pb'
|
|
32
37
|
|
|
33
38
|
module Google
|
|
34
39
|
module Gax
|
|
@@ -42,6 +47,35 @@ module Google
|
|
|
42
47
|
|
|
43
48
|
API_ERRORS = [GRPC::BadStatus, GRPC::Cancelled].freeze
|
|
44
49
|
|
|
50
|
+
def deserialize_error_status_details(error)
|
|
51
|
+
return unless error.is_a? GRPC::BadStatus
|
|
52
|
+
# If error status is malformed, swallow the gRPC error that gets raised.
|
|
53
|
+
begin
|
|
54
|
+
details =
|
|
55
|
+
GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(
|
|
56
|
+
error.to_status
|
|
57
|
+
).details
|
|
58
|
+
rescue
|
|
59
|
+
return 'Could not parse error details due to a malformed server '\
|
|
60
|
+
'response trailer.'
|
|
61
|
+
end
|
|
62
|
+
return if details.nil?
|
|
63
|
+
details =
|
|
64
|
+
GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(
|
|
65
|
+
error.to_status
|
|
66
|
+
).details
|
|
67
|
+
details.map do |any|
|
|
68
|
+
# If the type of the proto wrapped by the Any instance is not
|
|
69
|
+
# available, do not deserialize.
|
|
70
|
+
candidate_class_name = class_case(any.type_name.split('.')).join('::')
|
|
71
|
+
begin
|
|
72
|
+
any.unpack(Object.const_get(candidate_class_name))
|
|
73
|
+
rescue NameError
|
|
74
|
+
any
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
45
79
|
# rubocop:disable Metrics/ParameterLists
|
|
46
80
|
|
|
47
81
|
# Creates a gRPC client stub.
|
|
@@ -50,14 +84,14 @@ module Google
|
|
|
50
84
|
#
|
|
51
85
|
# @param port [Fixnum] The port on which to connect to the remote host.
|
|
52
86
|
#
|
|
53
|
-
# @param chan_creds [Grpc::Core::ChannelCredentials]
|
|
54
|
-
# A ChannelCredentials object for use with an SSL-enabled Channel.
|
|
55
|
-
# If nil, credentials are pulled from a default location.
|
|
56
|
-
#
|
|
57
87
|
# @param channel [Object]
|
|
58
88
|
# A Channel object through which to make calls. If nil, a secure
|
|
59
89
|
# channel is constructed.
|
|
60
90
|
#
|
|
91
|
+
# @param chan_creds [Grpc::Core::ChannelCredentials]
|
|
92
|
+
# A ChannelCredentials object for use with an SSL-enabled Channel.
|
|
93
|
+
# If nil, credentials are pulled from a default location.
|
|
94
|
+
#
|
|
61
95
|
# @param updater_proc [Proc]
|
|
62
96
|
# A function that transforms the metadata for requests, e.g., to give
|
|
63
97
|
# OAuth credentials.
|
|
@@ -66,32 +100,57 @@ module Google
|
|
|
66
100
|
# The OAuth scopes for this service. This parameter is ignored if
|
|
67
101
|
# a custom metadata_transformer is supplied.
|
|
68
102
|
#
|
|
103
|
+
# @raise [ArgumentError] if a combination channel, chan_creds, and
|
|
104
|
+
# updater_proc are passed.
|
|
105
|
+
#
|
|
69
106
|
# @yield [address, creds]
|
|
70
107
|
# the generated gRPC method to create a stub.
|
|
71
108
|
#
|
|
72
109
|
# @return A gRPC client stub.
|
|
73
110
|
def create_stub(service_path,
|
|
74
111
|
port,
|
|
75
|
-
chan_creds: nil,
|
|
76
112
|
channel: nil,
|
|
113
|
+
chan_creds: nil,
|
|
77
114
|
updater_proc: nil,
|
|
78
115
|
scopes: nil)
|
|
116
|
+
verify_params(channel, chan_creds, updater_proc)
|
|
79
117
|
address = "#{service_path}:#{port}"
|
|
80
|
-
if channel
|
|
81
|
-
|
|
118
|
+
if channel
|
|
119
|
+
yield(address, nil, channel_override: channel)
|
|
120
|
+
elsif chan_creds
|
|
121
|
+
yield(address, chan_creds)
|
|
122
|
+
else
|
|
82
123
|
if updater_proc.nil?
|
|
83
124
|
auth_creds = Google::Auth.get_application_default(scopes)
|
|
84
125
|
updater_proc = auth_creds.updater_proc
|
|
85
126
|
end
|
|
86
127
|
call_creds = GRPC::Core::CallCredentials.new(updater_proc)
|
|
87
|
-
chan_creds =
|
|
128
|
+
chan_creds = GRPC::Core::ChannelCredentials.new.compose(call_creds)
|
|
88
129
|
yield(address, chan_creds)
|
|
89
|
-
else
|
|
90
|
-
yield(address, nil, channel_override: channel)
|
|
91
130
|
end
|
|
92
131
|
end
|
|
93
132
|
|
|
94
|
-
module_function :create_stub
|
|
133
|
+
module_function :create_stub, :deserialize_error_status_details
|
|
134
|
+
|
|
135
|
+
def self.verify_params(channel, chan_creds, updater_proc)
|
|
136
|
+
if (channel && chan_creds) ||
|
|
137
|
+
(channel && updater_proc) ||
|
|
138
|
+
(chan_creds && updater_proc)
|
|
139
|
+
raise ArgumentError, 'Only one of channel, chan_creds, and ' \
|
|
140
|
+
'updater_proc should be passed into ' \
|
|
141
|
+
'Google::Gax::Grpc#create_stub.'
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Capitalize all modules except the message class, which is already
|
|
146
|
+
# correctly cased
|
|
147
|
+
def self.class_case(modules)
|
|
148
|
+
message = modules.pop
|
|
149
|
+
modules = modules.map(&:capitalize)
|
|
150
|
+
modules << message
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private_class_method :verify_params, :class_case
|
|
95
154
|
end
|
|
96
155
|
end
|
|
97
156
|
end
|
data/lib/google/gax/util.rb
CHANGED
|
@@ -30,17 +30,33 @@
|
|
|
30
30
|
module Google
|
|
31
31
|
# Gax defines Google API extensions
|
|
32
32
|
module Gax
|
|
33
|
+
# Regex used by gapic to find version files and directories.
|
|
34
|
+
VERSION_MATCHER = /
|
|
35
|
+
([vV]\d+) # Major version eg: v1
|
|
36
|
+
([pP]\d+)? # Point release eg: p2
|
|
37
|
+
(([aA]lpha|[bB]eta)\d*)? # Release level eg: alpha3
|
|
38
|
+
/x
|
|
39
|
+
|
|
33
40
|
# Creates an instance of a protobuf message from a hash that may include
|
|
34
41
|
# nested hashes. `google/protobuf` allows for the instantiation of protobuf
|
|
35
42
|
# messages using hashes but does not allow for nested hashes to instantiate
|
|
36
43
|
# nested submessages.
|
|
37
44
|
#
|
|
38
|
-
# @param hash [Hash] The hash to be converted into a proto message.
|
|
45
|
+
# @param hash [Hash || Class] The hash to be converted into a proto message.
|
|
46
|
+
# If an instance of the proto message class is given, it is returned
|
|
47
|
+
# unchanged.
|
|
39
48
|
# @param message_class [Class] The corresponding protobuf message class of
|
|
40
49
|
# the given hash.
|
|
41
50
|
#
|
|
42
51
|
# @return [Object] An instance of the given message class.
|
|
43
52
|
def to_proto(hash, message_class)
|
|
53
|
+
return hash if hash.is_a? message_class
|
|
54
|
+
|
|
55
|
+
# Sanity check: input must be a Hash
|
|
56
|
+
unless hash.is_a? Hash
|
|
57
|
+
raise ArgumentError,
|
|
58
|
+
"Value #{hash} must be a Hash or a #{message_class.name}"
|
|
59
|
+
end
|
|
44
60
|
hash = coerce_submessages(hash, message_class)
|
|
45
61
|
message_class.new(hash)
|
|
46
62
|
end
|
|
@@ -83,7 +99,7 @@ module Google
|
|
|
83
99
|
#
|
|
84
100
|
# @return [Object] The coerced version of the given value.
|
|
85
101
|
def coerce_submessage(val, field_descriptor)
|
|
86
|
-
if field_descriptor.label == :repeated
|
|
102
|
+
if (field_descriptor.label == :repeated) && !(map_field? field_descriptor)
|
|
87
103
|
coerce_array(val, field_descriptor)
|
|
88
104
|
else
|
|
89
105
|
coerce(val, field_descriptor)
|
|
@@ -101,12 +117,24 @@ module Google
|
|
|
101
117
|
#
|
|
102
118
|
# @return [Array<Object>] The coerced version of the given values.
|
|
103
119
|
def coerce_array(array, field_descriptor)
|
|
104
|
-
|
|
120
|
+
unless array.is_a? Array
|
|
121
|
+
raise ArgumentError, 'Value ' + array.to_s + ' must be an array'
|
|
122
|
+
end
|
|
105
123
|
array.map do |val|
|
|
106
124
|
coerce(val, field_descriptor)
|
|
107
125
|
end
|
|
108
126
|
end
|
|
109
127
|
|
|
128
|
+
# Hack to determine if field_descriptor is for a map.
|
|
129
|
+
#
|
|
130
|
+
# TODO(geigerj): Remove this once protobuf Ruby supports an official way
|
|
131
|
+
# to determine if a FieldDescriptor represents a map.
|
|
132
|
+
# See: https://github.com/google/protobuf/issues/3425
|
|
133
|
+
def map_field?(field_descriptor)
|
|
134
|
+
(field_descriptor.label == :repeated) &&
|
|
135
|
+
(field_descriptor.subtype.name.include? '_MapEntry_')
|
|
136
|
+
end
|
|
137
|
+
|
|
110
138
|
# Coerces the value of a field to be acceptable by the instantiation method
|
|
111
139
|
# of the wrapping message.
|
|
112
140
|
#
|
|
@@ -118,13 +146,13 @@ module Google
|
|
|
118
146
|
#
|
|
119
147
|
# @return [Object] The coerced version of the given value.
|
|
120
148
|
def coerce(val, field_descriptor)
|
|
121
|
-
return val unless val.is_a? Hash
|
|
149
|
+
return val unless (val.is_a? Hash) && !(map_field? field_descriptor)
|
|
122
150
|
to_proto(val, field_descriptor.subtype.msgclass)
|
|
123
151
|
end
|
|
124
152
|
|
|
125
153
|
module_function :to_proto, :coerce_submessages, :coerce_submessage,
|
|
126
|
-
:coerce_array, :coerce
|
|
154
|
+
:coerce_array, :coerce, :map_field?
|
|
127
155
|
private_class_method :coerce_submessages, :coerce_submessage, :coerce_array,
|
|
128
|
-
:coerce
|
|
156
|
+
:coerce, :map_field?
|
|
129
157
|
end
|
|
130
158
|
end
|
data/lib/google/gax/version.rb
CHANGED
|
@@ -40,6 +40,7 @@ require "json"
|
|
|
40
40
|
require "pathname"
|
|
41
41
|
|
|
42
42
|
require "google/gax"
|
|
43
|
+
require "googleauth"
|
|
43
44
|
|
|
44
45
|
require "google/longrunning/operations_pb"
|
|
45
46
|
|
|
@@ -48,7 +49,7 @@ module Google
|
|
|
48
49
|
# Manages long-running operations with an API service.
|
|
49
50
|
#
|
|
50
51
|
# When an API method normally takes long time to complete, it can be designed
|
|
51
|
-
# to return Operation to the client, and the client can use this
|
|
52
|
+
# to return {Google::Longrunning::Operation Operation} to the client, and the client can use this
|
|
52
53
|
# interface to receive the real response asynchronously by polling the
|
|
53
54
|
# operation resource, or pass the operation resource to another API (such as
|
|
54
55
|
# Google Cloud Pub/Sub API) to receive the response. Any API service that
|
|
@@ -82,21 +83,24 @@ module Google
|
|
|
82
83
|
ALL_SCOPES = [
|
|
83
84
|
].freeze
|
|
84
85
|
|
|
85
|
-
# @param
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
# A
|
|
91
|
-
#
|
|
92
|
-
# A
|
|
93
|
-
#
|
|
94
|
-
# A
|
|
95
|
-
#
|
|
86
|
+
# @param credentials [Google::Auth::Credentials, String, Hash, GRPC::Core::Channel, GRPC::Core::ChannelCredentials, Proc]
|
|
87
|
+
# Provides the means for authenticating requests made by the client. This parameter can
|
|
88
|
+
# be many types.
|
|
89
|
+
# A `Google::Auth::Credentials` uses a the properties of its represented keyfile for
|
|
90
|
+
# authenticating requests made by this client.
|
|
91
|
+
# A `String` will be treated as the path to the keyfile to be used for the construction of
|
|
92
|
+
# credentials for this client.
|
|
93
|
+
# A `Hash` will be treated as the contents of a keyfile to be used for the construction of
|
|
94
|
+
# credentials for this client.
|
|
95
|
+
# A `GRPC::Core::Channel` will be used to make calls through.
|
|
96
|
+
# A `GRPC::Core::ChannelCredentials` for the setting up the RPC client. The channel credentials
|
|
97
|
+
# should already be composed with a `GRPC::Core::CallCredentials` object.
|
|
98
|
+
# A `Proc` will be used as an updater_proc for the Grpc channel. The proc transforms the
|
|
99
|
+
# metadata for requests, generally, to give OAuth credentials.
|
|
96
100
|
# @param scopes [Array<String>]
|
|
97
101
|
# The OAuth scopes for this service. This parameter is ignored if
|
|
98
102
|
# an updater_proc is supplied.
|
|
99
|
-
# @param client_config[Hash]
|
|
103
|
+
# @param client_config [Hash]
|
|
100
104
|
# A Hash for call options for each method. See
|
|
101
105
|
# Google::Gax#construct_settings for the structure of
|
|
102
106
|
# this data. Falls back to the default config if not specified
|
|
@@ -109,11 +113,10 @@ module Google
|
|
|
109
113
|
channel: nil,
|
|
110
114
|
chan_creds: nil,
|
|
111
115
|
updater_proc: nil,
|
|
116
|
+
credentials: nil,
|
|
112
117
|
scopes: ALL_SCOPES,
|
|
113
118
|
client_config: {},
|
|
114
119
|
timeout: DEFAULT_TIMEOUT,
|
|
115
|
-
app_name: nil,
|
|
116
|
-
app_version: nil,
|
|
117
120
|
lib_name: nil,
|
|
118
121
|
lib_version: ""
|
|
119
122
|
# These require statements are intentionally placed here to initialize
|
|
@@ -122,9 +125,33 @@ module Google
|
|
|
122
125
|
require "google/gax/grpc"
|
|
123
126
|
require "google/longrunning/operations_services_pb"
|
|
124
127
|
|
|
128
|
+
if channel || chan_creds || updater_proc
|
|
129
|
+
warn "The `channel`, `chan_creds`, and `updater_proc` parameters will be removed " \
|
|
130
|
+
"on 2017/09/08"
|
|
131
|
+
credentials ||= channel
|
|
132
|
+
credentials ||= chan_creds
|
|
133
|
+
credentials ||= updater_proc
|
|
134
|
+
end
|
|
135
|
+
if service_path != SERVICE_ADDRESS || port != DEFAULT_SERVICE_PORT
|
|
136
|
+
warn "`service_path` and `port` parameters are deprecated and will be removed"
|
|
137
|
+
end
|
|
125
138
|
|
|
126
|
-
|
|
127
|
-
|
|
139
|
+
credentials ||= Google::Auth::Credentials.default(scopes: scopes)
|
|
140
|
+
|
|
141
|
+
if credentials.is_a?(String) || credentials.is_a?(Hash)
|
|
142
|
+
updater_proc = Google::Auth::Credentials.new(credentials).updater_proc
|
|
143
|
+
end
|
|
144
|
+
if credentials.is_a?(GRPC::Core::Channel)
|
|
145
|
+
channel = credentials
|
|
146
|
+
end
|
|
147
|
+
if credentials.is_a?(GRPC::Core::ChannelCredentials)
|
|
148
|
+
chan_creds = credentials
|
|
149
|
+
end
|
|
150
|
+
if credentials.is_a?(Proc)
|
|
151
|
+
updater_proc = credentials
|
|
152
|
+
end
|
|
153
|
+
if credentials.is_a?(Google::Auth::Credentials)
|
|
154
|
+
updater_proc = credentials.updater_proc
|
|
128
155
|
end
|
|
129
156
|
|
|
130
157
|
google_api_client = "gl-ruby/#{RUBY_VERSION}"
|
|
@@ -193,16 +220,17 @@ module Google
|
|
|
193
220
|
# @example
|
|
194
221
|
# require "google/longrunning"
|
|
195
222
|
#
|
|
196
|
-
# operations_client = Google::Longrunning
|
|
223
|
+
# operations_client = Google::Longrunning.new
|
|
197
224
|
# name = ''
|
|
198
225
|
# response = operations_client.get_operation(name)
|
|
199
226
|
|
|
200
227
|
def get_operation \
|
|
201
228
|
name,
|
|
202
229
|
options: nil
|
|
203
|
-
req =
|
|
230
|
+
req = {
|
|
204
231
|
name: name
|
|
205
|
-
}.delete_if { |_, v| v.nil? }
|
|
232
|
+
}.delete_if { |_, v| v.nil? }
|
|
233
|
+
req = Google::Gax::to_proto(req, Google::Longrunning::GetOperationRequest)
|
|
206
234
|
@get_operation.call(req, options)
|
|
207
235
|
end
|
|
208
236
|
|
|
@@ -234,7 +262,7 @@ module Google
|
|
|
234
262
|
# @example
|
|
235
263
|
# require "google/longrunning"
|
|
236
264
|
#
|
|
237
|
-
# operations_client = Google::Longrunning
|
|
265
|
+
# operations_client = Google::Longrunning.new
|
|
238
266
|
# name = ''
|
|
239
267
|
# filter = ''
|
|
240
268
|
#
|
|
@@ -256,11 +284,12 @@ module Google
|
|
|
256
284
|
filter,
|
|
257
285
|
page_size: nil,
|
|
258
286
|
options: nil
|
|
259
|
-
req =
|
|
287
|
+
req = {
|
|
260
288
|
name: name,
|
|
261
289
|
filter: filter,
|
|
262
290
|
page_size: page_size
|
|
263
|
-
}.delete_if { |_, v| v.nil? }
|
|
291
|
+
}.delete_if { |_, v| v.nil? }
|
|
292
|
+
req = Google::Gax::to_proto(req, Google::Longrunning::ListOperationsRequest)
|
|
264
293
|
@list_operations.call(req, options)
|
|
265
294
|
end
|
|
266
295
|
|
|
@@ -268,11 +297,11 @@ module Google
|
|
|
268
297
|
# makes a best effort to cancel the operation, but success is not
|
|
269
298
|
# guaranteed. If the server doesn't support this method, it returns
|
|
270
299
|
# +google.rpc.Code.UNIMPLEMENTED+. Clients can use
|
|
271
|
-
# Operations::GetOperation or
|
|
300
|
+
# {Google::Longrunning::Operations::GetOperation Operations::GetOperation} or
|
|
272
301
|
# other methods to check whether the cancellation succeeded or whether the
|
|
273
302
|
# operation completed despite cancellation. On successful cancellation,
|
|
274
303
|
# the operation is not deleted; instead, it becomes an operation with
|
|
275
|
-
# an Operation#error value with a Google::Rpc::Status#code of 1,
|
|
304
|
+
# an {Google::Longrunning::Operation#error Operation#error} value with a {Google::Rpc::Status#code} of 1,
|
|
276
305
|
# corresponding to +Code.CANCELLED+.
|
|
277
306
|
#
|
|
278
307
|
# @param name [String]
|
|
@@ -284,16 +313,17 @@ module Google
|
|
|
284
313
|
# @example
|
|
285
314
|
# require "google/longrunning"
|
|
286
315
|
#
|
|
287
|
-
# operations_client = Google::Longrunning
|
|
316
|
+
# operations_client = Google::Longrunning.new
|
|
288
317
|
# name = ''
|
|
289
318
|
# operations_client.cancel_operation(name)
|
|
290
319
|
|
|
291
320
|
def cancel_operation \
|
|
292
321
|
name,
|
|
293
322
|
options: nil
|
|
294
|
-
req =
|
|
323
|
+
req = {
|
|
295
324
|
name: name
|
|
296
|
-
}.delete_if { |_, v| v.nil? }
|
|
325
|
+
}.delete_if { |_, v| v.nil? }
|
|
326
|
+
req = Google::Gax::to_proto(req, Google::Longrunning::CancelOperationRequest)
|
|
297
327
|
@cancel_operation.call(req, options)
|
|
298
328
|
nil
|
|
299
329
|
end
|
|
@@ -312,16 +342,17 @@ module Google
|
|
|
312
342
|
# @example
|
|
313
343
|
# require "google/longrunning"
|
|
314
344
|
#
|
|
315
|
-
# operations_client = Google::Longrunning
|
|
345
|
+
# operations_client = Google::Longrunning.new
|
|
316
346
|
# name = ''
|
|
317
347
|
# operations_client.delete_operation(name)
|
|
318
348
|
|
|
319
349
|
def delete_operation \
|
|
320
350
|
name,
|
|
321
351
|
options: nil
|
|
322
|
-
req =
|
|
352
|
+
req = {
|
|
323
353
|
name: name
|
|
324
|
-
}.delete_if { |_, v| v.nil? }
|
|
354
|
+
}.delete_if { |_, v| v.nil? }
|
|
355
|
+
req = Google::Gax::to_proto(req, Google::Longrunning::DeleteOperationRequest)
|
|
325
356
|
@delete_operation.call(req, options)
|
|
326
357
|
nil
|
|
327
358
|
end
|
data/spec/fixtures/fixture.proto
CHANGED
data/spec/fixtures/fixture_pb.rb
CHANGED
|
@@ -12,6 +12,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
|
12
12
|
optional :name, :string, 1
|
|
13
13
|
optional :type, :enum, 2, "google.protobuf.User.UserType"
|
|
14
14
|
repeated :posts, :message, 3, "google.protobuf.Post"
|
|
15
|
+
map :map_field, :string, :string, 4
|
|
15
16
|
end
|
|
16
17
|
add_enum "google.protobuf.User.UserType" do
|
|
17
18
|
value :UNSPECIFIED, 0
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Copyright 2017, Google Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are
|
|
6
|
+
# met:
|
|
7
|
+
#
|
|
8
|
+
# * Redistributions of source code must retain the above copyright
|
|
9
|
+
# notice, this list of conditions and the following disclaimer.
|
|
10
|
+
# * Redistributions in binary form must reproduce the above
|
|
11
|
+
# copyright notice, this list of conditions and the following disclaimer
|
|
12
|
+
# in the documentation and/or other materials provided with the
|
|
13
|
+
# distribution.
|
|
14
|
+
# * Neither the name of Google Inc. nor the names of its
|
|
15
|
+
# contributors may be used to endorse or promote products derived from
|
|
16
|
+
# this software without specific prior written permission.
|
|
17
|
+
#
|
|
18
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
+
|
|
30
|
+
require 'google/gax/grpc'
|
|
31
|
+
|
|
32
|
+
describe Google::Gax::Grpc do
|
|
33
|
+
describe '#create_stub' do
|
|
34
|
+
it 'yields constructed channel credentials' do
|
|
35
|
+
mock = instance_double(GRPC::Core::ChannelCredentials)
|
|
36
|
+
composed_mock = instance_double(GRPC::Core::ChannelCredentials)
|
|
37
|
+
default_creds = instance_double(Google::Auth::ServiceAccountCredentials)
|
|
38
|
+
updater_proc = proc {}
|
|
39
|
+
|
|
40
|
+
allow(Google::Auth)
|
|
41
|
+
.to receive(:get_application_default).and_return(default_creds)
|
|
42
|
+
allow(default_creds).to receive(:updater_proc).and_return(updater_proc)
|
|
43
|
+
allow(mock).to receive(:compose).and_return(composed_mock)
|
|
44
|
+
allow(GRPC::Core::ChannelCredentials).to receive(:new).and_return(mock)
|
|
45
|
+
|
|
46
|
+
expect do |blk|
|
|
47
|
+
Google::Gax::Grpc.create_stub('service', 'port', &blk)
|
|
48
|
+
end.to yield_with_args('service:port', composed_mock)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'yields given channel' do
|
|
52
|
+
mock = instance_double(GRPC::Core::Channel)
|
|
53
|
+
expect do |blk|
|
|
54
|
+
Google::Gax::Grpc.create_stub('service', 'port', channel: mock, &blk)
|
|
55
|
+
end.to yield_with_args('service:port', nil, channel_override: mock)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'yields given channel credentials' do
|
|
59
|
+
mock = instance_double(GRPC::Core::ChannelCredentials)
|
|
60
|
+
expect do |blk|
|
|
61
|
+
Google::Gax::Grpc.create_stub('service', 'port', chan_creds: mock, &blk)
|
|
62
|
+
end.to yield_with_args('service:port', mock)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'yields channel credentials composed of the given updater_proc' do
|
|
66
|
+
chan_creds = instance_double(GRPC::Core::ChannelCredentials)
|
|
67
|
+
composed_chan_creds = instance_double(GRPC::Core::ChannelCredentials)
|
|
68
|
+
call_creds = instance_double(GRPC::Core::CallCredentials)
|
|
69
|
+
updater_proc = proc {}
|
|
70
|
+
|
|
71
|
+
allow(GRPC::Core::CallCredentials)
|
|
72
|
+
.to receive(:new).with(updater_proc).and_return(call_creds)
|
|
73
|
+
allow(GRPC::Core::ChannelCredentials)
|
|
74
|
+
.to receive(:new).and_return(chan_creds)
|
|
75
|
+
allow(chan_creds)
|
|
76
|
+
.to receive(:compose).with(call_creds).and_return(composed_chan_creds)
|
|
77
|
+
expect do |blk|
|
|
78
|
+
Google::Gax::Grpc.create_stub(
|
|
79
|
+
'service', 'port', updater_proc: updater_proc, &blk
|
|
80
|
+
)
|
|
81
|
+
end.to yield_with_args('service:port', composed_chan_creds)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'raise an argument error if multiple creds are passed in' do
|
|
85
|
+
channel = instance_double(GRPC::Core::Channel)
|
|
86
|
+
chan_creds = instance_double(GRPC::Core::ChannelCredentials)
|
|
87
|
+
updater_proc = instance_double(Proc)
|
|
88
|
+
|
|
89
|
+
expect do |blk|
|
|
90
|
+
Google::Gax::Grpc.create_stub(
|
|
91
|
+
'service', 'port', channel: channel, chan_creds: chan_creds, &blk
|
|
92
|
+
)
|
|
93
|
+
end.to raise_error(ArgumentError)
|
|
94
|
+
|
|
95
|
+
expect do |blk|
|
|
96
|
+
Google::Gax::Grpc.create_stub(
|
|
97
|
+
'service', 'port', channel: channel,
|
|
98
|
+
updater_proc: updater_proc, &blk
|
|
99
|
+
)
|
|
100
|
+
end.to raise_error(ArgumentError)
|
|
101
|
+
|
|
102
|
+
expect do |blk|
|
|
103
|
+
Google::Gax::Grpc.create_stub(
|
|
104
|
+
'service', 'port', chan_creds: chan_creds,
|
|
105
|
+
updater_proc: updater_proc, &blk
|
|
106
|
+
)
|
|
107
|
+
end.to raise_error(ArgumentError)
|
|
108
|
+
|
|
109
|
+
expect do |blk|
|
|
110
|
+
Google::Gax::Grpc.create_stub(
|
|
111
|
+
'service', 'port', channel: channel, chan_creds: chan_creds,
|
|
112
|
+
updater_proc: updater_proc, &blk
|
|
113
|
+
)
|
|
114
|
+
end.to raise_error(ArgumentError)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
describe '#deserialize_error_status_details' do
|
|
118
|
+
it 'deserializes a known error type' do
|
|
119
|
+
expected_error = Google::Rpc::DebugInfo.new(detail: 'shoes are untied')
|
|
120
|
+
|
|
121
|
+
any = Google::Protobuf::Any.new
|
|
122
|
+
any.pack(expected_error)
|
|
123
|
+
status = Google::Rpc::Status.new(details: [any])
|
|
124
|
+
encoded = Google::Rpc::Status.encode(status)
|
|
125
|
+
metadata = {
|
|
126
|
+
'grpc-status-details-bin' => encoded
|
|
127
|
+
}
|
|
128
|
+
error = GRPC::BadStatus.new(1, '', metadata)
|
|
129
|
+
|
|
130
|
+
expect(Google::Gax::Grpc.deserialize_error_status_details(error))
|
|
131
|
+
.to eq [expected_error]
|
|
132
|
+
end
|
|
133
|
+
it 'does not deserialize an unknown error type' do
|
|
134
|
+
expected_error = Random.new.bytes(8)
|
|
135
|
+
|
|
136
|
+
any = Google::Protobuf::Any.new(
|
|
137
|
+
type_url: 'unknown-type', value: expected_error
|
|
138
|
+
)
|
|
139
|
+
status = Google::Rpc::Status.new(details: [any])
|
|
140
|
+
encoded = Google::Rpc::Status.encode(status)
|
|
141
|
+
metadata = {
|
|
142
|
+
'grpc-status-details-bin' => encoded
|
|
143
|
+
}
|
|
144
|
+
error = GRPC::BadStatus.new(1, '', metadata)
|
|
145
|
+
|
|
146
|
+
expect(Google::Gax::Grpc.deserialize_error_status_details(error))
|
|
147
|
+
.to eq [any]
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
30
|
require 'google/gax'
|
|
31
|
+
require 'google/protobuf/any_pb'
|
|
31
32
|
require 'spec/fixtures/fixture_pb'
|
|
32
33
|
|
|
33
34
|
describe Google::Gax do
|
|
@@ -36,6 +37,10 @@ describe Google::Gax do
|
|
|
36
37
|
USER_NAME = 'Ernest'.freeze
|
|
37
38
|
USER_TYPE = :ADMINISTRATOR
|
|
38
39
|
POST_TEXT = 'This is a test post.'.freeze
|
|
40
|
+
MAP = {
|
|
41
|
+
'key1' => 'val1',
|
|
42
|
+
'key2' => 'val2'
|
|
43
|
+
}.freeze
|
|
39
44
|
|
|
40
45
|
it 'creates a protobuf message from a simple hash' do
|
|
41
46
|
hash = { name: USER_NAME, type: USER_TYPE }
|
|
@@ -91,6 +96,20 @@ describe Google::Gax do
|
|
|
91
96
|
end
|
|
92
97
|
end
|
|
93
98
|
|
|
99
|
+
it 'handles maps' do
|
|
100
|
+
request_hash = {
|
|
101
|
+
name: USER_NAME,
|
|
102
|
+
map_field: MAP
|
|
103
|
+
}
|
|
104
|
+
user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
|
|
105
|
+
expect(user).to be_an_instance_of(Google::Protobuf::User)
|
|
106
|
+
expect(user.name).to eq(USER_NAME)
|
|
107
|
+
expect(user.map_field).to be_an_instance_of(Google::Protobuf::Map)
|
|
108
|
+
user.map_field.each do |k, v|
|
|
109
|
+
expect(MAP[k]).to eq v
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
94
113
|
it 'fails if a key does not exist in the target message type' do
|
|
95
114
|
user_hash = {
|
|
96
115
|
name: USER_NAME,
|
|
@@ -100,5 +119,20 @@ describe Google::Gax do
|
|
|
100
119
|
Google::Gax.to_proto(user_hash, Google::Protobuf::User)
|
|
101
120
|
end.to raise_error(ArgumentError)
|
|
102
121
|
end
|
|
122
|
+
|
|
123
|
+
it 'handles proto messages' do
|
|
124
|
+
user_message = Google::Protobuf::User.new(
|
|
125
|
+
name: USER_NAME, type: USER_TYPE
|
|
126
|
+
)
|
|
127
|
+
user = Google::Gax.to_proto(user_message, Google::Protobuf::User)
|
|
128
|
+
expect(user).to eq user_message
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'fails if proto message has unexpected type' do
|
|
132
|
+
user_message = Google::Protobuf::Any
|
|
133
|
+
expect do
|
|
134
|
+
Google::Gax.to_proto(user_message, Google::Protobuf::User)
|
|
135
|
+
end.to raise_error(ArgumentError)
|
|
136
|
+
end
|
|
103
137
|
end
|
|
104
138
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: google-gax
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Google API Authors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-11-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: googleauth
|
|
@@ -16,42 +16,54 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.6.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.6.1
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: grpc
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 1.7.2
|
|
34
|
+
- - "<"
|
|
32
35
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
36
|
+
version: '2.0'
|
|
34
37
|
type: :runtime
|
|
35
38
|
prerelease: false
|
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
40
|
requirements:
|
|
38
|
-
- - "
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 1.7.2
|
|
44
|
+
- - "<"
|
|
39
45
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
46
|
+
version: '2.0'
|
|
41
47
|
- !ruby/object:Gem::Dependency
|
|
42
48
|
name: googleapis-common-protos
|
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
|
44
50
|
requirements:
|
|
45
|
-
- - "
|
|
51
|
+
- - ">="
|
|
46
52
|
- !ruby/object:Gem::Version
|
|
47
53
|
version: 1.3.5
|
|
54
|
+
- - "<"
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '2.0'
|
|
48
57
|
type: :runtime
|
|
49
58
|
prerelease: false
|
|
50
59
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
60
|
requirements:
|
|
52
|
-
- - "
|
|
61
|
+
- - ">="
|
|
53
62
|
- !ruby/object:Gem::Version
|
|
54
63
|
version: 1.3.5
|
|
64
|
+
- - "<"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '2.0'
|
|
55
67
|
- !ruby/object:Gem::Dependency
|
|
56
68
|
name: google-protobuf
|
|
57
69
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -175,6 +187,7 @@ files:
|
|
|
175
187
|
- spec/fixtures/fixture_pb.rb
|
|
176
188
|
- spec/google/gax/api_callable_spec.rb
|
|
177
189
|
- spec/google/gax/bundling_spec.rb
|
|
190
|
+
- spec/google/gax/grpc_spec.rb
|
|
178
191
|
- spec/google/gax/operation_spec.rb
|
|
179
192
|
- spec/google/gax/path_template_spec.rb
|
|
180
193
|
- spec/google/gax/settings_spec.rb
|