gapic-generator 0.51.1 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/lib/gapic/formatting_utils.rb +85 -18
  4. data/lib/gapic/generator/version.rb +1 -1
  5. data/lib/gapic/generators/default_generator.rb +6 -0
  6. data/lib/gapic/generators/default_generator_parameters.rb +2 -0
  7. data/lib/gapic/model/method/resumable_upload.rb +143 -0
  8. data/lib/gapic/presenters/gem_presenter.rb +1 -1
  9. data/lib/gapic/presenters/method_presenter.rb +35 -0
  10. data/lib/gapic/presenters/service_presenter.rb +65 -0
  11. data/lib/gapic/presenters/service_rest_presenter.rb +12 -0
  12. data/lib/gapic/presenters/snippet/response_handling_presenters.rb +60 -0
  13. data/lib/gapic/presenters/snippet_presenter.rb +16 -6
  14. data/templates/default/lib/_service.text.erb +3 -0
  15. data/templates/default/lib/rest/_rest.text.erb +3 -0
  16. data/templates/default/service/client/_client.text.erb +18 -0
  17. data/templates/default/service/client/_config.text.erb +8 -0
  18. data/templates/default/service/client/method/_def.text.erb +5 -1
  19. data/templates/default/service/client/method/def/_options_defaults.text.erb +5 -0
  20. data/templates/default/service/client/method/def/_response.text.erb +3 -1
  21. data/templates/default/service/client/method/def/_response_resumable_upload.text.erb +13 -0
  22. data/templates/default/service/client/method/def/_upload_error_handler.text.erb +2 -0
  23. data/templates/default/service/client/method/docs/_request_normal.text.erb +19 -0
  24. data/templates/default/service/client/method/docs/_response.text.erb +8 -0
  25. data/templates/default/service/rest/client/_client.text.erb +18 -0
  26. data/templates/default/service/rest/client/_config.text.erb +8 -0
  27. data/templates/default/service/rest/client/method/_def.text.erb +5 -1
  28. data/templates/default/service/rest/client/method/def/_response.text.erb +3 -1
  29. data/templates/default/service/rest/client/method/def/_response_resumable_upload.text.erb +13 -0
  30. data/templates/default/service/rest/client/method/def/_upload_error_handler.text.erb +2 -0
  31. data/templates/default/service/rest/client/method/docs/_request.text.erb +19 -0
  32. data/templates/default/service/rest/client/method/docs/_result.text.erb +7 -1
  33. data/templates/default/service/rest/service_stub/_service_stub.text.erb +2 -2
  34. data/templates/default/service/rest/service_stub/grpc_transcoding_method/_bindings.text.erb +15 -0
  35. data/templates/default/service/rest/service_stub/grpc_transcoding_method/_def.text.erb +1 -14
  36. data/templates/default/service/rest/test/client.text.erb +1 -1
  37. data/templates/default/service/resumable_upload_stub/_resumable_upload_stub.text.erb +64 -0
  38. data/templates/default/service/resumable_upload_stub/_transcoding_method.text.erb +22 -0
  39. data/templates/default/service/resumable_upload_stub.text.erb +6 -0
  40. data/templates/default/service/test/client.text.erb +1 -1
  41. data/templates/default/service/test/resumable_upload.text.erb +132 -0
  42. metadata +11 -1
@@ -20,6 +20,14 @@ require "securerandom"
20
20
  <%= indent service.doc_description(transport: :grpc), "# " %>
21
21
  #
22
22
  <%- end -%>
23
+ <%- if service.resumable_upload? -%>
24
+ <%- upload_names = service.resumable_upload_methods.map { |upload_method| "`#{upload_method.name}`" }.join ", " -%>
25
+ <%- upload_many = service.resumable_upload_methods.length > 1 -%>
26
+ # <%= upload_names %> <%= upload_many ? "perform resumable uploads: each returns" : "performs a resumable upload: it returns" %> a {::Gapic::ResumableUpload} handle
27
+ # instead of a response, and the per-call `timeout` and retry policy cover only the request that
28
+ # creates the upload session, not the upload itself.
29
+ #
30
+ <%- end -%>
23
31
  class <%= service.client_name %>
24
32
  # @private
25
33
  API_VERSION = "<%= service.api_version %>".freeze
@@ -140,6 +148,16 @@ class <%= service.client_name %>
140
148
  config.universe_domain = @config.universe_domain
141
149
  end
142
150
 
151
+ <%- end -%>
152
+ <%- if service.resumable_upload? -%>
153
+ <%= service.resumable_upload_stub_ivar %> = <%= service.resumable_upload_stub_name_full %>.new(
154
+ endpoint: @config.endpoint,
155
+ endpoint_template: DEFAULT_ENDPOINT_TEMPLATE,
156
+ universe_domain: @config.universe_domain,
157
+ credentials: credentials,
158
+ logger: @config.logger
159
+ )
160
+
143
161
  <%- end -%>
144
162
  @<%= service.stub_name %> = ::Gapic::ServiceStub.new(
145
163
  <%= service.proto_service_stub_name_full %>,
@@ -190,6 +190,14 @@ class Configuration
190
190
  <%- method_service.methods.each do |method| -%>
191
191
  ##
192
192
  # RPC-specific configuration for `<%= method.name %>`
193
+ <%- if method.resumable_upload? -%>
194
+ #
195
+ # `<%= method.name %>` performs a resumable upload, so the `timeout` and `retry_policy`
196
+ # configured here cover the request that creates the upload session only, not the upload
197
+ # itself. The whole-upload budget is the `upload_timeout:` argument of
198
+ # {::Gapic::ResumableUpload#start} and {::Gapic::ResumableUpload#resume}.
199
+ #
200
+ <%- end -%>
193
201
  # @return [::Gapic::Config::Method]
194
202
  #
195
203
  attr_reader :<%= method.name %>
@@ -9,15 +9,19 @@
9
9
  #
10
10
  <%= render partial: "service/client/method/docs/response", locals: { method: method } -%>
11
11
  #
12
+ <%- unless method.resumable_upload? -%>
12
13
  <%= render partial: "service/client/method/docs/error", locals: { method: method } -%>
13
14
  #
15
+ <%- end -%>
14
16
  <%= render partial: "service/client/method/docs/snippets", locals: { method: method } -%>
15
17
  <%= render partial: "service/client/method/docs/samples", locals: { method: method } -%>
16
- def <%= method.name %> request, options = nil
18
+ def <%= method.name %> request<%= method.resumable_upload? ? " = {}" : "" %>, options = nil
17
19
  <%= indent render(partial: "service/client/method/def/request", locals: { method: method }), 2 %>
18
20
 
19
21
  <%= indent render(partial: "service/client/method/def/options_defaults", locals: { method: method }), 2 %>
20
22
 
21
23
  <%= indent render(partial: "service/client/method/def/response", locals: { method: method }), 2 %>
24
+ <%- unless method.resumable_upload? -%>
22
25
  <%= render partial: "service/client/method/def/rescue", locals: { method: method } -%>
26
+ <%- end -%>
23
27
  end
@@ -8,7 +8,12 @@ metadata = @config.rpcs.<%= method.name %>.metadata.to_h
8
8
  # Set x-goog-api-client, x-goog-user-project and x-goog-api-version headers
9
9
  metadata[:"x-goog-api-client"] ||= ::Gapic::Headers.x_goog_api_client \
10
10
  lib_name: @config.lib_name, lib_version: @config.lib_version,
11
+ <%- if method.resumable_upload? -%>
12
+ gapic_version: ::<%= method.service.gem.version_name_full %>,
13
+ transports_version_send: [:rest]
14
+ <%- else -%>
11
15
  gapic_version: ::<%= method.service.gem.version_name_full %>
16
+ <%- end -%>
12
17
  metadata[:"x-goog-api-version"] = API_VERSION unless API_VERSION.empty?
13
18
  metadata[:"x-goog-user-project"] = @quota_project_id if @quota_project_id
14
19
  <%- if method.routing_params? && !method.client_streaming? -%>
@@ -1,5 +1,7 @@
1
1
  <%- assert_locals method -%>
2
- <%- if method.paged? -%>
2
+ <%- if method.resumable_upload? -%>
3
+ <%= render partial: "service/client/method/def/response_resumable_upload", locals: { method: method } -%>
4
+ <%- elsif method.paged? -%>
3
5
  <%= render partial: "service/client/method/def/response_paged", locals: { method: method } -%>
4
6
  <%- elsif method.rest.nonstandard_lro? -%>
5
7
  <%= render partial: "service/client/method/def/response_nonstandard_lro", locals: { method: method } -%>
@@ -0,0 +1,13 @@
1
+ <%- assert_locals method -%>
2
+ <%- error_handler = render(partial: "service/client/method/def/upload_error_handler", locals: { method: method }).strip -%>
3
+ ::Gapic::ResumableUpload.new(
4
+ client_stub_proc: -> { <%= method.service.resumable_upload_stub_ivar %>.client_stub },
5
+ initial_request_proc: lambda {
6
+ <%= method.service.resumable_upload_stub_name_full %>.<%= method.rest.transcoding_helper_name %> request
7
+ },
8
+ initial_headers: options.metadata,
9
+ start_retry_policy: ::Gapic::Rest::ResumableUpload.start_retry_policy_for(options),
10
+ response_type: <%= method.return_type %>,
11
+ method_name: "<%= method.name %>",
12
+ error_handler: <%= error_handler %>
13
+ )
@@ -0,0 +1,2 @@
1
+ <%- assert_locals method -%>
2
+ nil
@@ -1,4 +1,22 @@
1
1
  <%- assert_locals method -%>
2
+ <%- if method.resumable_upload? -%>
3
+ # @overload <%= method.name %>(request = {}, options = nil)
4
+ # Pass arguments to `<%= method.name %>` via a request object, either of type
5
+ # {<%= method.request_type %>} or an equivalent Hash.
6
+ #
7
+ # @param request [<%= method.request_type %>, ::Hash]
8
+ # A request object representing the call parameters. Optional: it is ignored when the returned
9
+ # handle is resumed rather than started, because a resumed upload targets a session the server
10
+ # has already created.
11
+ # @param options [::Gapic::CallOptions, ::Hash]
12
+ # Overrides for the initiation request only. The `timeout`, `retry_policy` and `metadata` set
13
+ # here apply to the single request that creates the upload session, not to the upload as a
14
+ # whole: an upload still transferring bytes an hour later has long outlived this `timeout`.
15
+ # To bound the whole upload, pass `upload_timeout:` to {::Gapic::ResumableUpload#start} or
16
+ # {::Gapic::ResumableUpload#resume}. Chunk transfers are retried by the upload protocol itself,
17
+ # with the defaults documented on {::Gapic::ResumableUpload}; no call option reaches them.
18
+ # Optional.
19
+ <%- else -%>
2
20
  # @overload <%= method.name %>(request, options = nil)
3
21
  # Pass arguments to `<%= method.name %>` via a request object, either of type
4
22
  # {<%= method.request_type %>} or an equivalent Hash.
@@ -8,6 +26,7 @@
8
26
  # parameters, or to keep all the default parameter values, pass an empty Hash.
9
27
  # @param options [::Gapic::CallOptions, ::Hash]
10
28
  # Overrides the default settings for this call, e.g, timeout, retries, etc. Optional.
29
+ <%- end -%>
11
30
  <%-if method.arguments.any?-%>
12
31
  #
13
32
  <%- arg_list = method.arguments.map { |arg| "#{arg.name}: nil"}.join ", " -%>
@@ -1,6 +1,14 @@
1
1
  <%- assert_locals method -%>
2
+ <%- if method.resumable_upload? -%>
3
+ # @return [::Gapic::ResumableUpload]
4
+ # A reusable upload handle. No request is sent and no byte is read from a stream until
5
+ # {::Gapic::ResumableUpload#start} or {::Gapic::ResumableUpload#resume} is called on it.
6
+ # Upload failures, including a failed initiation request, are raised by those methods,
7
+ # not by this one.
8
+ <%- else -%>
2
9
  # @yield [response, operation] Access the result along with the RPC operation
3
10
  # @yieldparam response [<%= method.doc_response_type %>]
4
11
  # @yieldparam operation [::GRPC::ActiveCall::Operation]
5
12
  #
6
13
  # @return [<%= method.doc_response_type %>]
14
+ <%- end -%>
@@ -21,6 +21,14 @@ require "securerandom"
21
21
  <%= indent service.doc_description(transport: :rest), "# " %>
22
22
  #
23
23
  <%- end -%>
24
+ <%- if service.resumable_upload? -%>
25
+ <%- upload_names = service.resumable_upload_methods.map { |upload_method| "`#{upload_method.name}`" }.join ", " -%>
26
+ <%- upload_many = service.resumable_upload_methods.length > 1 -%>
27
+ # <%= upload_names %> <%= upload_many ? "perform resumable uploads: each returns" : "performs a resumable upload: it returns" %> a {::Gapic::ResumableUpload} handle
28
+ # instead of a response, and the per-call `timeout` and retry policy cover only the request that
29
+ # creates the upload session, not the upload itself.
30
+ #
31
+ <%- end -%>
24
32
  class <%= service.rest.client_name %>
25
33
  # @private
26
34
  API_VERSION = "<%= service.api_version %>".freeze
@@ -141,6 +149,16 @@ class <%= service.rest.client_name %>
141
149
  <%- end -%>
142
150
  end
143
151
 
152
+ <%- end -%>
153
+ <%- if service.resumable_upload? -%>
154
+ <%= service.resumable_upload_stub_ivar %> = <%= service.resumable_upload_stub_name_full %>.new(
155
+ endpoint: @config.endpoint,
156
+ endpoint_template: DEFAULT_ENDPOINT_TEMPLATE,
157
+ universe_domain: @config.universe_domain,
158
+ credentials: credentials,
159
+ logger: @config.logger
160
+ )
161
+
144
162
  <%- end -%>
145
163
  @<%= service.stub_name %> = <%= service.rest.service_stub_name_full %>.new(
146
164
  endpoint: @config.endpoint,
@@ -162,6 +162,14 @@ class Configuration
162
162
  <%- method_service.rest.methods.each do |method| -%>
163
163
  ##
164
164
  # RPC-specific configuration for `<%= method.name %>`
165
+ <%- if method.resumable_upload? -%>
166
+ #
167
+ # `<%= method.name %>` performs a resumable upload, so the `timeout` and `retry_policy`
168
+ # configured here cover the request that creates the upload session only, not the upload
169
+ # itself. The whole-upload budget is the `upload_timeout:` argument of
170
+ # {::Gapic::ResumableUpload#start} and {::Gapic::ResumableUpload#resume}.
171
+ #
172
+ <%- end -%>
165
173
  # @return [::Gapic::Config::Method]
166
174
  #
167
175
  attr_reader :<%= method.name %>
@@ -7,10 +7,12 @@
7
7
  <%= render partial: "service/rest/client/method/docs/request", locals: { method: method } -%>
8
8
  <%= render partial: "service/rest/client/method/docs/result", locals: { method: method } -%>
9
9
  #
10
+ <%- unless method.resumable_upload? -%>
10
11
  <%= render partial: "service/rest/client/method/docs/error", locals: { method: method } -%>
11
12
  #
13
+ <%- end -%>
12
14
  <%= render partial: "service/rest/client/method/docs/snippets", locals: { method: method } -%>
13
- def <%= method.name %> request, options = nil
15
+ def <%= method.name %> request<%= method.resumable_upload? ? " = {}" : "" %>, options = nil
14
16
  <%= indent render(partial: "service/client/method/def/request", locals: { method: method }), 2 %>
15
17
 
16
18
  <%= indent render(partial: "service/rest/client/method/def/options_defaults", locals: { method: method }), 2 %>
@@ -20,5 +22,7 @@ def <%= method.name %> request, options = nil
20
22
  <%- end -%>
21
23
 
22
24
  <%= indent render(partial: "service/rest/client/method/def/response", locals: { method: method }), 2 %>
25
+ <%- unless method.resumable_upload? -%>
23
26
  <%= render partial: "service/rest/client/method/def/rescue", locals: { method: method } -%>
27
+ <%- end -%>
24
28
  end
@@ -1,5 +1,7 @@
1
1
  <%- assert_locals method -%>
2
- <%- if method.rest.paged? -%>
2
+ <%- if method.resumable_upload? -%>
3
+ <%= render partial: "service/rest/client/method/def/response_resumable_upload", locals: { method: method } -%>
4
+ <%- elsif method.rest.paged? -%>
3
5
  <%= render partial: "service/rest/client/method/def/response_paged", locals: { method: method } -%>
4
6
  <%- elsif method.rest.nonstandard_lro? -%>
5
7
  <%= render partial: "service/rest/client/method/def/response_nonstandard_lro", locals: { method: method } -%>
@@ -0,0 +1,13 @@
1
+ <%- assert_locals method -%>
2
+ <%- error_handler = render(partial: "service/rest/client/method/def/upload_error_handler", locals: { method: method }).strip -%>
3
+ ::Gapic::ResumableUpload.new(
4
+ client_stub_proc: -> { <%= method.service.resumable_upload_stub_ivar %>.client_stub },
5
+ initial_request_proc: lambda {
6
+ <%= method.service.resumable_upload_stub_name_full %>.<%= method.rest.transcoding_helper_name %> request
7
+ },
8
+ initial_headers: options.metadata,
9
+ start_retry_policy: ::Gapic::Rest::ResumableUpload.start_retry_policy_for(options),
10
+ response_type: <%= method.return_type %>,
11
+ method_name: "<%= method.name %>",
12
+ error_handler: <%= error_handler %>
13
+ )
@@ -0,0 +1,2 @@
1
+ <%- assert_locals method -%>
2
+ nil
@@ -1,4 +1,22 @@
1
1
  <%- assert_locals method -%>
2
+ <%- if method.resumable_upload? -%>
3
+ # @overload <%= method.name %>(request = {}, options = nil)
4
+ # Pass arguments to `<%= method.name %>` via a request object, either of type
5
+ # {<%= method.request_type %>} or an equivalent Hash.
6
+ #
7
+ # @param request [<%= method.request_type %>, ::Hash]
8
+ # A request object representing the call parameters. Optional: it is ignored when the returned
9
+ # handle is resumed rather than started, because a resumed upload targets a session the server
10
+ # has already created.
11
+ # @param options [::Gapic::CallOptions, ::Hash]
12
+ # Overrides for the initiation request only. The `timeout`, `retry_policy` and `metadata` set
13
+ # here apply to the single request that creates the upload session, not to the upload as a
14
+ # whole: an upload still transferring bytes an hour later has long outlived this `timeout`.
15
+ # To bound the whole upload, pass `upload_timeout:` to {::Gapic::ResumableUpload#start} or
16
+ # {::Gapic::ResumableUpload#resume}. Chunk transfers are retried by the upload protocol itself,
17
+ # with the defaults documented on {::Gapic::ResumableUpload}; no call option reaches them.
18
+ # Optional.
19
+ <%- else -%>
2
20
  # @overload <%= method.name %>(request, options = nil)
3
21
  # Pass arguments to `<%= method.name %>` via a request object, either of type
4
22
  # {<%= method.request_type %>} or an equivalent Hash.
@@ -8,6 +26,7 @@
8
26
  # parameters, or to keep all the default parameter values, pass an empty Hash.
9
27
  # @param options [::Gapic::CallOptions, ::Hash]
10
28
  # Overrides the default settings for this call, e.g, timeout, retries etc. Optional.
29
+ <%- end -%>
11
30
  <%-if method.arguments.any?-%>
12
31
  #
13
32
  <%- arg_list = method.arguments.map { |arg| "#{arg.name}: nil"}.join ", " -%>
@@ -1,5 +1,11 @@
1
1
  <%- assert_locals method -%>
2
- <%- if method.server_streaming? -%>
2
+ <%- if method.resumable_upload? -%>
3
+ # @return [::Gapic::ResumableUpload]
4
+ # A reusable upload handle. No request is sent and no byte is read from a stream until
5
+ # {::Gapic::ResumableUpload#start} or {::Gapic::ResumableUpload#resume} is called on it.
6
+ # Upload failures, including a failed initiation request, are raised by those methods,
7
+ # not by this one.
8
+ <%- elsif method.server_streaming? -%>
3
9
  # @return [::Enumerable<<%= method.rest.doc_response_type %>>]
4
10
  <%- else -%>
5
11
  # @yield [result, operation] Access the result along with the TransportOperation object
@@ -52,11 +52,11 @@ class <%= service.rest.service_stub_name %>
52
52
  stub ? @client_stub.stub_logger : @client_stub.logger
53
53
  end
54
54
 
55
- <%- service.rest.methods.each do |method| -%>
55
+ <%- service.rest.service_stub_methods.each do |method| -%>
56
56
  <%= indent_tail render(partial: "service/rest/service_stub/method/def", locals: { method: method, service_stub_name: service.rest.service_stub_name }), 2 %>
57
57
 
58
58
  <%- end %>
59
- <%- service.rest.methods.each do |method| -%>
59
+ <%- service.rest.service_stub_methods.each do |method| -%>
60
60
  <%= indent_tail render(partial: "service/rest/service_stub/grpc_transcoding_method/def", locals: { method: method }), 2 %>
61
61
 
62
62
  <%- end %>
@@ -0,0 +1,15 @@
1
+ <%- assert_locals method -%>
2
+ <%- method.http_bindings.each do |http_binding| -%>
3
+ .with_bindings(
4
+ uri_method: :<%= http_binding.verb %>,
5
+ uri_template: "<%= http_binding.uri_for_transcoding %>",
6
+ <%- if http_binding.body? -%>
7
+ body: "<%= http_binding.body %>",
8
+ <%- end -%>
9
+ matches: [
10
+ <%- http_binding.routing_params_transcoder_matches_strings.each do |match_str| -%>
11
+ <%= match_str %>
12
+ <%- end -%>
13
+ ]
14
+ )
15
+ <%- end -%>
@@ -19,19 +19,6 @@ def self.<%= method.rest.transcoding_helper_name %> request_pb<%= boverr_str %>
19
19
  <%- end %>
20
20
  <%- assignment = method.service.rest.is_main_mixin_service? ? "||=" : "=" -%>
21
21
  transcoder <%= assignment %> Gapic::Rest::GrpcTranscoder.new
22
- <%- method.http_bindings.each do |http_binding| -%>
23
- .with_bindings(
24
- uri_method: :<%= http_binding.verb %>,
25
- uri_template: "<%= http_binding.uri_for_transcoding %>",
26
- <%- if http_binding.body? -%>
27
- body: "<%= http_binding.body %>",
28
- <%- end -%>
29
- matches: [
30
- <%- http_binding.routing_params_transcoder_matches_strings.each do |match_str| -%>
31
- <%= match_str %>
32
- <%- end -%>
33
- ]
34
- )
35
- <%- end %>
22
+ <%= indent render(partial: "service/rest/service_stub/grpc_transcoding_method/bindings", locals: { method: method }), 44 %>
36
23
  transcoder.transcode request_pb
37
24
  end
@@ -9,7 +9,7 @@ require "<%= service.rest.service_require %>"
9
9
  class <%= service.rest.client_name_full %>Test < Minitest::Test
10
10
  <%= indent render(partial: "service/rest/test/method/setup"), 2 %>
11
11
 
12
- <% service.rest.methods.each do |method| %>
12
+ <% service.rest.methods.reject(&:resumable_upload?).each do |method| %>
13
13
  <%= indent render(partial: "service/rest/test/method/#{method.kind}",
14
14
  locals: { method: method }), 2 %>
15
15
 
@@ -0,0 +1,64 @@
1
+ <%- assert_locals service -%>
2
+ ##
3
+ # Resumable upload stub for the <%= service.name %> service.
4
+ #
5
+ # Owns the REST client stub the uploads are performed through, the transcoders that build their
6
+ # initiation requests, and the credentials error that a client unable to perform REST calls has to
7
+ # raise when an upload is attempted.
8
+ #
9
+ # @private
10
+ #
11
+ class <%= service.resumable_upload_stub_name %>
12
+ <%- service.resumable_upload_methods.each do |method| -%>
13
+ # @private
14
+ <%= method.upload_url_prefix_const_name %> = "<%= method.upload_url_prefix %>"
15
+
16
+ <%- end -%>
17
+ # @private
18
+ def initialize endpoint:, endpoint_template:, universe_domain:, credentials:, logger:
19
+ # These require statements are intentionally placed here to initialize
20
+ # the REST modules only when it's required.
21
+ require "gapic/rest"
22
+
23
+ # Uploads travel over REST, and credentials cannot be recovered from a gRPC channel. Rather than
24
+ # raise while a client is being constructed, which would break every other method on it, the
25
+ # error is stored and raised when an upload is actually attempted.
26
+ if defined?(::GRPC::Core::Channel) &&
27
+ (credentials.is_a?(::GRPC::Core::Channel) || credentials.is_a?(::GRPC::Core::ChannelCredentials))
28
+ @credentials_error = ::ArgumentError.new(
29
+ "Resumable uploads are performed over REST and cannot use a gRPC channel as credentials, " \
30
+ "because credentials cannot be recovered from a channel. Construct the client with Google " \
31
+ "OAuth credentials (a keyfile path, a Hash, or a Google::Auth::Credentials instance) to use " \
32
+ "resumable upload methods."
33
+ )
34
+ return
35
+ end
36
+
37
+ @client_stub = ::Gapic::Rest::ClientStub.new endpoint: endpoint,
38
+ endpoint_template: endpoint_template,
39
+ universe_domain: universe_domain,
40
+ credentials: credentials,
41
+ numeric_enums: false,
42
+ service_name: self.class,
43
+ raise_faraday_errors: false,
44
+ logger: logger
45
+ end
46
+
47
+ ##
48
+ # @private
49
+ #
50
+ # The REST client stub the uploads are performed through.
51
+ #
52
+ # @return [::Gapic::Rest::ClientStub]
53
+ #
54
+ # @raise [::ArgumentError] if this client cannot perform REST calls.
55
+ #
56
+ def client_stub
57
+ raise @credentials_error if @credentials_error
58
+ @client_stub
59
+ end
60
+ <%- service.resumable_upload_methods.each do |method| -%>
61
+
62
+ <%= indent_tail render(partial: "service/resumable_upload_stub/transcoding_method", locals: { method: method, service: service }), 2 %>
63
+ <%- end -%>
64
+ end
@@ -0,0 +1,22 @@
1
+ <%- assert_locals method, service -%>
2
+ ##
3
+ # @private
4
+ #
5
+ # GRPC transcoding helper method for the <%= method.name %> resumable upload initiation request.
6
+ #
7
+ # The upload itself is not transcoded: only the request that creates the upload session is, and the
8
+ # verb is discarded because initiation is always a POST. Query string parameters are folded into the
9
+ # URL, since the upload sends the initiation request with no separate parameters.
10
+ #
11
+ # @param request_pb [<%= method.request_type %>]
12
+ # A request object representing the call parameters. Required.
13
+ # @return [Array(String, [String, nil])]
14
+ # Uri, Body
15
+ def self.<%= method.rest.transcoding_helper_name %> request_pb
16
+ transcoder = ::Gapic::Rest::GrpcTranscoder.new
17
+ <%= indent render(partial: "service/rest/service_stub/grpc_transcoding_method/bindings", locals: { method: method }), 46 %>
18
+ _verb, uri, query_string_params, body = transcoder.transcode request_pb
19
+ uri = "/#{<%= method.upload_url_prefix_const_name %>}#{uri}"
20
+ uri = "#{uri}?#{query_string_params.join '&'}" if query_string_params.any?
21
+ [uri, body]
22
+ end
@@ -0,0 +1,6 @@
1
+ <%- assert_locals service -%>
2
+ <%= render partial: "service/resumable_upload_stub/resumable_upload_stub",
3
+ layout: "layouts/ruby",
4
+ locals: { service: service,
5
+ namespace: service.service_name_full }
6
+ %>
@@ -10,7 +10,7 @@ require "<%= service.service_require %>"
10
10
  class <%= service.client_name_full %>Test < Minitest::Test
11
11
  <%= indent render(partial: "service/test/method/setup"), 2 %>
12
12
 
13
- <% service.methods.each do |method| %>
13
+ <% service.methods.reject(&:resumable_upload?).each do |method| %>
14
14
  <%= indent render(partial: "service/test/method/#{method.kind}",
15
15
  locals: { method: method }), 2 %>
16
16
 
@@ -0,0 +1,132 @@
1
+ <%- assert_locals service -%>
2
+ <%= render partial: "shared/header" %>
3
+ require "helper"
4
+
5
+ require "gapic/rest"
6
+ <%- if service.generate_grpc_clients? -%>
7
+ require "gapic/grpc/service_stub"
8
+ <%- end -%>
9
+
10
+ require "<%= service.proto_service_require %>"
11
+ <%- if service.generate_grpc_clients? -%>
12
+ require "<%= service.service_require %>"
13
+ <%- end -%>
14
+ <%- if service.generate_rest_clients? -%>
15
+ require "<%= service.rest.service_require %>"
16
+ <%- end -%>
17
+
18
+ class <%= service.service_name_full %>::ResumableUploadTest < Minitest::Test
19
+ ##
20
+ # Stands in for the transport stub a client builds in its constructor. An upload method sends
21
+ # nothing, so this only has to satisfy the constructor.
22
+ #
23
+ class ClientStub
24
+ def endpoint
25
+ "endpoint.example.com"
26
+ end
27
+
28
+ def universe_domain
29
+ "example.com"
30
+ end
31
+
32
+ def stub_logger
33
+ nil
34
+ end
35
+
36
+ def logger
37
+ nil
38
+ end
39
+ end
40
+ <%- service.resumable_upload_methods.each do |method| -%>
41
+ <%- fields = method.fields_with_first_oneof -%>
42
+ <%- prefix_const = "#{service.resumable_upload_stub_name_full}::#{method.upload_url_prefix_const_name}" -%>
43
+
44
+ def test_transcode_<%= method.name %>_request
45
+ request = <%= method.request_type %>.new
46
+
47
+ # The transcoder is stubbed so the test pins the upload-specific post-processing (prefix,
48
+ # query-string folding, [uri, body] shape) independently of the method's path template.
49
+ transcoder = Gapic::Rest::GrpcTranscoder.new
50
+ transcoder.stub :transcode, [:post, "/transcoded/path", ["foo=bar", "baz=qux"], "{\"body\":true}"] do
51
+ Gapic::Rest::GrpcTranscoder.stub :new, transcoder do
52
+ uri, body = <%= service.resumable_upload_stub_name_full %>.<%= method.rest.transcoding_helper_name %> request
53
+
54
+ assert_equal "/#{<%= prefix_const %>}/transcoded/path?foo=bar&baz=qux", uri
55
+ assert_equal "{\"body\":true}", body
56
+ end
57
+ end
58
+ end
59
+ <%- if service.generate_grpc_clients? -%>
60
+
61
+ def test_<%= method.name %>
62
+ <%- fields.each do |field| -%>
63
+ <%= field.value_name %> = <%= field.default_value %>
64
+ <%- end -%>
65
+
66
+ client = nil
67
+ Gapic::ServiceStub.stub :new, ClientStub.new do
68
+ client = <%= service.client_name_full %>.new do |config|
69
+ config.credentials = :this_channel_is_insecure
70
+ end
71
+ end
72
+
73
+ upload = client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>)
74
+
75
+ # The call builds a handle and sends nothing. The upload only begins on #start or #resume.
76
+ assert_kind_of ::Gapic::ResumableUpload, upload
77
+ assert_nil upload.resume_handle
78
+ refute upload.resumable?
79
+ refute upload.running?
80
+ end
81
+
82
+ def test_<%= method.name %>_channel_credentials
83
+ <%- fields.each do |field| -%>
84
+ <%= field.value_name %> = <%= field.default_value %>
85
+ <%- end -%>
86
+ grpc_channel = GRPC::Core::Channel.new "localhost:8888", nil, :this_channel_is_insecure
87
+
88
+ client = nil
89
+ Gapic::ServiceStub.stub :new, ClientStub.new do
90
+ client = <%= service.client_name_full %>.new do |config|
91
+ config.credentials = grpc_channel
92
+ end
93
+ end
94
+
95
+ upload = client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>)
96
+
97
+ assert_kind_of ::Gapic::ResumableUpload, upload
98
+
99
+ # Uploads travel over REST and cannot use a channel as credentials. The error surfaces here,
100
+ # rather than at construction, and before the stream is touched.
101
+ stream = StringIO.new "resumable upload test payload"
102
+ assert_raises ::ArgumentError do
103
+ upload.start stream: stream, content_type: "application/octet-stream"
104
+ end
105
+ assert_equal 0, stream.pos
106
+ end
107
+ <%- end -%>
108
+ <%- if service.generate_rest_clients? -%>
109
+
110
+ def test_<%= method.name %>_rest
111
+ <%- fields.each do |field| -%>
112
+ <%= field.value_name %> = <%= field.default_value %>
113
+ <%- end -%>
114
+
115
+ client = nil
116
+ Gapic::Rest::ClientStub.stub :new, ClientStub.new do
117
+ client = <%= service.rest.client_name_full %>.new do |config|
118
+ config.credentials = :dummy_value
119
+ end
120
+ end
121
+
122
+ upload = client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>)
123
+
124
+ # The call builds a handle and sends nothing. The upload only begins on #start or #resume.
125
+ assert_kind_of ::Gapic::ResumableUpload, upload
126
+ assert_nil upload.resume_handle
127
+ refute upload.resumable?
128
+ refute upload.running?
129
+ end
130
+ <%- end -%>
131
+ <%- end -%>
132
+ end