gapic-generator 0.10.1 → 0.45.1

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 (257) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +333 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +71 -37
  5. data/bin/protoc-gen-ruby_gapic +2 -2
  6. data/lib/gapic/file_formatter.rb +23 -19
  7. data/lib/gapic/formatting_utils.rb +22 -9
  8. data/lib/gapic/gem_builder.rb +15 -17
  9. data/lib/gapic/generator/version.rb +1 -1
  10. data/lib/gapic/generators/base_generator.rb +6 -4
  11. data/lib/gapic/generators/default_generator.rb +70 -32
  12. data/lib/gapic/generators/default_generator_parameters.rb +11 -3
  13. data/lib/gapic/grpc_service_config/{service_config.rb → config.rb} +2 -2
  14. data/lib/gapic/grpc_service_config/parser.rb +10 -10
  15. data/lib/gapic/model/api_metadata.rb +173 -0
  16. data/lib/gapic/model/method/http_annotation.rb +221 -0
  17. data/lib/gapic/model/method/lro.rb +163 -0
  18. data/lib/gapic/model/method/routing.rb +248 -0
  19. data/lib/gapic/model/mixins.rb +247 -0
  20. data/lib/gapic/model/model_error.rb +26 -0
  21. data/lib/gapic/model/service/nonstandard_lro_provider.rb +292 -0
  22. data/lib/gapic/model.rb +22 -0
  23. data/lib/gapic/package_snippets.rb +159 -0
  24. data/lib/gapic/path_pattern/parser.rb +11 -2
  25. data/lib/gapic/path_pattern/pattern.rb +64 -1
  26. data/lib/gapic/path_pattern/segment.rb +108 -13
  27. data/lib/gapic/presenters/enum_presenter.rb +14 -0
  28. data/lib/gapic/presenters/enum_value_presenter.rb +4 -1
  29. data/lib/gapic/presenters/field_presenter.rb +78 -21
  30. data/lib/gapic/presenters/gem_presenter.rb +140 -34
  31. data/lib/gapic/presenters/{service_config_presenter.rb → grpc_service_config_presenter.rb} +1 -1
  32. data/lib/gapic/presenters/message_presenter.rb +15 -0
  33. data/lib/gapic/presenters/method/http_binding_presenter.rb +128 -0
  34. data/lib/gapic/presenters/method/rest_pagination_info.rb +25 -16
  35. data/lib/gapic/presenters/method_presenter.rb +149 -35
  36. data/lib/gapic/presenters/method_rest_presenter.rb +79 -168
  37. data/lib/gapic/presenters/package_presenter.rb +63 -18
  38. data/lib/gapic/presenters/resource_presenter.rb +9 -3
  39. data/lib/gapic/presenters/service/lro_client_presenter.rb +90 -0
  40. data/lib/gapic/presenters/service/mixin_client_presenter.rb +89 -0
  41. data/lib/gapic/presenters/service/sub_client_presenter.rb +84 -0
  42. data/lib/gapic/presenters/service_presenter.rb +361 -27
  43. data/lib/gapic/presenters/service_rest_presenter.rb +247 -13
  44. data/lib/gapic/presenters/snippet/client_call_presenter.rb +82 -0
  45. data/lib/gapic/presenters/snippet/client_initialization_presenter.rb +87 -0
  46. data/lib/gapic/presenters/snippet/declaration_presenter.rb +91 -0
  47. data/lib/gapic/presenters/snippet/expression_presenter.rb +135 -0
  48. data/lib/gapic/presenters/snippet/iteration_presenter.rb +118 -0
  49. data/lib/gapic/presenters/snippet/parameter_presenter.rb +67 -0
  50. data/lib/gapic/presenters/snippet/request_initialization_presenters.rb +202 -0
  51. data/lib/gapic/presenters/snippet/response_handling_presenters.rb +329 -0
  52. data/lib/gapic/presenters/snippet/statement_presenter.rb +134 -0
  53. data/lib/gapic/presenters/snippet/type_presenter.rb +98 -0
  54. data/lib/gapic/presenters/snippet_presenter.rb +199 -9
  55. data/lib/gapic/presenters.rb +5 -1
  56. data/lib/gapic/runner.rb +1 -1
  57. data/lib/gapic/schema/api.rb +105 -5
  58. data/lib/gapic/schema/loader.rb +69 -21
  59. data/lib/gapic/schema/parameter_schema.rb +8 -8
  60. data/lib/gapic/schema/proto_tools.rb +193 -0
  61. data/lib/gapic/schema/request_param_parser.rb +5 -7
  62. data/lib/gapic/schema/service_config_parser.rb +152 -0
  63. data/lib/gapic/schema/wrappers.rb +309 -25
  64. data/lib/gapic/uri_template/parser.rb +15 -7
  65. data/lib/google/cloud/tools/snippetgen/configlanguage/v1/snippet_config_language_pb.rb +104 -0
  66. data/lib/google/cloud/tools/snippetgen/snippetindex/v1/snippet_index_pb.rb +58 -0
  67. data/lib/google/protobuf/compiler/plugin_pb.rb +47 -0
  68. data/templates/default/binding_override.text.erb +6 -0
  69. data/templates/default/gem/gemfile.text.erb +12 -0
  70. data/templates/default/gem/{gemspec.erb → gemspec.text.erb} +3 -11
  71. data/templates/default/gem/{readme.erb → readme.text.erb} +10 -6
  72. data/templates/default/gem/{rubocop.erb → rubocop.text.erb} +3 -0
  73. data/templates/default/gem/{test_helper.erb → test_helper.text.erb} +4 -2
  74. data/templates/default/gem/toys.text.erb +12 -0
  75. data/templates/default/gem/{yardopts.erb → yardopts.text.erb} +1 -1
  76. data/templates/default/helpers/default_helper.rb +33 -1
  77. data/templates/default/lib/_binding_override.text.erb +49 -0
  78. data/templates/default/lib/{_package.erb → _package.text.erb} +7 -6
  79. data/templates/default/lib/_package_rest.text.erb +24 -0
  80. data/templates/default/lib/{_service.erb → _service.text.erb} +14 -20
  81. data/templates/default/lib/package/_self_configure.text.erb +16 -0
  82. data/templates/default/lib/package/_self_configure_defaults.text.erb +13 -0
  83. data/templates/default/lib/package/self_configure/_binding_default.text.erb +15 -0
  84. data/templates/default/lib/rest/_rest.text.erb +46 -0
  85. data/templates/default/package_rest.text.erb +6 -0
  86. data/templates/default/proto_docs/_deprecated.text.erb +9 -0
  87. data/templates/default/proto_docs/{_enum.erb → _enum.text.erb} +1 -0
  88. data/templates/default/proto_docs/{_message.erb → _message.text.erb} +2 -0
  89. data/templates/default/service/client/{_client.erb → _client.text.erb} +77 -17
  90. data/templates/default/service/client/{_config.erb → _config.text.erb} +39 -8
  91. data/templates/default/service/client/_nonstandard_lro.text.erb +57 -0
  92. data/templates/default/service/client/{_operations.erb → _operations.text.erb} +24 -3
  93. data/templates/default/service/client/{_self_configure_defaults.erb → _self_configure_defaults.text.erb} +2 -2
  94. data/templates/default/service/client/method/{_def.erb → _def.text.erb} +2 -2
  95. data/templates/default/service/client/method/def/{_options_defaults.erb → _options_defaults.text.erb} +3 -9
  96. data/templates/default/service/client/method/def/_request_normal.text.erb +18 -0
  97. data/templates/default/service/client/method/def/_request_streaming.text.erb +23 -0
  98. data/templates/default/service/client/method/def/_response.text.erb +10 -0
  99. data/templates/default/service/client/method/def/_response_nonstandard_lro.text.erb +23 -0
  100. data/templates/default/service/client/method/def/_response_normal.text.erb +4 -0
  101. data/templates/default/service/client/method/def/{_response_normal.erb → _response_normal_lro.text.erb} +1 -3
  102. data/templates/default/service/client/method/def/{_response_paged.erb → _response_paged.text.erb} +1 -1
  103. data/templates/default/service/client/method/def/_routing_params.text.erb +36 -0
  104. data/templates/default/service/client/method/docs/{_request_normal.erb → _request_normal.text.erb} +1 -1
  105. data/templates/default/service/client/method/docs/_snippets.text.erb +6 -0
  106. data/templates/default/service/client/resource/_def.text.erb +7 -0
  107. data/templates/default/service/nonstandard_lro.text.erb +6 -0
  108. data/templates/default/service/rest/client/_client.text.erb +202 -0
  109. data/templates/default/service/rest/client/_config.text.erb +178 -0
  110. data/templates/default/service/rest/client/_operations.text.erb +124 -0
  111. data/templates/default/service/rest/client/method/{_def.erb → _def.text.erb} +7 -1
  112. data/templates/default/service/rest/client/method/def/{_options_defaults.erb → _options_defaults.text.erb} +8 -3
  113. data/templates/default/service/rest/client/method/def/_response.text.erb +12 -0
  114. data/templates/default/service/rest/client/method/def/_response_nonstandard_lro.text.erb +24 -0
  115. data/templates/default/service/rest/client/method/def/_response_normal.text.erb +5 -0
  116. data/templates/default/service/rest/client/method/def/_response_normal_lro.text.erb +7 -0
  117. data/templates/default/service/rest/client/method/def/_response_paged.text.erb +7 -0
  118. data/templates/default/service/rest/client/method/def/_response_server_streaming.text.erb +11 -0
  119. data/templates/default/service/rest/client/method/docs/{_request.erb → _request.text.erb} +1 -3
  120. data/templates/default/service/rest/client/method/docs/_result.text.erb +10 -0
  121. data/templates/default/service/rest/client/method/docs/_snippets.text.erb +6 -0
  122. data/templates/default/service/rest/nonstandard_lro.text.erb +6 -0
  123. data/templates/default/service/rest/operations.text.erb +6 -0
  124. data/templates/default/service/rest/service_stub/_service_stub.text.erb +63 -0
  125. data/templates/default/service/rest/service_stub/grpc_transcoding_method/_def.text.erb +37 -0
  126. data/templates/default/service/rest/service_stub/method/_def.text.erb +35 -0
  127. data/templates/default/service/rest/service_stub/method/def/_response.text.erb +37 -0
  128. data/templates/default/service/rest/test/{client.erb → client.text.erb} +3 -3
  129. data/templates/default/service/rest/test/method/_assert_response.text.erb +2 -0
  130. data/templates/default/service/rest/test/method/{_configure.erb → _configure.text.erb} +3 -2
  131. data/templates/default/service/rest/test/method/_normal.text.erb +60 -0
  132. data/templates/default/service/rest/test/method/_server.text.erb +60 -0
  133. data/templates/default/service/rest/test/method/{_setup.erb → _setup.text.erb} +26 -10
  134. data/templates/default/service/test/{_resource.erb → _resource.text.erb} +1 -1
  135. data/templates/default/service/test/{client.erb → client.text.erb} +3 -2
  136. data/templates/default/service/test/client_paths.text.erb +33 -0
  137. data/templates/default/service/test/method/{_assert_response.erb → _assert_response.text.erb} +3 -0
  138. data/templates/default/service/test/method/{_bidi.erb → _bidi.text.erb} +1 -1
  139. data/templates/default/service/test/method/{_client.erb → _client.text.erb} +1 -1
  140. data/templates/default/service/test/method/{_configure.erb → _configure.text.erb} +2 -1
  141. data/templates/default/service/test/method/{_normal.erb → _normal.text.erb} +1 -1
  142. data/templates/default/service/test/method/{_server.erb → _server.text.erb} +1 -1
  143. data/templates/default/service/test/method/{_setup.erb → _setup.text.erb} +19 -2
  144. data/templates/default/snippets/{gemfile.erb → gemfile.text.erb} +2 -2
  145. data/templates/default/snippets/snippet/_body.text.erb +24 -0
  146. data/templates/default/snippets/snippet/_inline.text.erb +11 -0
  147. data/templates/default/snippets/snippet/_standalone.text.erb +25 -0
  148. data/templates/default/snippets/{standalone.erb → standalone.text.erb} +1 -1
  149. metadata +209 -230
  150. data/lib/google/api/annotations.pb.rb +0 -39
  151. data/lib/google/api/client.pb.rb +0 -43
  152. data/lib/google/api/field_behavior.pb.rb +0 -51
  153. data/lib/google/api/http.pb.rb +0 -60
  154. data/lib/google/api/resource.pb.rb +0 -80
  155. data/lib/google/longrunning/operations.pb.rb +0 -115
  156. data/lib/google/protobuf/any.pb.rb +0 -40
  157. data/lib/google/protobuf/compiler/plugin.pb.rb +0 -79
  158. data/lib/google/protobuf/descriptor.pb.rb +0 -360
  159. data/lib/google/protobuf/empty.pb.rb +0 -36
  160. data/lib/google/rpc/status.pb.rb +0 -46
  161. data/templates/default/gem/gemfile.erb +0 -4
  162. data/templates/default/lib/rest/_rest.erb +0 -9
  163. data/templates/default/service/client/method/def/_request_normal.erb +0 -4
  164. data/templates/default/service/client/method/def/_request_streaming.erb +0 -9
  165. data/templates/default/service/client/method/def/_response.erb +0 -6
  166. data/templates/default/service/client/method/docs/_deprecated.erb +0 -5
  167. data/templates/default/service/client/method/docs/_snippets.erb +0 -6
  168. data/templates/default/service/client/resource/_def.erb +0 -6
  169. data/templates/default/service/rest/client/_client.erb +0 -106
  170. data/templates/default/service/rest/client/_config.erb +0 -122
  171. data/templates/default/service/rest/client/method/def/_response.erb +0 -8
  172. data/templates/default/service/rest/client/method/def/_response_lro.erb +0 -7
  173. data/templates/default/service/rest/client/method/def/_response_normal.erb +0 -6
  174. data/templates/default/service/rest/client/method/def/_response_paged.erb +0 -7
  175. data/templates/default/service/rest/client/method/docs/_result.erb +0 -6
  176. data/templates/default/service/rest/service_stub/_service_stub.erb +0 -25
  177. data/templates/default/service/rest/service_stub/grpc_transcoding_method/_def.erb +0 -24
  178. data/templates/default/service/rest/service_stub/method/_def.erb +0 -20
  179. data/templates/default/service/rest/service_stub/method/def/_response.erb +0 -17
  180. data/templates/default/service/rest/test/method/_assert_response.erb +0 -2
  181. data/templates/default/service/rest/test/method/_normal.erb +0 -71
  182. data/templates/default/service/test/client_paths.erb +0 -15
  183. data/templates/default/snippets/snippet/_structure.erb +0 -71
  184. /data/gem_templates/{binary.erb → binary.text.erb} +0 -0
  185. /data/gem_templates/{dockerfile.erb → dockerfile.text.erb} +0 -0
  186. /data/gem_templates/{entrypoint.erb → entrypoint.text.erb} +0 -0
  187. /data/gem_templates/{gapic_sh.erb → gapic_sh.text.erb} +0 -0
  188. /data/gem_templates/{gemfile.erb → gemfile.text.erb} +0 -0
  189. /data/gem_templates/{gemspec.erb → gemspec.text.erb} +0 -0
  190. /data/gem_templates/{generator.erb → generator.text.erb} +0 -0
  191. /data/gem_templates/{gitignore.erb → gitignore.text.erb} +0 -0
  192. /data/gem_templates/{rakefile.erb → rakefile.text.erb} +0 -0
  193. /data/gem_templates/{readme.erb → readme.text.erb} +0 -0
  194. /data/gem_templates/{rubocop.erb → rubocop.text.erb} +0 -0
  195. /data/gem_templates/shared/{_header.erb → _header.text.erb} +0 -0
  196. /data/gem_templates/shared/{_license.erb → _license.text.erb} +0 -0
  197. /data/gem_templates/shared/{_warning.erb → _warning.text.erb} +0 -0
  198. /data/gem_templates/{test_generator.erb → test_generator.text.erb} +0 -0
  199. /data/gem_templates/{test_helper.erb → test_helper.text.erb} +0 -0
  200. /data/gem_templates/{version.erb → version.text.erb} +0 -0
  201. /data/templates/default/gem/{_version.erb → _version.text.erb} +0 -0
  202. /data/templates/default/gem/{changelog.erb → changelog.text.erb} +0 -0
  203. /data/templates/default/gem/{entrypoint.erb → entrypoint.text.erb} +0 -0
  204. /data/templates/default/gem/{gapic_metadata_json.erb → gapic_metadata_json.text.erb} +0 -0
  205. /data/templates/default/gem/{gitignore.erb → gitignore.text.erb} +0 -0
  206. /data/templates/default/gem/{license.erb → license.text.erb} +0 -0
  207. /data/templates/default/gem/{rakefile.erb → rakefile.text.erb} +0 -0
  208. /data/templates/default/gem/{version.erb → version.text.erb} +0 -0
  209. /data/templates/default/layouts/{_ruby.erb → _ruby.text.erb} +0 -0
  210. /data/templates/default/{package.erb → package.text.erb} +0 -0
  211. /data/templates/default/proto_docs/{_proto_file.erb → _proto_file.text.erb} +0 -0
  212. /data/templates/default/proto_docs/{proto_file.erb → proto_file.text.erb} +0 -0
  213. /data/templates/default/proto_docs/{readme.erb → readme.text.erb} +0 -0
  214. /data/templates/default/service/{_helpers.erb → _helpers.text.erb} +0 -0
  215. /data/templates/default/service/client/{_credentials.erb → _credentials.text.erb} +0 -0
  216. /data/templates/default/service/client/{_paths.erb → _paths.text.erb} +0 -0
  217. /data/templates/default/service/client/{_requires.erb → _requires.text.erb} +0 -0
  218. /data/templates/default/service/client/{_resource.erb → _resource.text.erb} +0 -0
  219. /data/templates/default/service/client/{_self_configure.erb → _self_configure.text.erb} +0 -0
  220. /data/templates/default/service/client/method/def/{_request.erb → _request.text.erb} +0 -0
  221. /data/templates/default/service/client/method/def/{_rescue.erb → _rescue.text.erb} +0 -0
  222. /data/templates/default/service/client/method/docs/{_error.erb → _error.text.erb} +0 -0
  223. /data/templates/default/service/client/method/docs/{_request.erb → _request.text.erb} +0 -0
  224. /data/templates/default/service/client/method/docs/{_request_field.erb → _request_field.text.erb} +0 -0
  225. /data/templates/default/service/client/method/docs/{_request_streaming.erb → _request_streaming.text.erb} +0 -0
  226. /data/templates/default/service/client/method/docs/{_response.erb → _response.text.erb} +0 -0
  227. /data/templates/default/service/client/method/docs/{_sample.erb → _sample.text.erb} +0 -0
  228. /data/templates/default/service/client/method/docs/{_sample_response.erb → _sample_response.text.erb} +0 -0
  229. /data/templates/default/service/client/method/docs/{_samples.erb → _samples.text.erb} +0 -0
  230. /data/templates/default/service/client/method/docs/request_field/{_arg.erb → _arg.text.erb} +0 -0
  231. /data/templates/default/service/client/method/docs/request_field/{_hash.erb → _hash.text.erb} +0 -0
  232. /data/templates/default/service/client/method/docs/sample_response/{_comment.erb → _comment.text.erb} +0 -0
  233. /data/templates/default/service/client/method/docs/sample_response/{_define.erb → _define.text.erb} +0 -0
  234. /data/templates/default/service/client/method/docs/sample_response/{_loop.erb → _loop.text.erb} +0 -0
  235. /data/templates/default/service/client/method/docs/sample_response/{_print.erb → _print.text.erb} +0 -0
  236. /data/templates/default/service/client/method/docs/sample_response/{_write_file.erb → _write_file.text.erb} +0 -0
  237. /data/templates/default/service/client/resource/{_doc.erb → _doc.text.erb} +0 -0
  238. /data/templates/default/service/client/resource/{_multi.erb → _multi.text.erb} +0 -0
  239. /data/templates/default/service/client/resource/{_single.erb → _single.text.erb} +0 -0
  240. /data/templates/default/service/{client.erb → client.text.erb} +0 -0
  241. /data/templates/default/service/{credentials.erb → credentials.text.erb} +0 -0
  242. /data/templates/default/service/{operations.erb → operations.text.erb} +0 -0
  243. /data/templates/default/service/{paths.erb → paths.text.erb} +0 -0
  244. /data/templates/default/service/rest/client/method/def/{_rescue.erb → _rescue.text.erb} +0 -0
  245. /data/templates/default/service/rest/client/method/docs/{_error.erb → _error.text.erb} +0 -0
  246. /data/templates/default/service/rest/{client.erb → client.text.erb} +0 -0
  247. /data/templates/default/service/rest/{grpc_transcoding.erb → grpc_transcoding.text.erb} +0 -0
  248. /data/templates/default/service/rest/service_stub/grpc_transcoding_method/def/{_query_string_param.erb → _query_string_param.text.erb} +0 -0
  249. /data/templates/default/service/rest/service_stub/method/def/{_request.erb → _request.text.erb} +0 -0
  250. /data/templates/default/service/rest/{service_stub.erb → service_stub.text.erb} +0 -0
  251. /data/templates/default/service/{rest.erb → rest.text.erb} +0 -0
  252. /data/templates/default/service/test/{client_operations.erb → client_operations.text.erb} +0 -0
  253. /data/templates/default/service/test/{smoke.erb → smoke.text.erb} +0 -0
  254. /data/templates/default/{service.erb → service.text.erb} +0 -0
  255. /data/templates/default/shared/{_header.erb → _header.text.erb} +0 -0
  256. /data/templates/default/shared/{_license.erb → _license.text.erb} +0 -0
  257. /data/templates/default/shared/{_warning.erb → _warning.text.erb} +0 -0
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Gapic
18
+ module Model
19
+ # Aggregated information about the mixin services
20
+ # that should be referenced from their gems in the
21
+ # generated client libraries
22
+ class Mixins
23
+ # LRO might be specified in the mixins but it is not generated
24
+ # as a mixin
25
+ LRO_SERVICE = "google.longrunning.Operations"
26
+
27
+ # Locations and Iam are generated as mixins
28
+ LOCATIONS_SERVICE = "google.cloud.location.Locations"
29
+ IAM_SERVICE = "google.iam.v1.IAMPolicy"
30
+
31
+ # @return [Enumerable<String>] List of services from the Api model
32
+ attr_accessor :api_services
33
+
34
+ ##
35
+ # @param api_services [Enumerable<String>]
36
+ # List of services from the Api model
37
+ # @param service_config [Google::Api::Service]
38
+ # The service config
39
+ # @param gem_name [String]
40
+ # The name of the gem.
41
+ def initialize api_services, service_config, gem_name
42
+ @api_services = api_services
43
+ @service_config = service_config
44
+ @gem_name = gem_name
45
+ end
46
+
47
+ # @return [Boolean] Whether there are any mix-in services
48
+ def mixins?
49
+ mixin_services.any?
50
+ end
51
+
52
+ # @return [Enumerable<Mixin>]
53
+ # List of Mixin objects, providing the information that is needed
54
+ # to add the mixin service references to the generated library
55
+ def mixins
56
+ @mixins ||= mixin_services.map { |service| create_mixin service }
57
+ end
58
+
59
+ # @return [Enumerable<String>] Full proto names of the mix-in services
60
+ def mixin_services
61
+ @mixin_services ||= begin
62
+ candidates = services_in_config & SERVICE_TO_DEPENDENCY.keys
63
+ candidates.reject { |name| SERVICE_TO_DEPENDENCY[name].include? @gem_name }
64
+ end
65
+ end
66
+
67
+ # @return [Hash<String, String>]
68
+ # Aggregated dependencies for the mix-in services
69
+ def dependencies
70
+ @dependencies ||= mixins.reduce({}) { |deps, mixin| deps.merge mixin.dependency }
71
+ end
72
+
73
+ # Model of a single mixin service
74
+ # @!attribute [r] service
75
+ # Full name of the service
76
+ # @return [String]
77
+ # @!attribute [r] dependency
78
+ # Service dependencies, in the
79
+ # `{ gem_name => version pattern }` format
80
+ # @return [Hash<String, String>]
81
+ # @!attribute [r] require_str
82
+ # Path to `require` the client of the service
83
+ # @return [String]
84
+ # @!attribute [r] require_str_rest
85
+ # Path to `require` the REST client of the service
86
+ # @return [String]
87
+ # @!attribute [r] client_class_name
88
+ # Full name of the class of the client of the service
89
+ # @return [String]
90
+ # @!attribute [r] client_class_name_rest
91
+ # Full name of the class of the REST client of the service
92
+ # @return [String]
93
+ # @!attribute [r] client_class_docname
94
+ # Name of the class as it should appear in the documentation
95
+ # @return [String]
96
+ # @!attribute [r] client_class_docname_rest
97
+ # Name of the REST class as it should appear in the documentation
98
+ # @return [String]
99
+ # @!attribute [r] client_var_name
100
+ # Name for the variable for the client of the
101
+ # mixin service to use when generating library's service
102
+ # @return [String]
103
+ class Mixin
104
+ attr_reader :service
105
+ attr_reader :dependency
106
+ attr_reader :require_str
107
+ attr_reader :require_str_rest
108
+ attr_reader :client_class_name
109
+ attr_reader :client_class_name_rest
110
+ attr_reader :client_class_docname
111
+ attr_reader :client_class_docname_rest
112
+ attr_reader :client_var_name
113
+
114
+ # @param service [String]
115
+ # Full name of the service
116
+ # @param dependency [Hash<String, String>]
117
+ # Service dependencies, in the
118
+ # `{ gem_name => version pattern }` format
119
+ # @param require_str [String]
120
+ # Path to require the client of the service
121
+ # @param require_str_rest [String]
122
+ # Path to require the REST client of the service
123
+ # @param client_class_name [String]
124
+ # Full name of the class of the client of the service
125
+ # @param client_class_name_rest [String]
126
+ # Full name of the class of the REST client of the service
127
+ # @param client_var_name [String]
128
+ # Name for the variable for the client of the mixin service
129
+ # to use when generating library's service
130
+ def initialize service, dependency, require_str, require_str_rest, client_class_name, client_class_name_rest,
131
+ client_var_name
132
+ @service = service
133
+ @dependency = dependency
134
+ @require_str = require_str
135
+ @require_str_rest = require_str_rest
136
+ @client_class_name = client_class_name
137
+ @client_class_name_rest = client_class_name_rest
138
+ @client_class_docname = client_class_name # For mixins, the doc name should be the full class name
139
+ @client_class_docname_rest = client_class_name_rest # For mixins, the doc name should be the full class name
140
+ @client_var_name = client_var_name
141
+ end
142
+
143
+ # @return [String] The description to place in the comments to the
144
+ # mixin's attribute in the library services's client class
145
+ def service_description
146
+ "mix-in of the #{client_class_name.split('::')[-2]}"
147
+ end
148
+ end
149
+
150
+ ##
151
+ # Returns true if the given service address is a mixin.
152
+ # This just checks the service against a (hard-coded) set of known mixins.
153
+ # If `gem_name` is provided, services that correspond to that gem_name are not considered mixins.
154
+ #
155
+ # @param service_address [String,Array<String>] The address (either array
156
+ # or dot-delimited) of the service to check.
157
+ # @param gem_name [String] The name of the gem.
158
+ # @return [boolean]
159
+ #
160
+ def self.mixin_service_address? service_address, gem_name: nil
161
+ service_address = service_address.join "." unless service_address.is_a? String
162
+ MIXIN_GEM_NAMES.include?(service_address) && gem_name != MIXIN_GEM_NAMES[service_address]
163
+ end
164
+
165
+ private
166
+
167
+ # @return [Enumerable<String>] Names of all services that are specified
168
+ # in the Service Config. These include mixin services, as well as
169
+ # some, all, or none of the library's own services
170
+ def services_in_config
171
+ return [] unless @service_config&.apis
172
+ @service_config.apis.map(&:name)
173
+ end
174
+
175
+ MIXIN_GEM_NAMES = {
176
+ LOCATIONS_SERVICE => "google-cloud-location",
177
+ IAM_SERVICE => "google-iam-v1",
178
+ LRO_SERVICE => "google-longrunning-operations"
179
+ }.freeze
180
+ private_constant :MIXIN_GEM_NAMES
181
+
182
+ # Since mixins are scope-limited to a couple of services, it is easier to
183
+ # have these in lookup tables than to construct a ServicePresenter
184
+
185
+ SERVICE_TO_DEPENDENCY = {
186
+ LOCATIONS_SERVICE => { "google-cloud-location" => ["~> 1.0"] },
187
+ IAM_SERVICE => { "google-iam-v1" => ["~> 1.3"] }
188
+ }.freeze
189
+ private_constant :SERVICE_TO_DEPENDENCY
190
+
191
+ SERVICE_TO_REQUIRE_STR = {
192
+ LOCATIONS_SERVICE => "google/cloud/location",
193
+ IAM_SERVICE => "google/iam/v1"
194
+ }.freeze
195
+ private_constant :SERVICE_TO_REQUIRE_STR
196
+
197
+ SERVICE_TO_REQUIRE_STR_REST = {
198
+ LOCATIONS_SERVICE => "google/cloud/location/rest",
199
+ IAM_SERVICE => "google/iam/v1/rest"
200
+ }.freeze
201
+ private_constant :SERVICE_TO_REQUIRE_STR_REST
202
+
203
+ SERVICE_TO_CLIENT_CLASS_NAME = {
204
+ LOCATIONS_SERVICE => "Google::Cloud::Location::Locations::Client",
205
+ IAM_SERVICE => "Google::Iam::V1::IAMPolicy::Client"
206
+ }.freeze
207
+ private_constant :SERVICE_TO_CLIENT_CLASS_NAME
208
+
209
+ SERVICE_TO_CLIENT_CLASS_NAME_REST = {
210
+ LOCATIONS_SERVICE => "Google::Cloud::Location::Locations::Rest::Client",
211
+ IAM_SERVICE => "Google::Iam::V1::IAMPolicy::Rest::Client"
212
+ }.freeze
213
+ private_constant :SERVICE_TO_CLIENT_CLASS_NAME_REST
214
+
215
+ SERVICE_TO_CLIENT_ATTR_NAME = {
216
+ LOCATIONS_SERVICE => "location_client",
217
+ IAM_SERVICE => "iam_policy_client"
218
+ }.freeze
219
+ private_constant :SERVICE_TO_CLIENT_ATTR_NAME
220
+
221
+ # @param service [String] full grpc name of the service
222
+ # @raise [ModelError]
223
+ # @return [Mixin]
224
+ def create_mixin service
225
+ unless SERVICE_TO_DEPENDENCY.key?(service) &&
226
+ SERVICE_TO_REQUIRE_STR.key?(service) &&
227
+ SERVICE_TO_REQUIRE_STR_REST.key?(service) &&
228
+ SERVICE_TO_CLIENT_CLASS_NAME.key?(service) &&
229
+ SERVICE_TO_CLIENT_CLASS_NAME_REST.key?(service) &&
230
+ SERVICE_TO_CLIENT_ATTR_NAME.key?(service)
231
+
232
+ error_text = "A mixin service #{service} is specified in service config, but " \
233
+ "the Generator does not know of it."
234
+ raise ModelError, error_text
235
+ end
236
+
237
+ Mixin.new service,
238
+ SERVICE_TO_DEPENDENCY[service],
239
+ SERVICE_TO_REQUIRE_STR[service],
240
+ SERVICE_TO_REQUIRE_STR_REST[service],
241
+ SERVICE_TO_CLIENT_CLASS_NAME[service],
242
+ SERVICE_TO_CLIENT_CLASS_NAME_REST[service],
243
+ SERVICE_TO_CLIENT_ATTR_NAME[service]
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Gapic
18
+ module Model
19
+ ##
20
+ # Represents an error due to inconsistency in the Model
21
+ # that the Generator is attempting to Generate
22
+ #
23
+ class ModelError < StandardError
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,292 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Gapic
18
+ module Model
19
+ ##
20
+ # Service-level models
21
+ #
22
+ module Service
23
+ ##
24
+ # Nonstandard (AIP-151 nonconforming) long-running operation service-level model
25
+ # for the services that are LRO providers (contain polling methods for long-running operations)
26
+ #
27
+ # @!attribute [r] service_full_name
28
+ # @return [String] Full grpc name of this service. E.g. `google.example.LroProvider`.
29
+ #
30
+ # @!attribute [r] polling_method_name
31
+ # @return [String] Name of the method that is used to poll for LROs. E.g. `Poll`
32
+ #
33
+ # @!attribute [r] lro_object_full_name
34
+ # @return [String] Full grpc name of the object that is returned by the polling method.
35
+ # E.g. `google.cloud.compute.v1.Operation`
36
+ #
37
+ # @!attribute [r] operation_status_field
38
+ # @return [String] In the Operation message for this service, the name of the `status` field.
39
+ # The `status` field signals that the operation has finished. It should either contain symbols, and
40
+ # be set to `:DONE` when finished or contain a boolean and be set to `true` when finished.
41
+ #
42
+ # @!attribute [r] operation_name_field
43
+ # @return [String, nil] In the Operation message for this service, the name of the `name` field.
44
+ #
45
+ # @!attribute [r] operation_err_code_field
46
+ # @return [String, nil] In the Operation message for this service, the name of the `error code` field.
47
+ #
48
+ # @!attribute [r] operation_err_msg_field
49
+ # @return [String, nil] In the Operation message for this service, the name of the `error message` field.
50
+ #
51
+ # @!attribute [r] operation_response_fields
52
+ # @return [Hash<String, String>] The map of the fields that need to be copied from the
53
+ # long-running operation object that the polling method returns to the polling request.
54
+ # The format is `name of the operation object field` -> `name of the polling request field` (`from -> to`).
55
+ # E.g. `{"foo" => "bar"}` means that when constructing a polling request,
56
+ # the following assignment should be carried out:
57
+ # `lro_polling_request.bar = operation_object.foo`.
58
+ #
59
+ class NonstandardLroProvider
60
+ attr_reader :service_full_name
61
+ attr_reader :polling_method_name
62
+ attr_reader :lro_object_full_name
63
+ attr_reader :operation_status_field
64
+ attr_reader :operation_name_field
65
+ attr_reader :operation_err_code_field
66
+ attr_reader :operation_err_msg_field
67
+ attr_reader :operation_response_fields
68
+
69
+ ##
70
+ # @return [Boolean] Whether this is a model for a nonstandard LRO provider service
71
+ #
72
+ def nonstandard_lro?
73
+ true
74
+ end
75
+
76
+ ##
77
+ # @param service_full_name [String]
78
+ # Full grpc name of this service. E.g. `google.example.LroProvider`.
79
+ #
80
+ # @param polling_method_name [String]
81
+ # Name of the method that is used to poll for LROs. E.g. `Poll`
82
+ #
83
+ # @param lro_object_full_name
84
+ # Full grpc name of the object that is returned by the polling method.
85
+ # E.g. `google.cloud.compute.v1.Operation`
86
+ #
87
+ # @param operation_status_field [String]
88
+ # In the Operation message for this service, the name of the `status` field.
89
+ # The `status` field signals that the operation has finished. It should either contain symbols, and
90
+ # be set to `:DONE` when finished or contain a boolean and be set to `true` when finished.
91
+ #
92
+ # @param operation_name_field [String, nil]
93
+ # In the Operation message for this service, the name of the `name` field.
94
+ #
95
+ # @param operation_err_code_field [String, nil]
96
+ # In the Operation message for this service, the name of the `error code` field.
97
+ #
98
+ # @param operation_err_msg_field [String, nil]
99
+ # In the Operation message for this service, the name of the `error message` field.
100
+ #
101
+ # @param operation_response_fields [Hash<String, String>]
102
+ # The map of the fields that need to be copied from the
103
+ # long-running operation object that the polling method returns to the polling request.
104
+ # The format is `name of the operation object field` -> `name of the polling request field` (`from -> to`).
105
+ # E.g. `{"foo" => "bar"}` means that when constructing a polling request,
106
+ # the following assignment should be carried out:
107
+ # `lro_polling_request.bar = operation_object.foo`.
108
+ #
109
+ def initialize service_full_name,
110
+ polling_method_name,
111
+ lro_object_full_name,
112
+ operation_status_field,
113
+ operation_name_field,
114
+ operation_err_code_field,
115
+ operation_err_msg_field,
116
+ operation_response_fields
117
+ @service_full_name = service_full_name
118
+ @polling_method_name = polling_method_name
119
+ @lro_object_full_name = lro_object_full_name
120
+ @operation_status_field = operation_status_field
121
+ @operation_name_field = operation_name_field
122
+ @operation_err_code_field = operation_err_code_field
123
+ @operation_err_msg_field = operation_err_msg_field
124
+ @operation_response_fields = operation_response_fields
125
+ end
126
+ end
127
+
128
+ ##
129
+ # Service does not provide nonstandard LRO polling capabilities
130
+ #
131
+ class NoNonstandardLro
132
+ include Singleton
133
+
134
+ ##
135
+ # @return [Boolean] Whether this is a model for a nonstandard LRO provider service
136
+ #
137
+ def nonstandard_lro?
138
+ false
139
+ end
140
+ end
141
+
142
+ class << self
143
+ ##
144
+ # Parses the service proto information to determine, whether it is
145
+ # a provider for nonstandard long-running operations polling
146
+ #
147
+ # @param service [Gapic::Schema::Service]
148
+ #
149
+ # @raises [Gapic::Model::ModelError]
150
+ #
151
+ # @return [NonstandardLroProvider, nil]
152
+ def parse_nonstandard_lro service
153
+ polling_method = find_polling_method service
154
+ return unless polling_method
155
+
156
+ # There should not be any methods that have the `operation_service` annotation
157
+ # in the LRO provider service.
158
+ # In theory there is nothing wrong with one LRO polling service using another
159
+ # LRO polling service, in practice there is potential for service intialization cycles
160
+ # Until we have a real usecase it's safer to assume an error in proto.
161
+ nonstandard_lro_candidates = service.methods.find_all do |m|
162
+ !m.operation_service.nil? && !m.operation_service.empty?
163
+ end
164
+
165
+ if nonstandard_lro_candidates.length.positive?
166
+ ops_service_method = nonstandard_lro_candidates[0]
167
+ error_text = "A service `#{service.name}` has a method annotated " \
168
+ "with `polling_method` (`#{polling_method.name}`), and also a method annotated " \
169
+ "with `operation_service` (`#{ops_service_method.name}`). " \
170
+ "This means a grpc service tries to be a client " \
171
+ "and a provider of the nonstandard LRO at the same time. " \
172
+ "This is not supported."
173
+ raise ModelError, error_text
174
+ end
175
+
176
+ lro_object_full_name = polling_method.output.full_name
177
+
178
+ status_field = find_status_field service, polling_method
179
+ operation_status_field = status_field.name
180
+
181
+ operation_name_field = name_of_operation_field polling_method, ::Google::Cloud::OperationResponseMapping::NAME
182
+ operation_err_code_field = name_of_operation_field polling_method,
183
+ ::Google::Cloud::OperationResponseMapping::ERROR_CODE
184
+ operation_err_msg_field = name_of_operation_field polling_method,
185
+ ::Google::Cloud::OperationResponseMapping::ERROR_MESSAGE
186
+
187
+ # optionally, there might be fields in the polling method's input object
188
+ # that should be filled with information from the LRO object
189
+ ops_response_fields = polling_method.input.fields.find_all do |f|
190
+ !f.operation_response_field.nil? && !f.operation_response_field.empty?
191
+ end
192
+
193
+ operation_response_fields = ops_response_fields.to_h do |field|
194
+ [field.name, field.operation_response_field]
195
+ end
196
+
197
+ NonstandardLroProvider.new service.full_name,
198
+ polling_method.name,
199
+ lro_object_full_name,
200
+ operation_status_field,
201
+ operation_name_field,
202
+ operation_err_code_field,
203
+ operation_err_msg_field,
204
+ operation_response_fields
205
+ end
206
+
207
+ private
208
+
209
+ ##
210
+ # Returns a name of the polling method's output object (presumed to be LRO object)'s field
211
+ # that is marked with a given `operation_response_field` annotation,
212
+ # or nil if no such field exists.
213
+ #
214
+ # @param polling_method [Gapic::Schema::Method] the polling method
215
+ # @param ops_response_field [Integer] the value of the `operation_response_field` annotation
216
+ #
217
+ # @return [String]
218
+ #
219
+ def name_of_operation_field polling_method, ops_response_field
220
+ name_candidate = polling_method.output.fields.find do |f|
221
+ f.operation_field == ops_response_field
222
+ end
223
+ name_candidate&.name
224
+ end
225
+
226
+ ##
227
+ # If this service is provider for a nonstandard LRO,
228
+ # find the polling method.
229
+ # Otherwise returns nil.
230
+ #
231
+ # @param service [Gapic::Schema::Service]
232
+ #
233
+ # @raises [Gapic::Model::ModelError]
234
+ #
235
+ # @returns [Gapic::Schema::Method, nil]
236
+ #
237
+ def find_polling_method service
238
+ # On a LRO service, one method should be marked as 'polling'
239
+ polling_method_candidates = service.methods.find_all do |m|
240
+ !m.polling_method.nil? && m.polling_method
241
+ end
242
+ if polling_method_candidates.length > 1
243
+ error_text = "A service #{service.name} has more than one method annotated " \
244
+ "with `operation_polling_method`. This should not happen."
245
+ raise ModelError, error_text
246
+ end
247
+
248
+ return unless polling_method_candidates.length == 1
249
+
250
+ polling_method_candidates[0]
251
+ end
252
+
253
+ ##
254
+ # Find the `status` field in the LRO message that this service provides a
255
+ # polling functionality for
256
+ #
257
+ # @param service [Gapic::Schema::Service]
258
+ # @param polling_method [Gapic::Schema::Method]
259
+ #
260
+ # @raises [Gapic::Model::ModelError]
261
+ #
262
+ # @returns [Gapic::Schema::Field]
263
+ #
264
+ def find_status_field service, polling_method
265
+ # The output of the polling method is an Operation, which should have at least
266
+ # a Status field
267
+ status_candidates = polling_method.output.fields.find_all do |f|
268
+ f.operation_field == ::Google::Cloud::OperationResponseMapping::STATUS
269
+ end
270
+
271
+ if status_candidates.length > 1
272
+ error_text = "A nonstandard LRO provider service `#{service.name}`'s " \
273
+ "polling method `#{polling_method.name}`'s output message " \
274
+ "`#{polling_method.output.name}` has more than one field annotated " \
275
+ "with `google.cloud.operation_field = STATUS`. This is not supported."
276
+ raise ModelError, error_text
277
+ end
278
+
279
+ if status_candidates.empty?
280
+ error_text = "A nonstandard LRO provider service `#{service.name}`'s " \
281
+ "polling method `#{polling_method.name}`'s output message " \
282
+ "`#{polling_method.output.name}` does not have any fields annotated " \
283
+ "with `google.cloud.operation_field = STATUS`. This is not supported."
284
+ raise ModelError, error_text
285
+ end
286
+
287
+ status_candidates[0]
288
+ end
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "gapic/model/method/http_annotation"
18
+ require "gapic/model/method/lro"
19
+ require "gapic/model/method/routing"
20
+ require "gapic/model/mixins"
21
+ require "gapic/model/model_error"
22
+ require "gapic/model/service/nonstandard_lro_provider"