aws-sdk-code-generator 0.4.0.pre → 0.6.0.pre

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/aws-sdk-code-generator/api.rb +2 -1
  3. data/lib/aws-sdk-code-generator/client_constructor.rb +2 -1
  4. data/lib/aws-sdk-code-generator/client_operation_documentation.rb +2 -1
  5. data/lib/aws-sdk-code-generator/client_operation_list.rb +4 -0
  6. data/lib/aws-sdk-code-generator/code_builder.rb +54 -2
  7. data/lib/aws-sdk-code-generator/endpoint_parameter.rb +190 -0
  8. data/lib/aws-sdk-code-generator/eventstream_example.rb +34 -34
  9. data/lib/aws-sdk-code-generator/gem_builder.rb +3 -5
  10. data/lib/aws-sdk-code-generator/helper.rb +11 -1
  11. data/lib/aws-sdk-code-generator/plugin_list.rb +5 -2
  12. data/lib/aws-sdk-code-generator/rbs/error_list.rb +38 -0
  13. data/lib/aws-sdk-code-generator/rbs/keyword_argument_builder.rb +159 -0
  14. data/lib/aws-sdk-code-generator/rbs/method_signature.rb +11 -0
  15. data/lib/aws-sdk-code-generator/rbs/resource_action.rb +39 -0
  16. data/lib/aws-sdk-code-generator/rbs/resource_association.rb +50 -0
  17. data/lib/aws-sdk-code-generator/rbs/resource_batch_action.rb +59 -0
  18. data/lib/aws-sdk-code-generator/rbs/resource_client_request.rb +40 -0
  19. data/lib/aws-sdk-code-generator/rbs/waiter.rb +53 -0
  20. data/lib/aws-sdk-code-generator/rbs.rb +40 -0
  21. data/lib/aws-sdk-code-generator/resource_batch_action_code.rb +3 -1
  22. data/lib/aws-sdk-code-generator/resource_client_request.rb +3 -1
  23. data/lib/aws-sdk-code-generator/resource_waiter.rb +6 -5
  24. data/lib/aws-sdk-code-generator/service.rb +85 -16
  25. data/lib/aws-sdk-code-generator/views/async_client_class.rb +5 -1
  26. data/lib/aws-sdk-code-generator/views/client_api_module.rb +58 -16
  27. data/lib/aws-sdk-code-generator/views/client_class.rb +5 -1
  28. data/lib/aws-sdk-code-generator/views/endpoint_parameters_class.rb +6 -50
  29. data/lib/aws-sdk-code-generator/views/endpoint_provider_class.rb +9 -0
  30. data/lib/aws-sdk-code-generator/views/endpoints_module.rb +18 -124
  31. data/lib/aws-sdk-code-generator/views/endpoints_plugin.rb +46 -4
  32. data/lib/aws-sdk-code-generator/views/errors_module.rb +21 -0
  33. data/lib/aws-sdk-code-generator/views/event_streams_module.rb +7 -1
  34. data/lib/aws-sdk-code-generator/views/features/smoke.rb +100 -23
  35. data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +1 -4
  36. data/lib/aws-sdk-code-generator/views/gemspec.rb +13 -3
  37. data/lib/aws-sdk-code-generator/views/rbs/client_class.rb +172 -0
  38. data/lib/aws-sdk-code-generator/views/rbs/errors_module.rb +28 -0
  39. data/lib/aws-sdk-code-generator/views/rbs/resource_class.rb +95 -0
  40. data/lib/aws-sdk-code-generator/views/rbs/root_resource_class.rb +30 -0
  41. data/lib/aws-sdk-code-generator/views/rbs/types_module.rb +257 -0
  42. data/lib/aws-sdk-code-generator/views/rbs/waiters_module.rb +22 -0
  43. data/lib/aws-sdk-code-generator/views/resource_class.rb +22 -0
  44. data/lib/aws-sdk-code-generator/views/root_resource_class.rb +19 -0
  45. data/lib/aws-sdk-code-generator/views/service_module.rb +41 -27
  46. data/lib/aws-sdk-code-generator/views/spec/endpoint_provider_spec_class.rb +25 -12
  47. data/lib/aws-sdk-code-generator/views/types_module.rb +34 -11
  48. data/lib/aws-sdk-code-generator.rb +29 -1
  49. data/templates/async_client_class.mustache +6 -1
  50. data/templates/client_api_module.mustache +14 -0
  51. data/templates/client_class.mustache +10 -47
  52. data/templates/endpoint_parameters_class.mustache +16 -13
  53. data/templates/endpoints_module.mustache +19 -11
  54. data/templates/endpoints_plugin.mustache +38 -20
  55. data/templates/errors_module.mustache +5 -0
  56. data/templates/features/smoke.mustache +11 -15
  57. data/templates/features/step_definitions.mustache +0 -5
  58. data/templates/gemspec.mustache +5 -2
  59. data/templates/rbs/client_class.mustache +39 -0
  60. data/templates/rbs/errors_module.mustache +17 -0
  61. data/templates/rbs/resource_class.mustache +71 -0
  62. data/templates/rbs/root_resource_class.mustache +26 -0
  63. data/templates/rbs/types_module.mustache +37 -0
  64. data/templates/rbs/waiters_module.mustache +17 -0
  65. data/templates/resource_class.mustache +8 -1
  66. data/templates/root_resource_class.mustache +5 -0
  67. data/templates/service_module.mustache +13 -3
  68. data/templates/spec/endpoint_provider_spec_class.mustache +11 -1
  69. data/templates/types_module.mustache +4 -0
  70. metadata +27 -7
  71. data/lib/aws-sdk-code-generator/views/features/smoke_step_definitions.rb +0 -26
  72. data/templates/features/smoke_step_definitions.mustache +0 -31
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ # similar to SyntaxExampleHash
6
+ class KeywordArgumentBuilder
7
+ include Helper
8
+
9
+ attr_reader :newline
10
+
11
+ def initialize(api:, shape:, newline:)
12
+ @api = api
13
+ @shape = shape
14
+ @newline = newline
15
+ end
16
+
17
+ def format(indent: '')
18
+ members_str = struct_members(@shape, indent, [], keyword: true)
19
+ result = []
20
+ result << '' if newline
21
+ result << members_str if !members_str.empty?
22
+ result << indent if newline
23
+ result.join(joint)
24
+ end
25
+
26
+ def struct(struct_shape, i, visited)
27
+ members_str = struct_members(struct_shape, i, visited, keyword: false)
28
+ result = ["{"]
29
+ result << members_str if struct_shape['members']&.empty?&.!
30
+ result << "#{i}}"
31
+ result.join(joint)
32
+ end
33
+
34
+ def struct_members(struct_shape, i, visited, keyword:)
35
+ lines = []
36
+ unless struct_shape['members'].nil?
37
+ n = 0
38
+ struct_shape['members'].each do |member_name, member_ref|
39
+ next if member_ref['documented'] === false
40
+ more_indent = newline ? " " : ""
41
+ if @api['shapes'][member_ref['shape']]['eventstream'] === true
42
+ # FIXME: "input_event_stream_hander: EventStreams::#{member_ref['shape']}.new"
43
+ lines << "#{i}#{more_indent}input_event_stream_hander: untyped,"
44
+ else
45
+ lines << "#{i}#{more_indent}#{struct_member(struct_shape, member_name, member_ref, i, visited, keyword: keyword)}"
46
+ end
47
+ end
48
+ end
49
+ if lines.empty?
50
+ ""
51
+ else
52
+ lines.join(joint).chomp(",")
53
+ end
54
+ end
55
+
56
+ def struct_member(struct, member_name, member_ref, i, visited, keyword:)
57
+ required = (struct['required'] || []).include?(member_name)
58
+ if keyword
59
+ "#{required ? '' : '?'}#{underscore(member_name)}: #{ref_value(member_ref, i + more_indent, visited)},"
60
+ else
61
+ "#{underscore(member_name)}: #{ref_value(member_ref, i + more_indent, visited)}#{required ? '' : '?'},"
62
+ end
63
+ end
64
+
65
+ def ref_value(ref, i, visited)
66
+ if visited.include?(ref['shape'])
67
+ return "untyped"
68
+ else
69
+ visited = visited + [ref['shape']]
70
+ end
71
+
72
+ s = shape(ref)
73
+ case s['type']
74
+ when 'structure'
75
+ if ref['shape'] == 'AttributeValue'
76
+ 'untyped'
77
+ else
78
+ struct(s, i, visited)
79
+ end
80
+ when 'blob'
81
+ if ref['streaming']
82
+ "::String | ::StringIO | ::File" # input only
83
+ else
84
+ "::String"
85
+ end
86
+ when 'list' then list(s, i, visited)
87
+ when 'map' then map(s, i, visited)
88
+ when 'boolean' then "bool"
89
+ when 'integer', 'long' then '::Integer'
90
+ when 'float', 'double' then '::Float'
91
+ when 'byte' then '::Integer'
92
+ when 'character' then '::String'
93
+ when 'string' then string(ref)
94
+ when 'timestamp' then '::Time'
95
+ else raise "unsupported shape #{s['type'].inspect}"
96
+ end
97
+ end
98
+
99
+ def list(list_shape, i, visited)
100
+ member_ref = list_shape['member']
101
+ if complex?(member_ref)
102
+ complex_list(member_ref, i, visited)
103
+ else
104
+ scalar_list(member_ref, i, visited)
105
+ end
106
+ end
107
+
108
+ def scalar_list(member_ref, i, visited)
109
+ "Array[#{ref_value(member_ref, i, visited)}]"
110
+ end
111
+
112
+ def complex_list(member_ref, i, visited)
113
+ newline_indent = newline ? "\n#{i}" : ""
114
+ "Array[#{newline_indent}#{more_indent}#{ref_value(member_ref, i + more_indent, visited)},#{newline_indent}]"
115
+ end
116
+
117
+ def complex?(ref)
118
+ s = shape(ref)
119
+ if s['type'] == 'structure'
120
+ !ddb_av?(ref)
121
+ else
122
+ s['type'] == 'list' || s['type'] == 'map'
123
+ end
124
+ end
125
+
126
+ def ddb_av?(ref)
127
+ s = shape(ref)
128
+ case s['type']
129
+ when 'list' then ddb_av?(s['member'])
130
+ when 'structure' then ref['shape'] == 'AttributeValue'
131
+ else false
132
+ end
133
+ end
134
+
135
+ def map(map_shape, i, visited)
136
+ key = string(map_shape['key'])
137
+ value = ref_value(map_shape['value'], i + more_indent, visited)
138
+ "Hash[#{key}, #{value}]"
139
+ end
140
+
141
+ def string(ref)
142
+ string_shape = shape(ref)
143
+ if string_shape['enum']
144
+ "(#{string_shape['enum'].map { |s| "\"#{s}\"" }.join(" | ")})"
145
+ else ref['shape']
146
+ "::String"
147
+ end
148
+ end
149
+
150
+ def more_indent
151
+ newline ? " " : ""
152
+ end
153
+
154
+ def joint
155
+ newline ? "\n" : " "
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class MethodSignature < Struct.new(:method_name, :overloads, keyword_init: true)
6
+ def signature
7
+ "def #{method_name}: #{overloads.join("\n #{" " * method_name.length}| ")}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class ResourceAction
6
+ class << self
7
+ def build_method_signature_list(resource:, api:)
8
+ (resource["actions"] || []).map do |action_name, action|
9
+ new(action_name: action_name, action: action, api: api).build_method_signature
10
+ end
11
+ end
12
+ end
13
+
14
+ def initialize(action_name:, action:, api:)
15
+ request = action["request"]
16
+ operation = api["operations"][request["operation"]]
17
+ returns = if action["resource"]
18
+ resource = action["resource"]
19
+ AwsSdkCodeGenerator::Api.plural?(resource) ? "#{resource["type"]}::Collection" : resource["type"]
20
+ elsif operation["output"]
21
+ "Types::#{operation["output"]["shape"]}"
22
+ else
23
+ "::Aws::EmptyStructure"
24
+ end
25
+
26
+ @client_request = ResourceClientRequest.new(
27
+ method_name: Underscore.underscore(action_name),
28
+ api: api,
29
+ request: request,
30
+ returns: returns,
31
+ )
32
+ end
33
+
34
+ def build_method_signature
35
+ @client_request.build_method_signature
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class ResourceAssociation
6
+ class << self
7
+ def build_method_signature_list(resource:, api:, paginators:)
8
+ associations = []
9
+ associations += has_associations(resource: resource)
10
+ associations += has_many_associations(resource: resource, api: api, paginators: paginators)
11
+ associations.sort_by(&:method_name)
12
+ end
13
+
14
+ private
15
+
16
+ def has_associations(resource:)
17
+ resource.fetch("has", {}).map do |name, assoc|
18
+ method_name = Underscore.underscore(name)
19
+ arguments = AwsSdkCodeGenerator::ResourceHasAssociation.send(:compute_params, assoc).map { |param|
20
+ "#{param[:type]} #{Underscore.underscore(param[:name])}"
21
+ }.join(', ')
22
+ returns = AwsSdkCodeGenerator::ResourceHasAssociation.send(:return_type, assoc).sub(/, nil$/, "?")
23
+ MethodSignature.new(
24
+ method_name: method_name,
25
+ overloads: ["(#{arguments}) -> #{returns}"]
26
+ )
27
+ end
28
+ end
29
+
30
+ def has_many_associations(resource:, api:, paginators:)
31
+ resource.fetch("hasMany", {}).map do |name, assoc|
32
+ ResourceClientRequest.new(
33
+ method_name: Underscore.underscore(name),
34
+ api: api,
35
+ request: assoc["request"],
36
+ returns: "#{assoc["resource"]["type"]}::Collection",
37
+ skip: AwsSdkCodeGenerator::ResourceHasManyAssociation.send(
38
+ :paging_options,
39
+ {
40
+ assoc: assoc,
41
+ paginators: paginators
42
+ }
43
+ ),
44
+ ).build_method_signature
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class ResourceBatchAction
6
+ class << self
7
+ def build_method_signature_list(resource:, api:)
8
+ resource.fetch("batchActions", {}).map do |name, action|
9
+ new(api: api, name: name, action: action).build_method_signature
10
+ end
11
+ end
12
+ end
13
+
14
+ def initialize(api:, name:, action:)
15
+ @api = api
16
+ @name = name
17
+ @action = action
18
+ @batch_action_documentation = AwsSdkCodeGenerator::ResourceBatchActionDocumentation.new(
19
+ var_name: nil,
20
+ method_name: method_name,
21
+ action: action,
22
+ api: api,
23
+ )
24
+ @skip_params = @batch_action_documentation.send(:skip_params)
25
+ @input_ref = @batch_action_documentation.send(:input_ref)
26
+ @input_shape = AwsSdkCodeGenerator::Api.shape(@input_ref, api)
27
+ end
28
+
29
+ def build_method_signature
30
+ arguments = nil
31
+ include_required = false
32
+
33
+ if @input_shape
34
+ shape = Helper.deep_copy(@input_shape)
35
+ shape.fetch("members").reject! { |member_name, _| @skip_params.include?(member_name) }
36
+ arguments = KeywordArgumentBuilder.new(
37
+ api: @api,
38
+ shape: shape,
39
+ newline: true
40
+ ).format(indent: ' ' * (14 + method_name.length))
41
+ end
42
+
43
+ MethodSignature.new(
44
+ method_name: method_name,
45
+ overloads: [
46
+ "(#{arguments}) -> void",
47
+ "(#{include_required ? "" : "?"}Hash[Symbol, untyped]) -> void",
48
+ ]
49
+ )
50
+ end
51
+
52
+ private
53
+
54
+ def method_name
55
+ AwsSdkCodeGenerator::ResourceBatchAction.send(:build_method_name, @name, @action)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class ResourceClientRequest
6
+ include Helper
7
+
8
+ attr_reader :method_name
9
+ attr_reader :arguments
10
+ attr_reader :returns
11
+ attr_reader :include_required
12
+
13
+ def initialize(method_name:, api:, request:, returns:, skip: [])
14
+ @method_name = method_name
15
+ @returns = returns
16
+ @include_required = false
17
+
18
+ operation = api["operations"][request["operation"]]
19
+ shape_ref = operation["input"]
20
+ input_shape = AwsSdkCodeGenerator::Api.shape(shape_ref, api)
21
+ skip = Set.new(skip + AwsSdkCodeGenerator::ResourceSkipParams.compute(input_shape, request))
22
+ @arguments = if input_shape
23
+ shape = deep_copy(input_shape)
24
+ shape["members"].select! { |member_name, _| !skip.include?(member_name) }
25
+ KeywordArgumentBuilder.new(api: api, shape: shape, newline: true).format(indent: ' ' * (12 + method_name.length))
26
+ end
27
+ end
28
+
29
+ def build_method_signature
30
+ MethodSignature.new(
31
+ method_name: method_name,
32
+ overloads: [
33
+ "(#{arguments}) -> #{returns}",
34
+ "(#{@include_required ? "" : "?"}Hash[Symbol, untyped]) -> #{returns}"
35
+ ]
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class Waiter < Struct.new(
6
+ :name,
7
+ :class_name,
8
+ :client_overload_keyword_argument,
9
+ :client_overload_positional_argument,
10
+ :waiter_overload_keyword_argument,
11
+ :waiter_overload_positional_argument,
12
+ keyword_init: true
13
+ )
14
+ class << self
15
+ def build_list(api:, waiters:)
16
+ operations = api.fetch("operations")
17
+ waiters =
18
+ if waiters&.first
19
+ waiters["waiters"]
20
+ else
21
+ {}
22
+ end
23
+ waiters.map do |waiter_name, waiter|
24
+ operation = waiter.fetch("operation")
25
+ operation_ref = operations[operation]
26
+ input_shape = operation_ref.dig("input", "shape")
27
+ include_required = api["shapes"][input_shape]&.[]("required")&.empty?&.!
28
+
29
+ name = ":#{Underscore.underscore(waiter_name)}"
30
+ shapes = api.fetch("shapes")
31
+ input_shape_ref = shapes[input_shape]
32
+ params = AwsSdkCodeGenerator::RBS::KeywordArgumentBuilder.new(
33
+ api: api,
34
+ shape: input_shape_ref,
35
+ newline: true,
36
+ ).format(indent: ' ' * 18)
37
+ returns = operation_ref.dig("output", "shape") ? "Client::_#{operation}ResponseSuccess" : "::Seahorse::Client::_ResponseSuccess[::Aws::EmptyStructure]"
38
+ prefix = include_required ? "" : "?"
39
+
40
+ new.tap do |w|
41
+ w.name = name
42
+ w.class_name = waiter_name
43
+ w.client_overload_keyword_argument = "(#{name} waiter_name, #{params}) -> #{returns}"
44
+ w.client_overload_positional_argument = "(#{name} waiter_name, #{prefix}Hash[Symbol, untyped] params, ?Hash[Symbol, untyped] options) -> #{returns}"
45
+ w.waiter_overload_keyword_argument = "(#{params}) -> #{returns}"
46
+ w.waiter_overload_positional_argument = "(#{prefix}Hash[Symbol, untyped]) -> #{returns}"
47
+ end
48
+ end.sort_by(&:name)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module RBS
5
+ class << self
6
+ def to_type(shape_ref, api)
7
+ _, shape = Api.resolve(shape_ref, api)
8
+ case shape['type']
9
+ when 'blob' then Api.streaming?(shape_ref, api) ? '::IO' : '::String'
10
+ when 'boolean' then 'bool'
11
+ when 'byte' then '::Integer'
12
+ when 'character' then '::String'
13
+ when 'double' then '::Float'
14
+ when 'float' then '::Float'
15
+ when 'integer' then '::Integer'
16
+ when 'list' then "::Array[#{to_type(shape['member'], api)}]"
17
+ when 'long' then '::Integer'
18
+ when 'map' then "::Hash[#{to_type(shape['key'], api)}, #{to_type(shape['value'], api)}]"
19
+ when 'string'
20
+ if shape['enum']
21
+ "(#{shape['enum'].map { |e| "\"#{e}\"" }.join(" | ")})"
22
+ elsif Api.streaming?(shape_ref, api)
23
+ '::IO'
24
+ else
25
+ '::String'
26
+ end
27
+ when 'structure'
28
+ if shape['document']
29
+ 'untyped'
30
+ else
31
+ "Types::#{shape_ref['shape']}"
32
+ end
33
+ when 'timestamp' then '::Time'
34
+ else
35
+ raise "unhandled type #{shape['type'].inspect}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -15,7 +15,9 @@ module AwsSdkCodeGenerator
15
15
  parts << 'batch_enum.each do |batch|'
16
16
  parts << initialize_params
17
17
  parts << apply_params_per_batch
18
- parts << " batch[0].client.#{client_method}(params)"
18
+ parts << " Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do"
19
+ parts << " batch[0].client.#{client_method}(params)"
20
+ parts << ' end'
19
21
  parts << 'end'
20
22
  parts << 'nil'
21
23
  parts.join("\n").rstrip
@@ -15,9 +15,11 @@ module AwsSdkCodeGenerator
15
15
  parts = []
16
16
  parts << request_options(params) if merge
17
17
  parts << assignment(options)
18
- parts << "@client."
18
+ parts << "Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do\n"
19
+ parts << " @client."
19
20
  parts << operation_name(request)
20
21
  parts << arguments(merge, params, streaming)
22
+ parts << "\nend"
21
23
  parts.join
22
24
  end
23
25
 
@@ -52,11 +52,12 @@ module AwsSdkCodeGenerator
52
52
  args = ResourceClientRequestParams.new(
53
53
  params: waiter['params']
54
54
  ).to_s.strip
55
- if waiter['path']
56
- "resp = waiter.wait(params.merge(#{args}))"
57
- else
58
- "waiter.wait(params.merge(#{args}))"
59
- end
55
+ parts = []
56
+ parts << 'resp = ' if waiter['path']
57
+ parts << "Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do\n"
58
+ parts << " waiter.wait(params.merge(#{args}))"
59
+ parts << "\nend"
60
+ parts.join
60
61
  end
61
62
 
62
63
  def constructor_args(resource, waiter)
@@ -2,12 +2,26 @@
2
2
 
3
3
  module AwsSdkCodeGenerator
4
4
  class Service
5
+ # Ordered priority list of supported protocols
6
+ # api-gateway is a special case and is always first.
7
+ SUPPORTED_PROTOCOLS = %w[
8
+ api-gateway
9
+ smithy-rpc-v2-cbor
10
+ json_1.0
11
+ json_1.1
12
+ rest-json
13
+ rest-xml
14
+ query
15
+ ec2
16
+ ]
5
17
 
6
18
  # @param [Hash] options
7
- # @option options [required, String] :gem_version Gem version, e.g. "1.0.0".
8
19
  # @option options [required, String] :name The service name, e.g. "S3"
9
20
  # @option options [String] :module_name The service module name, defaults
10
21
  # to "Aws::#{name}", e.g. "Aws::S3".
22
+ # @option options [String] :gem_name The gem name, defaults to
23
+ # "aws-sdk-#{name}", e.g. "aws-sdk-s3".
24
+ # @option options [required, String] :gem_version Gem version, e.g. "1.0.0".
11
25
  # @option options [required, Hash, String] :api
12
26
  # @option options [Hash, String] :docs
13
27
  # @option options [Hash, String] :paginators
@@ -20,43 +34,50 @@ module AwsSdkCodeGenerator
20
34
  # @option options [Hash<gem,version>] :gem_dependencies ({})
21
35
  # @option options [Hash] :add_plugins ({})
22
36
  # @option options [Hash] :remove_plugins ([])
37
+ # @option options [Boolean] :deprecated (false)
38
+ # @option options [String] :default_endpoint (nil)
39
+ # @option options [String] :endpoints_key (nil)
23
40
  def initialize(options)
24
41
  @name = options.fetch(:name)
25
42
  @identifier = name.downcase
26
43
  @module_name = options[:module_name] || "Aws::#{name}"
27
44
  @gem_name = options[:gem_name] || "aws-sdk-#{identifier}"
28
45
  @gem_version = options.fetch(:gem_version)
46
+
29
47
  @api = load_json(options.fetch(:api))
30
- unless @api['metadata']['protocol'] == 'api-gateway'
31
- # Dont reply on API Gateway doc.json
48
+
49
+ # computed attributes
50
+ metadata = @api.fetch('metadata')
51
+ @protocol = select_protocol(metadata)
52
+ @protocol_settings = metadata['protocolSettings'] || {}
53
+ @api_version = metadata['apiVersion']
54
+ @signature_version = metadata['signatureVersion']
55
+ @auth = api.fetch('metadata')['auth']
56
+ @full_name = metadata['serviceFullName']
57
+ @short_name = metadata['serviceAbbreviation'] || @full_name
58
+
59
+ # Dont reply on API Gateway doc.json
60
+ unless @protocol == 'api-gateway'
32
61
  ApplyDocs.new(@api).apply(load_json(options[:docs]))
33
62
  end
34
63
  @paginators = load_json(options[:paginators])
35
64
  @waiters = load_json(options[:waiters])
36
65
  @resources = load_json(options[:resources])
37
66
  @examples = load_json(options[:examples])
38
- @smoke_tests = load_json(options[:smoke_tests])
39
67
  unless options[:legacy_endpoints]
40
68
  @endpoint_rules = load_json(options[:endpoint_rules])
41
69
  @endpoint_tests = load_json(options[:endpoint_tests])
42
70
  end
71
+ @smoke_tests = load_json(options[:smoke_tests])
72
+
43
73
  @gem_dependencies = options[:gem_dependencies] || {}
44
74
  @add_plugins = options[:add_plugins] || {}
45
75
  @remove_plugins = options[:remove_plugins] || []
76
+ @deprecated = options[:deprecated] || false
77
+ @default_endpoint = options[:default_endpoint] # APIG custom service only
46
78
  @endpoints_key = options.fetch(:endpoints_key, nil)
47
- # APIG custom service only
48
- @default_endpoint = options[:default_endpoint]
49
79
 
50
- # computed attributes
51
- @protocol = api.fetch('metadata').fetch('protocol')
52
- @protocol_settings = api.fetch('metadata')['protocolSettings'] || {}
53
- @api_version = api.fetch('metadata')['apiVersion']
54
- @signature_version = api.fetch('metadata')['signatureVersion']
55
- @full_name = api.fetch('metadata')['serviceFullName']
56
- @short_name = api.fetch('metadata')['serviceAbbreviation'] || @full_name
57
- @require_endpoint_discovery = api.fetch('operations', []).any? do |_, o|
58
- o['endpointdiscovery'] && o['endpointdiscovery']['required']
59
- end
80
+ @require_endpoint_discovery = endpoint_discovery_required?
60
81
  end
61
82
 
62
83
  # @return [String] The service name, e.g. "S3"
@@ -127,6 +148,9 @@ module AwsSdkCodeGenerator
127
148
  # @return [String] The service protocol, e.g. "json", "query", etc.
128
149
  attr_reader :protocol
129
150
 
151
+ # @return [Array<String>] The list of supported protocols
152
+ attr_reader :protocols
153
+
130
154
  # @return [Hash] The service protocol settings
131
155
  attr_reader :protocol_settings
132
156
 
@@ -136,6 +160,9 @@ module AwsSdkCodeGenerator
136
160
  # @return [String] The signature version, e.g. "v4"
137
161
  attr_reader :signature_version
138
162
 
163
+ # @return [Array<String>] A list of supported auth types
164
+ attr_reader :auth
165
+
139
166
  # @return [String] The full product name for the service,
140
167
  # e.g. "Amazon Simple Storage Service".
141
168
  attr_reader :full_name
@@ -146,6 +173,25 @@ module AwsSdkCodeGenerator
146
173
  # @return [Boolean] true if any operation requires endpoint_discovery
147
174
  attr_reader :require_endpoint_discovery
148
175
 
176
+ # @return [String] the service_id
177
+ def service_id
178
+ metadata = @api['metadata']
179
+ return metadata['serviceId'] if metadata['serviceId']
180
+
181
+ name = metadata['serviceAbbreviation'] || metadata['serviceFullName']
182
+ name = name.gsub(/AWS/, '').gsub(/Amazon/, '')
183
+ name = name.gsub(/[^a-zA-Z0-9 ]+/, '')
184
+ name = name.gsub(/^[0-9]+/, '')
185
+ name = name.strip
186
+
187
+ name
188
+ end
189
+
190
+ # @return [Boolean] true if the service is deprecated
191
+ def deprecated?
192
+ @deprecated
193
+ end
194
+
149
195
  # @api private
150
196
  def inspect
151
197
  "#<#{self.class.name}>"
@@ -153,6 +199,29 @@ module AwsSdkCodeGenerator
153
199
 
154
200
  private
155
201
 
202
+ def select_protocol(metadata)
203
+ protocols = metadata.fetch('protocols', [metadata['protocol']])
204
+ protocol = SUPPORTED_PROTOCOLS.find do |supported_protocol|
205
+ if %w[json_1.0 json_1.1].include?(supported_protocol)
206
+ supported_protocol, version = supported_protocol.split('_')
207
+ end
208
+
209
+ if protocols.include?(supported_protocol) &&
210
+ (version.nil? || version == metadata['jsonVersion'])
211
+ return supported_protocol
212
+ end
213
+ end
214
+ return protocol if protocol
215
+
216
+ raise "unsupported protocols `#{protocols.join(', ')}'"
217
+ end
218
+
219
+ def endpoint_discovery_required?
220
+ @api.fetch('operations', []).any? do |_, o|
221
+ o['endpointdiscovery'] && o['endpointdiscovery']['required']
222
+ end
223
+ end
224
+
156
225
  def load_json(value)
157
226
  case value
158
227
  when nil then nil
@@ -24,10 +24,14 @@ module AwsSdkCodeGenerator
24
24
  @gem_version = options.fetch(:gem_version)
25
25
  @plugins = PluginList.new(options)
26
26
  @codegenerated_plugins = options.fetch(:codegenerated_plugins, [])
27
+ @default_plugins = Seahorse::Client::AsyncBase.plugins.map do |plugin|
28
+ PluginList::Plugin.new(class_name: plugin.name, options: plugin.options, path: '')
29
+ end
27
30
  @client_constructor = ClientConstructor.new(
28
31
  options.merge(
29
32
  plugins: @plugins,
30
- codegenerated_plugins: @codegenerated_plugins))
33
+ codegenerated_plugins: @codegenerated_plugins,
34
+ default_plugins: @default_plugins))
31
35
  @operations = ClientOperationList.new(options).to_a
32
36
  end
33
37