gapic-generator 0.1.3

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 +38 -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 +56 -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,67 @@
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
+ module Gapic
18
+ module PathTemplate
19
+ # A segment in a URI path template.
20
+ #
21
+ # @see https://tools.ietf.org/html/rfc6570 URI Template
22
+ #
23
+ # @!attribute [r] name
24
+ # @return [String, Integer] The name of a named segment, or the position
25
+ # of a positional segment.
26
+ # @!attribute [r] pattern
27
+ # @return [String, nil] The pattern of the segment, nil if not set.
28
+ class Segment
29
+ attr_reader :name, :pattern
30
+
31
+ def initialize name, pattern
32
+ @name = name
33
+ @pattern = pattern
34
+ end
35
+
36
+ # Determines if the segment is positional (has a number for a name).
37
+ #
38
+ # @return [Boolean]
39
+ def positional?
40
+ name.is_a? Integer
41
+ end
42
+
43
+ # Determines if the segment is named (has a string for a name).
44
+ #
45
+ # @return [Boolean]
46
+ def named?
47
+ !positional?
48
+ end
49
+
50
+ # Determines if the segment has a pattern. Positional segments always
51
+ # have a pattern. Named segments may have a pattern if provided in the
52
+ # URI path template.
53
+ #
54
+ # @return [Boolean]
55
+ def pattern?
56
+ !@pattern.nil?
57
+ end
58
+
59
+ # @private
60
+ def == other
61
+ return false unless other.is_a? self.class
62
+
63
+ (name == other.name) && (pattern == other.pattern)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 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
+ # TODO: Enter docs
19
+ # Dooooooooocs!!!
20
+ class ResourceLookup
21
+ # @private
22
+ def initialize service
23
+ @service = service
24
+ @api = service.parent.parent
25
+ end
26
+
27
+ # @private
28
+ def lookup!
29
+ resources = @api.files.flat_map { |file| lookup_file_resource_descriptors file }
30
+ resources.compact.uniq
31
+ end
32
+
33
+ # @private
34
+ def lookup_file_resource_descriptors file
35
+ resources = []
36
+ resources += file.resources.select { |resource| service_resource_types.include? resource.type }
37
+ resources += file.messages.flat_map { |message| lookup_message_resources_descriptors message }
38
+ resources
39
+ end
40
+
41
+ # @private
42
+ def service_resource_types
43
+ @service_resource_types ||= begin
44
+ @service.methods.flat_map do |method|
45
+ message_resource_types method.input
46
+ end.uniq
47
+ end
48
+ end
49
+
50
+ # @private
51
+ def message_resource_types message, seen_messages = []
52
+ return [] if seen_messages.include? message
53
+ seen_messages << message
54
+ resource_types = []
55
+ resource_types << message.resource.type if message.resource
56
+ resource_types += message.nested_messages.map do |nested_message|
57
+ message_resource_types nested_message, seen_messages
58
+ end
59
+ message.fields.each do |field|
60
+ resource_types << field.resource_reference.type if field.resource_reference
61
+ resource_types += message_resource_types field.message, seen_messages if field.message?
62
+ end
63
+ resource_types.flatten
64
+ end
65
+
66
+ # @private
67
+ def lookup_message_resources_descriptors message
68
+ resources = []
69
+
70
+ # We don't expect service_resource_types to iclude nil, so we can use message.resource&.type
71
+ resources << message.resource if service_resource_types.include? message.resource&.type
72
+
73
+ if message.nested_messages
74
+ resources += message.nested_messages.flat_map do |nested_message|
75
+ lookup_message_resources_descriptors nested_message
76
+ end
77
+ end
78
+
79
+ resources
80
+ end
81
+
82
+ # Lookup all resources for a given service.
83
+ #
84
+ # @param service [Gapic::Service] The service to lookup on.
85
+ #
86
+ # @return [Array<Google::Api::ResourceDescriptor>]
87
+ def self.for_service service
88
+ ResourceLookup.new(service).lookup!
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 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/generator"
18
+ require "gapic/schema"
19
+ require "google/protobuf/compiler/plugin.pb"
20
+
21
+ module Gapic
22
+ # TODO: Enter docs
23
+ # Dooooooooocs!!!
24
+ class Runner
25
+ attr_reader :request
26
+
27
+ # Initializes the runner.
28
+ # @param [Google::Protobuf::Compiler::CodeGeneratorRequest] request
29
+ def initialize request
30
+ @request = request
31
+ end
32
+
33
+ # Run protoc generation.
34
+ # @param [String] generator_type
35
+ # @return [Google::Protobuf::Compiler::CodeGeneratorResponse]
36
+ def run generator_type: nil
37
+ # Create an API Schema from the FileDescriptorProtos
38
+ api = Gapic::Schema::Api.new request
39
+
40
+ write_binary_file! api
41
+
42
+ # Retrieve generator type from protoc_options if not already provided.
43
+ generator_type ||= api.protoc_options["generator"]
44
+ # Find the generator for the generator type.
45
+ generator = Gapic::Generator.find generator_type
46
+
47
+ # Create and run the generator from the API.
48
+ output_files = generator.new(api).generate
49
+
50
+ # Create and write the response
51
+ Google::Protobuf::Compiler::CodeGeneratorResponse.new \
52
+ file: output_files
53
+ end
54
+
55
+ # Run protoc generation.
56
+ # @param [Google::Protobuf::Compiler::CodeGeneratorRequest] request
57
+ # @param [String] generator
58
+ # @return [Google::Protobuf::Compiler::CodeGeneratorResponse]
59
+ def self.run request, generator: nil
60
+ new(request).run generator_type: generator
61
+ end
62
+
63
+ private
64
+
65
+ def write_binary_file! api
66
+ return unless api.protoc_options["binary_output"]
67
+
68
+ # First, strip the binary_output parameter out so it doesn't get saved
69
+ binary_file = api.protoc_options.delete "binary_output"
70
+ request.parameter = api.protoc_parameter
71
+
72
+ # Write binary file if the binary_output option is set
73
+ File.binwrite binary_file, request.to_proto
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 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/schema/api"
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 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 "yaml"
18
+ require "json"
19
+ require "gapic/schema/loader"
20
+ require "gapic/grpc_service_config/parser"
21
+
22
+ module Gapic
23
+ module Schema
24
+ # rubocop:disable Metrics/ClassLength
25
+
26
+ # A representation of a full API.
27
+ #
28
+ # @!attribute [r] files
29
+ # @return [Array<File>] The files represented by this API.
30
+ # @!attribute [r] services
31
+ # @return [<Array<Service>] The services seen across all files in this
32
+ # API.
33
+ # @!attribute [r] messages
34
+ # @return [Array<Message>] The top level messages seen across all files
35
+ # in this API.
36
+ # @!attribute [r] enums
37
+ # @return [Array<Enum>] The top level enums seen across all files in
38
+ # this API.
39
+ class Api
40
+ attr_accessor :request, :files
41
+
42
+ # Initializes an API object with the file descriptors that represent the
43
+ # API.
44
+ #
45
+ # @param request [Google::Protobuf::Compiler::CodeGeneratorRequest]
46
+ # The request object.
47
+ def initialize request
48
+ @request = request
49
+ loader = Loader.new
50
+ @files = request.proto_file.map do |fd|
51
+ loader.load_file fd, request.file_to_generate.include?(fd.name)
52
+ end
53
+ @files.each { |f| f.parent = self }
54
+ end
55
+
56
+ def lookup address
57
+ address = address.join "." if address.is_a? Array
58
+ @files.each do |f|
59
+ lookup = f.lookup address
60
+ return lookup if lookup
61
+ end
62
+ nil
63
+ end
64
+
65
+ def file_for address
66
+ address = address.join "." if address.is_a? Array
67
+ matching_files = @files.select { |f| f.lookup address }
68
+ matching_files.first
69
+ end
70
+
71
+ def fix_file_path str
72
+ str = String str
73
+ return str if configuration[:overrides].nil?
74
+ return str if configuration[:overrides][:file_path].nil?
75
+ configuration[:overrides][:file_path].fetch str, str
76
+ end
77
+
78
+ def fix_namespace str
79
+ str = String str
80
+ return str if configuration[:overrides].nil?
81
+ return str if configuration[:overrides][:namespace].nil?
82
+ configuration[:overrides][:namespace].fetch str, str
83
+ end
84
+
85
+ def generate_files
86
+ @files.select(&:generate?)
87
+ end
88
+
89
+ def services
90
+ @files.map(&:services).flatten
91
+ end
92
+
93
+ def messages
94
+ @files.map(&:messages).flatten
95
+ end
96
+
97
+ # Structured Hash representation of the parameter values.
98
+ # @return [Hash]
99
+ # A Hash of the request parameters.
100
+ def protoc_options
101
+ @protoc_options ||= begin
102
+ result = {}
103
+ parameters = parse_parameter request.parameter
104
+ parameters.each do |param_array|
105
+ key = param_array.first
106
+ next if key.empty?
107
+ value = param_array[1..-1]
108
+ value = value.first if value.size == 1
109
+ value = nil if value.empty?
110
+ result[str_to_key(key)] = value
111
+ end
112
+ result
113
+ end
114
+ end
115
+
116
+ # Reconstructed string representation of the protoc options
117
+ # @return [String]
118
+ def protoc_parameter
119
+ protoc_options.map do |k, v|
120
+ v = Array(v).map do |s|
121
+ s.gsub("\\", "\\\\\\\\").gsub(",", "\\\\,").gsub("=", "\\\\=")
122
+ end.join("=")
123
+ k = key_to_str k
124
+ "#{k}=#{v}"
125
+ end.join ","
126
+ end
127
+
128
+ # Structured representation of the samples configuration files.
129
+ # @return [Array<Hash>]
130
+ # An array of the sample file hashes.
131
+ def samples
132
+ @samples ||= begin
133
+ protoc_options["samples"].to_s.split(";").flat_map do |sample_path|
134
+ YAML.load_file sample_path
135
+ end.compact
136
+ end
137
+ end
138
+
139
+ # Structured representation of the standalone samples configuration files.
140
+ # @return [Array<Hash>]
141
+ # An array of the standalone sample configuration hashes.
142
+ def standalone_samples
143
+ @standalone_samples ||= begin
144
+ supported_types = [
145
+ "com.google.api.codegen.SampleConfigProto",
146
+ "com.google.api.codegen.samplegen.v1p2.SampleConfigProto"
147
+ ]
148
+ supported_sample_types = [nil, "standalone"]
149
+ samples.select { |sample_file| supported_types.include? sample_file["type"] }
150
+ .select { |sample_file| sample_file["schema_version"] == "1.2.0" }
151
+ .map { |sample_file| sample_file["samples"] }
152
+ .flatten.compact
153
+ .select { |sample_config| supported_sample_types.include? sample_config["sample_type"] }
154
+ end
155
+ end
156
+
157
+ # Structured representation of the standalone test samples configuration files.
158
+ # @return [Array<Hash>]
159
+ # An array of the standalone sample configuration hashes.
160
+ def standalone_test_samples
161
+ @standalone_test_samples ||= begin
162
+ samples.select { |sample| sample["type"] == "test/samples" }
163
+ .select { |sample| sample["schema_version"] == "1" || sample["schema_version"] == 1 }
164
+ .map { |sample| sample["samples"] }
165
+ .flatten.compact
166
+ end
167
+ end
168
+
169
+ # Structured representation of the inline samples configuration files.
170
+ # @return [Array<Hash>]
171
+ # An array of the incode sample configuration hashes, sorted by sample_type.
172
+ def incode_samples
173
+ @incode_samples ||= begin
174
+ supported_types = [
175
+ "com.google.api.codegen.SampleConfigProto",
176
+ "com.google.api.codegen.samplegen.v1p2.SampleConfigProto"
177
+ ]
178
+ samples.select { |sample_file| supported_types.include? sample_file["type"] }
179
+ .select { |sample_file| sample_file["schema_version"] == "1.2.0" }
180
+ .map { |sample_file| sample_file["samples"] }
181
+ .flatten.compact
182
+ .select { |sample_config| sample_config["sample_type"]&.start_with? "incode/" }
183
+ .sort_by { |sample_config| sample_config["sample_type"] }
184
+ end
185
+ end
186
+
187
+ # Structured Hash representation of the configuration file.
188
+ # @return [Hash]
189
+ # A Hash of the configuration values.
190
+ def configuration
191
+ @configuration ||= begin
192
+ config_file = protoc_options["configuration"]
193
+ config = config_file ? YAML.load_file(config_file) : {}
194
+ protoc_options.each do |k, v|
195
+ next if k == "configuration"
196
+ branch = key_to_str(k).split(".").reverse.inject(v) { |m, s| { str_to_key(s) => m } }
197
+ config = deep_merge config, branch
198
+ end
199
+ config
200
+ end
201
+ end
202
+
203
+ # Raw parsed json of the combined grpc service config files if provided
204
+ # or an empty hash if no config was provided
205
+ def grpc_service_config_raw
206
+ @grpc_service_config_raw ||= begin
207
+ filenames = protoc_options["grpc_service_config"].to_s.split ";"
208
+ filenames.inject({}) do |running_hash, filename|
209
+ file_hash = JSON.parse ::File.read filename
210
+ deep_merge running_hash, file_hash
211
+ end
212
+ end
213
+ end
214
+
215
+ # Parsed grpc service config
216
+ def grpc_service_config
217
+ @grpc_service_config ||= begin
218
+ Gapic::GrpcServiceConfig::Parser.parse grpc_service_config_raw
219
+ end
220
+ end
221
+
222
+ private
223
+
224
+ def parse_parameter str
225
+ str.scan(/\\.|,|=|[^\\,=]+/)
226
+ .each_with_object([[String.new]]) do |tok, arr|
227
+ if tok == ","
228
+ arr.append [String.new]
229
+ elsif tok == "="
230
+ arr.last.append String.new
231
+ elsif tok.start_with? "\\"
232
+ arr.last.last << tok[1]
233
+ else
234
+ arr.last.last << tok
235
+ end
236
+ arr
237
+ end
238
+ end
239
+
240
+ def str_to_key str
241
+ str = str.to_s
242
+ str.start_with?(":") ? str[1..-1].to_sym : str
243
+ end
244
+
245
+ def key_to_str key
246
+ key.is_a?(::Symbol) ? ":#{key}" : key.to_s
247
+ end
248
+
249
+ def deep_merge left, right
250
+ left.merge right do |_k, lt, rt|
251
+ if lt.is_a?(Hash) && rt.is_a?(Hash)
252
+ deep_merge lt, rt
253
+ elsif lt.is_a?(Array) && rt.is_a?(Array)
254
+ lt + rt
255
+ else
256
+ rt
257
+ end
258
+ end
259
+ end
260
+ end
261
+
262
+ # rubocop:enable Metrics/ClassLength
263
+ end
264
+ end