gapic-generator 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +13 -0
  3. data/CHANGELOG.md +30 -0
  4. data/CODE_OF_CONDUCT.md +43 -0
  5. data/CONTRIBUTING.md +28 -0
  6. data/LICENSE +202 -0
  7. data/README.md +72 -0
  8. data/bin/gapic-generator +103 -0
  9. data/bin/protoc-gen-ruby_gapic +33 -0
  10. data/default-rubocop.yml +10 -0
  11. data/gem_templates/binary.erb +20 -0
  12. data/gem_templates/dockerfile.erb +39 -0
  13. data/gem_templates/entrypoint.erb +24 -0
  14. data/gem_templates/gapic_sh.erb +97 -0
  15. data/gem_templates/gemfile.erb +8 -0
  16. data/gem_templates/gemspec.erb +36 -0
  17. data/gem_templates/generator.erb +37 -0
  18. data/gem_templates/gitignore.erb +10 -0
  19. data/gem_templates/rakefile.erb +29 -0
  20. data/gem_templates/readme.erb +69 -0
  21. data/gem_templates/rubocop.erb +16 -0
  22. data/gem_templates/shared/_header.erb +4 -0
  23. data/gem_templates/shared/_license.erb +13 -0
  24. data/gem_templates/shared/_warning.erb +1 -0
  25. data/gem_templates/test_generator.erb +13 -0
  26. data/gem_templates/test_helper.erb +25 -0
  27. data/gem_templates/version.erb +10 -0
  28. data/lib/gapic/file_formatter.rb +62 -0
  29. data/lib/gapic/gem_builder.rb +98 -0
  30. data/lib/gapic/generator.rb +30 -0
  31. data/lib/gapic/generator/version.rb +21 -0
  32. data/lib/gapic/generators/base_generator.rb +91 -0
  33. data/lib/gapic/generators/default_generator.rb +101 -0
  34. data/lib/gapic/grpc_service_config/method_config.rb +49 -0
  35. data/lib/gapic/grpc_service_config/parser.rb +218 -0
  36. data/lib/gapic/grpc_service_config/parsing_error.rb +25 -0
  37. data/lib/gapic/grpc_service_config/retry_policy.rb +51 -0
  38. data/lib/gapic/grpc_service_config/service_config.rb +42 -0
  39. data/lib/gapic/path_template.rb +35 -0
  40. data/lib/gapic/path_template/parser.rb +83 -0
  41. data/lib/gapic/path_template/segment.rb +67 -0
  42. data/lib/gapic/resource_lookup.rb +91 -0
  43. data/lib/gapic/runner.rb +76 -0
  44. data/lib/gapic/schema.rb +17 -0
  45. data/lib/gapic/schema/api.rb +264 -0
  46. data/lib/gapic/schema/loader.rb +269 -0
  47. data/lib/gapic/schema/wrappers.rb +718 -0
  48. data/lib/google/api/annotations.pb.rb +39 -0
  49. data/lib/google/api/client.pb.rb +43 -0
  50. data/lib/google/api/field_behavior.pb.rb +51 -0
  51. data/lib/google/api/http.pb.rb +60 -0
  52. data/lib/google/api/resource.pb.rb +80 -0
  53. data/lib/google/longrunning/operations.pb.rb +115 -0
  54. data/lib/google/protobuf/any.pb.rb +40 -0
  55. data/lib/google/protobuf/compiler/plugin.pb.rb +72 -0
  56. data/lib/google/protobuf/descriptor.pb.rb +359 -0
  57. data/lib/google/protobuf/empty.pb.rb +36 -0
  58. data/lib/google/rpc/status.pb.rb +46 -0
  59. data/templates/default/gem/_version.erb +2 -0
  60. data/templates/default/gem/changelog.erb +3 -0
  61. data/templates/default/gem/gemfile.erb +4 -0
  62. data/templates/default/gem/gemspec.erb +37 -0
  63. data/templates/default/gem/gitignore.erb +18 -0
  64. data/templates/default/gem/license.erb +22 -0
  65. data/templates/default/gem/rakefile.erb +27 -0
  66. data/templates/default/gem/readme.erb +24 -0
  67. data/templates/default/gem/rubocop.erb +59 -0
  68. data/templates/default/gem/version.erb +6 -0
  69. data/templates/default/gem/yardopts.erb +12 -0
  70. data/templates/default/helpers/default_helper.rb +45 -0
  71. data/templates/default/helpers/filepath_helper.rb +38 -0
  72. data/templates/default/helpers/namespace_helper.rb +44 -0
  73. data/templates/default/helpers/presenter_helper.rb +24 -0
  74. data/templates/default/helpers/presenters/enum_presenter.rb +35 -0
  75. data/templates/default/helpers/presenters/enum_value_presenter.rb +33 -0
  76. data/templates/default/helpers/presenters/field_presenter.rb +146 -0
  77. data/templates/default/helpers/presenters/file_presenter.rb +53 -0
  78. data/templates/default/helpers/presenters/gem_presenter.rb +140 -0
  79. data/templates/default/helpers/presenters/message_presenter.rb +66 -0
  80. data/templates/default/helpers/presenters/method_presenter.rb +293 -0
  81. data/templates/default/helpers/presenters/package_presenter.rb +65 -0
  82. data/templates/default/helpers/presenters/resource_presenter.rb +92 -0
  83. data/templates/default/helpers/presenters/sample_presenter.rb +74 -0
  84. data/templates/default/helpers/presenters/service_presenter.rb +276 -0
  85. data/templates/default/layouts/_ruby.erb +20 -0
  86. data/templates/default/package.erb +6 -0
  87. data/templates/default/proto_docs/_enum.erb +13 -0
  88. data/templates/default/proto_docs/_message.erb +23 -0
  89. data/templates/default/proto_docs/_proto_file.erb +9 -0
  90. data/templates/default/proto_docs/proto_file.erb +6 -0
  91. data/templates/default/proto_docs/readme.erb +5 -0
  92. data/templates/default/service.erb +8 -0
  93. data/templates/default/service/client.erb +6 -0
  94. data/templates/default/service/client/_client.erb +137 -0
  95. data/templates/default/service/client/_config.erb +155 -0
  96. data/templates/default/service/client/_credentials.erb +21 -0
  97. data/templates/default/service/client/_helpers.erb +9 -0
  98. data/templates/default/service/client/_operations.erb +88 -0
  99. data/templates/default/service/client/_paths.erb +8 -0
  100. data/templates/default/service/client/_requires.erb +1 -0
  101. data/templates/default/service/client/_resource.erb +6 -0
  102. data/templates/default/service/client/_self_configure.erb +9 -0
  103. data/templates/default/service/client/_self_configure_defaults.erb +22 -0
  104. data/templates/default/service/client/_self_configure_retry_policy.erb +15 -0
  105. data/templates/default/service/client/method/_def.erb +21 -0
  106. data/templates/default/service/client/method/def/_options_defaults.erb +29 -0
  107. data/templates/default/service/client/method/def/_request.erb +6 -0
  108. data/templates/default/service/client/method/def/_request_normal.erb +4 -0
  109. data/templates/default/service/client/method/def/_request_streaming.erb +9 -0
  110. data/templates/default/service/client/method/def/_rescue.erb +1 -0
  111. data/templates/default/service/client/method/def/_response.erb +6 -0
  112. data/templates/default/service/client/method/def/_response_normal.erb +8 -0
  113. data/templates/default/service/client/method/def/_response_paged.erb +9 -0
  114. data/templates/default/service/client/method/docs/_error.erb +2 -0
  115. data/templates/default/service/client/method/docs/_request.erb +6 -0
  116. data/templates/default/service/client/method/docs/_request_field.erb +7 -0
  117. data/templates/default/service/client/method/docs/_request_normal.erb +20 -0
  118. data/templates/default/service/client/method/docs/_request_streaming.erb +5 -0
  119. data/templates/default/service/client/method/docs/_response.erb +6 -0
  120. data/templates/default/service/client/method/docs/_sample.erb +20 -0
  121. data/templates/default/service/client/method/docs/_sample_response.erb +24 -0
  122. data/templates/default/service/client/method/docs/_samples.erb +6 -0
  123. data/templates/default/service/client/method/docs/request_field/_arg.erb +10 -0
  124. data/templates/default/service/client/method/docs/request_field/_hash.erb +19 -0
  125. data/templates/default/service/client/method/docs/sample_response/_comment.erb +5 -0
  126. data/templates/default/service/client/method/docs/sample_response/_define.erb +2 -0
  127. data/templates/default/service/client/method/docs/sample_response/_loop.erb +12 -0
  128. data/templates/default/service/client/method/docs/sample_response/_print.erb +2 -0
  129. data/templates/default/service/client/method/docs/sample_response/_write_file.erb +2 -0
  130. data/templates/default/service/client/resource/_def.erb +6 -0
  131. data/templates/default/service/client/resource/_doc.erb +8 -0
  132. data/templates/default/service/client/resource/_multi.erb +28 -0
  133. data/templates/default/service/client/resource/_single.erb +11 -0
  134. data/templates/default/service/credentials.erb +6 -0
  135. data/templates/default/service/operations.erb +6 -0
  136. data/templates/default/service/paths.erb +6 -0
  137. data/templates/default/service/test/client.erb +24 -0
  138. data/templates/default/service/test/client_operations.erb +24 -0
  139. data/templates/default/service/test/method/_assert_response.erb +11 -0
  140. data/templates/default/service/test/method/_bidi.erb +100 -0
  141. data/templates/default/service/test/method/_client.erb +84 -0
  142. data/templates/default/service/test/method/_normal.erb +69 -0
  143. data/templates/default/service/test/method/_server.erb +85 -0
  144. data/templates/default/service/test/method/_setup.erb +21 -0
  145. data/templates/default/service/test/smoke.erb +12 -0
  146. data/templates/default/shared/_header.erb +4 -0
  147. data/templates/default/shared/_license.erb +21 -0
  148. data/templates/default/shared/_warning.erb +1 -0
  149. metadata +350 -0
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 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 "active_support/inflector"
18
+ require_relative "gem_presenter"
19
+ require_relative "service_presenter"
20
+
21
+ class PackagePresenter
22
+ include FilepathHelper
23
+ include NamespaceHelper
24
+
25
+ def initialize api, package
26
+ @api = api
27
+ @package = package
28
+ end
29
+
30
+ def gem
31
+ GemPresenter.new @api
32
+ end
33
+
34
+ def name
35
+ @package
36
+ end
37
+
38
+ def namespace
39
+ return services.first&.namespace if services.first&.namespace
40
+ ruby_namespace_for_address address
41
+ end
42
+
43
+ def services
44
+ @services ||= begin
45
+ files = @api.generate_files.select { |f| f.package == @package }
46
+ files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
47
+ end
48
+ end
49
+
50
+ def address
51
+ @package.split "."
52
+ end
53
+
54
+ def package_require
55
+ ruby_file_path @api, namespace
56
+ end
57
+
58
+ def package_file_path
59
+ package_require + ".rb"
60
+ end
61
+
62
+ def empty?
63
+ services.empty?
64
+ end
65
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 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/path_template"
18
+ require "ostruct"
19
+ require "active_support/inflector"
20
+
21
+ class ResourcePresenter
22
+ # @param resource [Google::Api::ResourceDescriptor]
23
+ def initialize resource
24
+ @resource = resource
25
+
26
+ @patterns = resource.pattern.map do |template|
27
+ segments = Gapic::PathTemplate.parse template
28
+ OpenStruct.new(
29
+ template: template,
30
+ segments: segments,
31
+ arguments: arguments_for(segments),
32
+ path_string: path_string_for(segments)
33
+ )
34
+ end
35
+
36
+ @patterns.each do |pattern|
37
+ # URI path template verification for expected proto resource usage
38
+ if named_arg_patterns? pattern.segments
39
+ raise ArgumentError, "only resources without named patterns are supported, " \
40
+ " not #{pattern.template}"
41
+ elsif positional_args? pattern.segments
42
+ raise ArgumentError, "only resources with named segments are supported, " \
43
+ " not #{pattern.template}"
44
+ end
45
+ end
46
+ end
47
+
48
+ def name
49
+ @resource.type.split("/").delete_if(&:empty?).last
50
+ end
51
+
52
+ def type
53
+ @resource.type
54
+ end
55
+
56
+ def patterns
57
+ @patterns
58
+ end
59
+
60
+ def path_helper
61
+ "#{ActiveSupport::Inflector.underscore name}_path"
62
+ end
63
+
64
+ private
65
+
66
+ def arguments_for segments
67
+ arg_segments(segments).map(&:name)
68
+ end
69
+
70
+ def arg_segments segments
71
+ segments.select { |segment| segment.is_a? Gapic::PathTemplate::Segment }
72
+ end
73
+
74
+ def path_string_for segments
75
+ segments.map do |segment|
76
+ if segment.is_a? Gapic::PathTemplate::Segment
77
+ "\#{#{segment.name}}"
78
+ else
79
+ # Should be a String
80
+ segment
81
+ end
82
+ end.join
83
+ end
84
+
85
+ def positional_args? segments
86
+ arg_segments(segments).any?(&:positional?)
87
+ end
88
+
89
+ def named_arg_patterns? segments
90
+ arg_segments(segments).any?(&:pattern)
91
+ end
92
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 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 "active_support/inflector"
18
+
19
+ class SamplePresenter
20
+ def initialize api, sample_config
21
+ @api = api
22
+ @sample_config = sample_config
23
+ end
24
+
25
+ def description
26
+ @sample_config["description"]
27
+ end
28
+
29
+ def input_parameters
30
+ @sample_config["request"].select { |f| f.key? "input_parameter" }.map { |f| RequestField.new f }
31
+ end
32
+
33
+ def fields
34
+ dotted_hash = @sample_config["request"].each_with_object({}) do |f, memo|
35
+ memo[f["field"]] = f
36
+ end
37
+ dotted_hash.each_with_object({}) do |(path, f), memo|
38
+ parts = path.split "."
39
+ leaf_hash = parts[0...-1].inject(memo) { |h, k| h[k] ||= {} }
40
+ leaf_hash[parts.last] = RequestField.new f
41
+ end
42
+ end
43
+
44
+ def kwargs
45
+ fields.keys.map { |k| "#{k}: #{k}" }.join ", "
46
+ end
47
+
48
+ def response_raw
49
+ @sample_config["response"]
50
+ end
51
+
52
+ class RequestField
53
+ attr_reader :field, :value, :input_parameter, :comment, :value_is_file
54
+ def initialize field
55
+ @field = field["field"]
56
+ @value = convert field["value"]
57
+ @input_parameter = field["input_parameter"]
58
+ @comment = field["comment"]
59
+ @comment = nil if @comment&.empty?
60
+ @value_is_file = field["value_is_file"]
61
+ end
62
+
63
+ protected
64
+
65
+ def convert val
66
+ if val.is_a? String
67
+ return ":#{val}" if val =~ /\A[A-Z_0-9]+\z/ # print constants as symbols
68
+ val.inspect
69
+ else
70
+ val.to_s
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 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 "active_support/inflector"
18
+ require_relative "gem_presenter"
19
+ require_relative "package_presenter"
20
+ require_relative "resource_presenter"
21
+ require_relative "method_presenter"
22
+
23
+ class ServicePresenter
24
+ include FilepathHelper
25
+ include NamespaceHelper
26
+
27
+ def initialize api, service
28
+ @api = api
29
+ @service = service
30
+ end
31
+
32
+ def gem
33
+ GemPresenter.new @api
34
+ end
35
+
36
+ def file
37
+ FilePresenter.new @api, @service.parent
38
+ end
39
+
40
+ def package
41
+ PackagePresenter.new @api, @service.parent.package
42
+ end
43
+
44
+ def methods
45
+ @methods ||= begin
46
+ @service.methods.map { |m| MethodPresenter.new @api, m }
47
+ end
48
+ end
49
+
50
+ def address
51
+ @service.address
52
+ end
53
+
54
+ def namespace
55
+ return @service.ruby_package if @service.ruby_package.present?
56
+
57
+ namespace = ruby_namespace_for_address @service.address[0...-1]
58
+ fix_namespace @api, namespace
59
+ end
60
+
61
+ def version
62
+ ActiveSupport::Inflector.camelize @service.address[-2]
63
+ end
64
+
65
+ def name
66
+ @service.name
67
+ end
68
+
69
+ def proto_service_name_full
70
+ fix_namespace @api, "#{namespace}::#{name}"
71
+ end
72
+
73
+ def proto_service_file_path
74
+ @service.parent.name.sub ".proto", "_pb.rb"
75
+ end
76
+
77
+ def proto_service_file_name
78
+ proto_service_file_path.split("/").last
79
+ end
80
+
81
+ def proto_service_require
82
+ proto_service_file_path.sub ".rb", ""
83
+ end
84
+
85
+ def proto_services_file_path
86
+ @service.parent.name.sub ".proto", "_services_pb.rb"
87
+ end
88
+
89
+ def proto_services_file_name
90
+ proto_services_file_path.split("/").last
91
+ end
92
+
93
+ def proto_services_require
94
+ proto_services_file_path.sub ".rb", ""
95
+ end
96
+
97
+ def proto_service_stub_name_full
98
+ "#{proto_service_name_full}::Stub"
99
+ end
100
+
101
+ def service_file_path
102
+ service_require + ".rb"
103
+ end
104
+
105
+ def service_file_name
106
+ service_file_path.split("/").last
107
+ end
108
+
109
+ def service_require
110
+ ruby_file_path @api, proto_service_name_full
111
+ end
112
+
113
+ def client_name
114
+ "Client"
115
+ end
116
+
117
+ def client_name_full
118
+ fix_namespace @api, "#{proto_service_name_full}::#{client_name}"
119
+ end
120
+
121
+ def client_require
122
+ ruby_file_path @api, client_name_full
123
+ end
124
+
125
+ def client_file_path
126
+ client_require + ".rb"
127
+ end
128
+
129
+ def client_file_name
130
+ client_file_path.split("/").last
131
+ end
132
+
133
+ def client_endpoint
134
+ @service.host || default_config(:default_host) || "localhost"
135
+ end
136
+
137
+ def client_scopes
138
+ @service.scopes || default_config(:oauth_scopes)
139
+ end
140
+
141
+ def client_proto_name
142
+ @service.address.join "."
143
+ end
144
+
145
+ def credentials_name
146
+ "Credentials"
147
+ end
148
+
149
+ def credentials_name_full
150
+ fix_namespace @api, "#{proto_service_name_full}::#{credentials_name}"
151
+ end
152
+
153
+ def credentials_file_path
154
+ credentials_require + ".rb"
155
+ end
156
+
157
+ def credentials_file_name
158
+ credentials_file_path.split("/").last
159
+ end
160
+
161
+ def credentials_require
162
+ ruby_file_path @api, credentials_name_full
163
+ end
164
+
165
+ def helpers_file_path
166
+ helpers_require + ".rb"
167
+ end
168
+
169
+ def helpers_file_name
170
+ "helpers.rb"
171
+ end
172
+
173
+ def helpers_require
174
+ ruby_file_path @api, "#{proto_service_name_full}::Helpers"
175
+ end
176
+
177
+ def references
178
+ @references ||= @service.resources.map { |resource| ResourcePresenter.new resource }.sort_by(&:name)
179
+ end
180
+
181
+ def paths?
182
+ references.any?
183
+ end
184
+
185
+ def paths_name
186
+ "Paths"
187
+ end
188
+
189
+ def paths_name_full
190
+ fix_namespace @api, "#{proto_service_name_full}::#{paths_name}"
191
+ end
192
+
193
+ def paths_file_path
194
+ paths_require + ".rb"
195
+ end
196
+
197
+ def paths_file_name
198
+ paths_file_path.split("/").last
199
+ end
200
+
201
+ def paths_require
202
+ ruby_file_path @api, "#{proto_service_name_full}::#{paths_name}"
203
+ end
204
+
205
+ def test_client_file_path
206
+ service_file_path.sub ".rb", "_test.rb"
207
+ end
208
+
209
+ def test_client_operations_file_path
210
+ service_file_path.sub ".rb", "_operations_test.rb"
211
+ end
212
+
213
+ def stub_name
214
+ "#{ActiveSupport::Inflector.underscore name}_stub"
215
+ end
216
+
217
+ def lro?
218
+ methods.find(&:lro?)
219
+ end
220
+
221
+ def lro_client_var
222
+ "operations_client"
223
+ end
224
+
225
+ def lro_client_ivar
226
+ "@#{lro_client_var}"
227
+ end
228
+
229
+ def operations_name
230
+ "Operations"
231
+ end
232
+
233
+ def operations_name_full
234
+ fix_namespace @api, "#{proto_service_name_full}::#{operations_name}"
235
+ end
236
+
237
+ def operations_file_path
238
+ operations_require + ".rb"
239
+ end
240
+
241
+ def operations_file_name
242
+ operations_file_path.split("/").last
243
+ end
244
+
245
+ def operations_require
246
+ ruby_file_path @api, "#{proto_service_name_full}::#{operations_name}"
247
+ end
248
+
249
+ def lro_service
250
+ lro = @service.parent.parent.files.find { |file| file.name == "google/longrunning/operations.proto" }
251
+
252
+ return ServicePresenter.new @api, lro.services.first unless lro.nil?
253
+ end
254
+
255
+ def config_channel_args
256
+ { "grpc.service_config_disable_resolution" => 1 }
257
+ end
258
+
259
+ def grpc_service_config
260
+ return unless @api.grpc_service_config&.service_level_configs&.key? grpc_full_name
261
+ @api.grpc_service_config.service_level_configs[grpc_full_name]
262
+ end
263
+
264
+ def grpc_full_name
265
+ @service.address.join "."
266
+ end
267
+
268
+ private
269
+
270
+ def default_config key
271
+ return unless @service.parent.parent.configuration[:defaults]
272
+ return unless @service.parent.parent.configuration[:defaults][:service]
273
+
274
+ @service.parent.parent.configuration[:defaults][:service][key]
275
+ end
276
+ end