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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7fb40d292b456b41ebc200bcffb22da7e4ca50da
4
- data.tar.gz: b9fcf56ab01370e96b5994882ebb920269d40a73
3
+ metadata.gz: fddb2e602722db6f4c4aa081c4660a6a3291214c
4
+ data.tar.gz: 6be83a2a050318833068ccef972ae886668a5484
5
5
  SHA512:
6
- metadata.gz: 721417435023acd011e44287fa6d4cbeabc98b45f411f5d87bdd4a3bc672ea92d991e29957fadfa394d98b4d5696ca88cc55ed837ccbebc7513e934ae1d58cca
7
- data.tar.gz: dda6c253c18408035897de6c50724609e03f3d7cfa799c2d246b981ad950c9a5313379da769723ea1f8c55f46192ee70f6d6528973cacf3db44ad7397c860c9d
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
- a_func.call(request)
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
- result = nil
340
- now = Time.now
341
- deadline = now + total_timeout
342
- loop do
343
- begin
344
- result = add_timeout_arg(a_func, timeout, kwargs).call(request)
345
- break
346
- rescue => exception
347
- unless exception.respond_to?(:code) &&
348
- retry_options.retry_codes.include?(exception.code)
349
- raise RetryError, 'Exception occurred in retry method that ' \
350
- 'was not classified as transient'
351
- end
352
- sleep(rand(delay) / MILLIS_PER_SECOND)
353
- now = Time.now
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, :catch_errors, :bundleable,
359
+ module_function :create_api_call, :bundleable,
381
360
  :page_streamable, :retryable, :add_timeout_arg
382
- private_class_method :catch_errors, :bundleable, :page_streamable,
361
+ private_class_method :bundleable, :page_streamable,
383
362
  :retryable, :add_timeout_arg
384
363
  end
385
364
  end
@@ -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
@@ -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.nil?
81
- chan_creds = GRPC::Core::ChannelCredentials.new if chan_creds.nil?
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 = chan_creds.compose(call_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
@@ -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
- raise ArgumentError unless array.is_a? Array
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
@@ -29,6 +29,6 @@
29
29
 
30
30
  module Google
31
31
  module Gax
32
- VERSION = '0.8.4'.freeze
32
+ VERSION = '0.9.0'.freeze
33
33
  end
34
34
  end
@@ -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 service_path [String]
86
- # The domain name of the API remote host.
87
- # @param port [Integer]
88
- # The port on which to connect to the remote host.
89
- # @param channel [Channel]
90
- # A Channel object through which to make calls.
91
- # @param chan_creds [Grpc::ChannelCredentials]
92
- # A ChannelCredentials for the setting up the RPC client.
93
- # @param updater_proc [Proc]
94
- # A function that transforms the metadata for requests, e.g., to give
95
- # OAuth credentials.
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
- if app_name || app_version
127
- warn "`app_name` and `app_version` are no longer being used in the request headers."
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::OperationsClient.new
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 = Google::Longrunning::GetOperationRequest.new({
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::OperationsClient.new
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 = Google::Longrunning::ListOperationsRequest.new({
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::OperationsClient.new
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 = Google::Longrunning::CancelOperationRequest.new({
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::OperationsClient.new
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 = Google::Longrunning::DeleteOperationRequest.new({
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
@@ -6,9 +6,7 @@
6
6
  "DEADLINE_EXCEEDED",
7
7
  "UNAVAILABLE"
8
8
  ],
9
- "non_idempotent": [
10
- "UNAVAILABLE"
11
- ]
9
+ "non_idempotent": []
12
10
  },
13
11
  "retry_params": {
14
12
  "default": {
@@ -28,6 +28,7 @@ message User {
28
28
  string name = 1;
29
29
  UserType type = 2;
30
30
  repeated Post posts = 3;
31
+ map<string, string> map_field = 4;
31
32
  }
32
33
 
33
34
  message Post {
@@ -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.8.4
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-06-27 00:00:00.000000000 Z
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.5.1
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.5.1
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: '1.0'
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: '1.0'
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