aws-sdk-code-generator 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/lib/aws-sdk-code-generator.rb +91 -0
  3. data/lib/aws-sdk-code-generator/apply_docs.rb +37 -0
  4. data/lib/aws-sdk-code-generator/code_builder.rb +201 -0
  5. data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +23 -0
  6. data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +43 -0
  7. data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +11 -0
  8. data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +11 -0
  9. data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +15 -0
  10. data/lib/aws-sdk-code-generator/dsl/block_param.rb +11 -0
  11. data/lib/aws-sdk-code-generator/dsl/class.rb +27 -0
  12. data/lib/aws-sdk-code-generator/dsl/code_literal.rb +66 -0
  13. data/lib/aws-sdk-code-generator/dsl/code_object.rb +33 -0
  14. data/lib/aws-sdk-code-generator/dsl/docstring.rb +36 -0
  15. data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +15 -0
  16. data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +12 -0
  17. data/lib/aws-sdk-code-generator/dsl/formatter.rb +25 -0
  18. data/lib/aws-sdk-code-generator/dsl/include_statement.rb +17 -0
  19. data/lib/aws-sdk-code-generator/dsl/main.rb +105 -0
  20. data/lib/aws-sdk-code-generator/dsl/method.rb +108 -0
  21. data/lib/aws-sdk-code-generator/dsl/module.rb +167 -0
  22. data/lib/aws-sdk-code-generator/dsl/option_tag.rb +36 -0
  23. data/lib/aws-sdk-code-generator/dsl/param.rb +43 -0
  24. data/lib/aws-sdk-code-generator/dsl/param_list.rb +38 -0
  25. data/lib/aws-sdk-code-generator/dsl/return_tag.rb +19 -0
  26. data/lib/aws-sdk-code-generator/dsl/tag_default.rb +20 -0
  27. data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +27 -0
  28. data/lib/aws-sdk-code-generator/dsl/tag_type.rb +18 -0
  29. data/lib/aws-sdk-code-generator/errors.rb +30 -0
  30. data/lib/aws-sdk-code-generator/gem_builder.rb +71 -0
  31. data/lib/aws-sdk-code-generator/generators/client_api_module.rb +334 -0
  32. data/lib/aws-sdk-code-generator/generators/client_class.rb +389 -0
  33. data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +166 -0
  34. data/lib/aws-sdk-code-generator/generators/errors_module.rb +25 -0
  35. data/lib/aws-sdk-code-generator/generators/resource/action.rb +88 -0
  36. data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +211 -0
  37. data/lib/aws-sdk-code-generator/generators/resource/builder.rb +50 -0
  38. data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +15 -0
  39. data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +49 -0
  40. data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +97 -0
  41. data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +88 -0
  42. data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +180 -0
  43. data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +24 -0
  44. data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +18 -0
  45. data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +49 -0
  46. data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +29 -0
  47. data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +32 -0
  48. data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +101 -0
  49. data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +108 -0
  50. data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +26 -0
  51. data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +28 -0
  52. data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +67 -0
  53. data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +65 -0
  54. data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +68 -0
  55. data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +61 -0
  56. data/lib/aws-sdk-code-generator/generators/resource_class.rb +325 -0
  57. data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +83 -0
  58. data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +42 -0
  59. data/lib/aws-sdk-code-generator/generators/service_documentation.rb +64 -0
  60. data/lib/aws-sdk-code-generator/generators/shared_example.rb +132 -0
  61. data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +95 -0
  62. data/lib/aws-sdk-code-generator/generators/syntax_example.rb +169 -0
  63. data/lib/aws-sdk-code-generator/generators/types_module.rb +52 -0
  64. data/lib/aws-sdk-code-generator/generators/waiter_class.rb +62 -0
  65. data/lib/aws-sdk-code-generator/generators/waiters_module.rb +20 -0
  66. data/lib/aws-sdk-code-generator/hash_formatter.rb +122 -0
  67. data/lib/aws-sdk-code-generator/helper.rb +215 -0
  68. data/lib/aws-sdk-code-generator/service.rb +126 -0
  69. data/lib/aws-sdk-code-generator/underscore.rb +45 -0
  70. data/lib/aws-sdk-code-generator/view.rb +23 -0
  71. data/lib/aws-sdk-code-generator/views.rb +3 -0
  72. data/lib/aws-sdk-code-generator/views/features/env.rb +24 -0
  73. data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +20 -0
  74. data/lib/aws-sdk-code-generator/views/gemspec.rb +41 -0
  75. data/lib/aws-sdk-code-generator/views/service_module.rb +85 -0
  76. data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +24 -0
  77. data/lib/aws-sdk-code-generator/views/version.rb +16 -0
  78. metadata +120 -0
@@ -0,0 +1,65 @@
1
+ module AwsSdkCodeGenerator
2
+ module Generators
3
+ module Resource
4
+ class LoadMethod < Dsl::Method
5
+
6
+ LOAD_NOT_IMPLEMENTED =
7
+ "#load is not implemented, data only available via enumeration"
8
+
9
+ # @option options [required, String] :resource_name
10
+ # @option options [required, Hash] :definition
11
+ def initialize(options = {})
12
+ @resource_name = options.fetch(:resource_name)
13
+ @load = options.fetch(:definition)
14
+ super('load')
15
+ alias_as('reload')
16
+ if @load
17
+ docstring(load_docstring)
18
+ code do |c|
19
+ c << client_request
20
+ c << "@data = resp.#{load_path}"
21
+ c << "self"
22
+ end
23
+ else
24
+ docstring('@raise [Errors::ResourceNotLoadable]')
25
+ docstring('@api private')
26
+ code do |c|
27
+ c << "msg = #{LOAD_NOT_IMPLEMENTED.inspect}"
28
+ c << "raise Errors::ResourceNotLoadable, msg"
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def client_request
36
+ ClientRequest.new(request: @load['request'], resp: true, merge: false)
37
+ end
38
+
39
+ def load_path
40
+ if @load['path'] == '@'
41
+ 'data'
42
+ else
43
+ @load['path'].downcase
44
+ end
45
+ end
46
+
47
+ def operation_name
48
+ underscore(@load['request']['operation'])
49
+ end
50
+
51
+ def load_docstring
52
+ <<-MARKDOWN
53
+ Loads, or reloads {#data} for the current {#{@resource_name}}.
54
+ Returns `self` making it possible to chain methods.
55
+
56
+ #{underscore(@resource_name)}.reload.data
57
+
58
+ @return [self]
59
+ MARKDOWN
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,68 @@
1
+ module AwsSdkCodeGenerator
2
+ module Generators
3
+ module Resource
4
+ class ValueSource < String
5
+
6
+ def initialize(value)
7
+ super(send("param_#{underscore(value['source'])}", value))
8
+ end
9
+
10
+ private
11
+
12
+ def param_identifier(param)
13
+ "@" + underscore(param['name'])
14
+ end
15
+
16
+ def param_data(param)
17
+ path = param['path']
18
+ if path == '@'
19
+ 'data'
20
+ elsif path.match(/^(\w(\[0\])?)+(\.\w+)*$/)
21
+ 'data.' + underscore_path(path)
22
+ else
23
+ raise "unsupported path: #{path.inspect}"
24
+ end
25
+ end
26
+
27
+ def param_response(param)
28
+ if param['path'] == '@'
29
+ 'resp.data'
30
+ else
31
+ 'resp.data.' + underscore_path(param['path'])
32
+ end
33
+ end
34
+
35
+ def param_request_parameter(param)
36
+ if param['path'].match(/^\w+(\.\w+)*$/)
37
+ "options" + path_parts(param['path']).map { |part| "[:#{part}]" }.join
38
+ else
39
+ raise "unsupported path expression: #{param['path']}"
40
+ end
41
+ end
42
+
43
+ def param_string(param)
44
+ param['value'].inspect
45
+ end
46
+ alias param_integer param_string
47
+ alias param_boolean param_string
48
+
49
+ def param_input(param)
50
+ underscore(param['target'])
51
+ end
52
+
53
+ def underscore(str)
54
+ Underscore.underscore(str)
55
+ end
56
+
57
+ def underscore_path(path)
58
+ path.gsub(/\w+/) { |part| underscore(part) }
59
+ end
60
+
61
+ def path_parts(path)
62
+ path.split('.').map { |part| underscore(part) }
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,61 @@
1
+ module AwsSdkCodeGenerator
2
+ module Generators
3
+ module Resource
4
+ class WaiterMethod < Dsl::Method
5
+
6
+ # @option options [required, String] :resource_name
7
+ # @option options [required, Hash] :resource
8
+ # @option options [required, String] :resource_waiter_name
9
+ # @option options [required, Hash] :resource_waiter
10
+ # @option options [required, Hash] :waiter
11
+ def initialize(options)
12
+ resource_name = options.fetch(:resource_name)
13
+ @resource = options.fetch(:resource)
14
+ @resource_waiter = options.fetch(:resource_waiter)
15
+ @waiter_name = @resource_waiter['waiterName']
16
+ waiter = options.fetch(:waiter)
17
+ super("wait_until_#{underscore(options.fetch(:resource_waiter_name))}")
18
+ param('options', type: 'Hash', default:{})
19
+ option(name: 'max_attempts', type:Integer, default: waiter['maxAttempts'])
20
+ option(name: 'delay', type:Float, default: waiter['delay'])
21
+ option(name: 'before_attempt', type:Proc)
22
+ option(name: 'before_wait', type:Proc)
23
+
24
+ returns(resource_name)
25
+
26
+ resp = @resource_waiter['path'] ? 'resp = ' : ''
27
+ code(<<-CODE)
28
+ options, params = separate_params_and_options(options)
29
+ waiter = Waiters::#{@waiter_name}.new(options)
30
+ yield_waiter_and_warn(waiter, &Proc.new) if block_given?
31
+ #{resp}waiter.wait(params.merge(#{args}))
32
+ #{resource_name}.new(#{constructor_args})
33
+ CODE
34
+ end
35
+
36
+ private
37
+
38
+ def args
39
+ ClientRequestParams.new(params: @resource_waiter['params']).to_s.strip
40
+ end
41
+
42
+ def constructor_args
43
+ args = {}
44
+ (@resource['identifiers'] || []).each do |i|
45
+ name = underscore(i['name']).to_sym
46
+ args[name] = "@#{name}"
47
+ end
48
+ if @resource_waiter['path']
49
+ args[:data] = ValueSource.new(
50
+ 'source' => 'response',
51
+ 'path' => @resource_waiter['path']
52
+ )
53
+ end
54
+ args[:client] = '@client'
55
+ HashFormatter.new.format(args)
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,325 @@
1
+ require 'set'
2
+
3
+ module AwsSdkCodeGenerator
4
+ module Generators
5
+ class ResourceClass < Dsl::Class
6
+
7
+ extend Helper
8
+
9
+ # @option options [required, String] :name
10
+ # @option options [required, Hash] :resource
11
+ # @option options [required, Hash] :api
12
+ # @option options [Hash] :paginators
13
+ # @option options [Hash] :waiters
14
+ # @option options [String] :var_name (underscore(name))
15
+ def initialize(options)
16
+ @api = options.fetch(:api)
17
+ @name = options.fetch(:name)
18
+ @resource = options.fetch(:resource)
19
+ @paginators = options.fetch(:paginators, nil)
20
+ @waiters = options.fetch(:waiters, nil)
21
+ @var_name = options.fetch(:var_name, underscore(@name))
22
+ super(@name)
23
+ build
24
+ check_for_method_name_conflicts!
25
+ end
26
+
27
+ private
28
+
29
+ def build
30
+ extend_module('Aws::Deprecations')
31
+ add(initialize_method)
32
+ code('# @!group Read-Only Attributes')
33
+ add(*identifier_getters)
34
+ add(*data_attribute_getters)
35
+ code('# @!endgroup')
36
+ add(client_getter)
37
+ add(load_method)
38
+ add(data_method)
39
+ add(data_loaded_method)
40
+ add(exists_method)
41
+ add(*waiters)
42
+ apply_actions
43
+ apply_associations
44
+ add(identifiers_method)
45
+ add(*private_methods)
46
+ add(batch_action)
47
+ end
48
+
49
+ def initialize_method
50
+ Generators::Resource::InitializeMethod.new(resource: @resource)
51
+ end
52
+
53
+ def identifier_getters
54
+ identifiers.map do |i|
55
+ Generators::Resource::IdentifierGetter.new(identifier: i)
56
+ end
57
+ end
58
+
59
+ def data_attribute_getters
60
+ data_attribute_names.map do |member_name, member_ref|
61
+ Generators::Resource::DataAttributeGetter.new(
62
+ api: @api,
63
+ member_name: member_name,
64
+ member_ref: member_ref
65
+ )
66
+ end
67
+ end
68
+
69
+ def client_getter
70
+ Generators::Resource::ClientGetter.new
71
+ end
72
+
73
+ def load_method
74
+ Generators::Resource::LoadMethod.new(
75
+ resource_name: @name,
76
+ definition: @resource['load']
77
+ )
78
+ end
79
+
80
+ def data_method
81
+ Generators::Resource::DataMethod.new(
82
+ resource_name: @name,
83
+ resource: @resource
84
+ )
85
+ end
86
+
87
+ def data_loaded_method
88
+ Generators::Resource::DataLoadedMethod.new
89
+ end
90
+
91
+ def exists_method
92
+ if @resource['waiters'] && @resource['waiters']['Exists']
93
+ Generators::Resource::ExistsMethod.new(
94
+ resource_name: @name,
95
+ resource: @resource,
96
+ waiters: @waiters,
97
+ )
98
+ end
99
+ end
100
+
101
+ def waiters
102
+ (@resource['waiters'] || {}).map do |waiter_name, waiter|
103
+ Generators::Resource::WaiterMethod.new(
104
+ resource_name: @name,
105
+ resource: @resource,
106
+ resource_waiter_name: waiter_name,
107
+ resource_waiter: waiter,
108
+ waiter: @waiters['waiters'][waiter['waiterName']]
109
+ )
110
+ end
111
+ end
112
+
113
+ def apply_actions
114
+ actions = @resource['actions'] || {}
115
+ return if actions.empty?
116
+ code('# @!group Actions')
117
+ actions.each do |name, action|
118
+ add(Resource::Action.new(
119
+ api: @api,
120
+ name: name,
121
+ action: action,
122
+ var_name: @var_name,
123
+ ))
124
+ end
125
+ end
126
+
127
+ def apply_associations
128
+ associations = []
129
+ associations += has_associations
130
+ associations += has_many_associations
131
+
132
+ return if associations.empty?
133
+
134
+ code('# @!group Associations')
135
+ associations.sort_by(&:name).each do |association_method|
136
+ add(association_method)
137
+ end
138
+ end
139
+
140
+ def has_associations
141
+ (@resource['has'] || {}).map do |name, has|
142
+ Resource::HasAssociation.new(
143
+ api: @api,
144
+ name: name,
145
+ has: has
146
+ )
147
+ end
148
+ end
149
+
150
+ def has_many_associations
151
+ (@resource['hasMany'] || {}).map do |name, has_many|
152
+ Resource::HasManyAssociation.new(
153
+ name: name,
154
+ has_many: has_many,
155
+ api: @api,
156
+ paginators: @paginators,
157
+ var_name: @var_name,
158
+ )
159
+ end
160
+ end
161
+
162
+ def batch_action
163
+ Generators::Resource::CollectionClass.new(
164
+ resource_name: @name,
165
+ resource: @resource,
166
+ api: @api,
167
+ )
168
+ end
169
+
170
+ def identifiers_method
171
+ Generators::Resource::IdentifiersMethod.new(
172
+ identifiers: identifiers
173
+ )
174
+ end
175
+
176
+ def private_methods
177
+ methods = []
178
+ methods.concat(extract_identifier_methods)
179
+ methods << yield_waiter_and_warn_method
180
+ methods << separate_params_and_options
181
+ methods.compact
182
+ end
183
+
184
+ def extract_identifier_methods
185
+ identifiers.map.with_index do |identifier, n|
186
+ Generators::Resource::ExtractIdentifierMethod.new(
187
+ identifier: identifier,
188
+ index: n
189
+ )
190
+ end
191
+ end
192
+
193
+ def identifiers
194
+ @resource['identifiers'] || []
195
+ end
196
+
197
+ def data_attribute_names
198
+
199
+ skip = Set.new
200
+
201
+ # do no duplicate identifiers
202
+ identifiers.each do |i|
203
+ skip << i['name']
204
+ skip << i['memberName'] if i.key?('memberName')
205
+ end
206
+
207
+ # do no duplicate action names
208
+ (@resource['actions'] || {}).keys.each do |action_name|
209
+ skip << action_name
210
+ end
211
+
212
+ # do no duplicate has association names
213
+ (@resource['has'] || {}).keys.each do |association_name|
214
+ skip << association_name
215
+ end
216
+
217
+ # do no duplicate hasMany association names
218
+ (@resource['hasMany'] || {}).keys.each do |association_name|
219
+ skip << association_name
220
+ end
221
+
222
+ shape = (@api['shapes'] || {})[@resource['shape']] || {}
223
+ members = shape['members'] || {}
224
+ Enumerator.new do |y|
225
+ members.each do |member_name, member_ref|
226
+ unless skip.include?(member_name)
227
+ y.yield(member_name, member_ref)
228
+ end
229
+ end
230
+ end
231
+ end
232
+
233
+ def check_for_method_name_conflicts!
234
+
235
+ names = Set.new
236
+
237
+ # Ensure the resource does not have duplicate names. This
238
+ # includes comparing identifier names, action names, association
239
+ # names, e.g. anything that is exposed as a method.
240
+ @code_objects.each do |code_obj|
241
+ if Dsl::Method === code_obj || Dsl::AttributeAccessor === code_obj
242
+ check_for_duplicate_method!(code_obj.name, names)
243
+ end
244
+ end
245
+
246
+ # It is possible for Dsl::Method#aliases to collide with
247
+ # code object names. Remove aliases that collide.
248
+ @code_objects.each do |code_obj|
249
+ if Dsl::Method === code_obj
250
+ code_obj.aliases.each do |alias_name|
251
+ if names.include?(alias_name.to_s)
252
+ code_obj.aliases.delete(alias_name.to_s)
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ # Compare all resource methods against methods defined
259
+ # on Ruby's Object class as an instance method. We need to
260
+ # ensure we do not clobber built in Ruby functionality.
261
+ Object.instance_methods.each do |obj_method_name|
262
+ if names.include?(obj_method_name.to_s)
263
+ raise Errors::ResourceMethodConflict.new(
264
+ resource_name: @name,
265
+ method_name: obj_method_name
266
+ )
267
+ end
268
+ end
269
+ end
270
+
271
+ def check_for_duplicate_method!(method_name, names)
272
+ method_name = method_name.to_s
273
+ if names.include?(method_name)
274
+ raise Errors::ResourceMethodConflict.new(
275
+ resource_name: @name,
276
+ method_name: method_name
277
+ )
278
+ else
279
+ names << method_name
280
+ end
281
+ end
282
+
283
+ def yield_waiter_and_warn_method
284
+ if @resource['waiters'] && @resource['waiters'].size > 0
285
+ Dsl::Method.new(:yield_waiter_and_warn, access: :private) do |m|
286
+ m.param(:waiter)
287
+ m.block_param
288
+ m.code(<<-CODE)
289
+ if !@waiter_block_warned
290
+ msg = "pass options to configure the waiter; "
291
+ msg << "yielding the waiter is deprecated"
292
+ warn(msg)
293
+ @waiter_block_warned = true
294
+ end
295
+ yield(waiter.waiter)
296
+ CODE
297
+ end
298
+ end
299
+ end
300
+
301
+ def separate_params_and_options
302
+ if @resource['waiters'] && @resource['waiters'].size > 0
303
+ Dsl::Method.new(:separate_params_and_options, access: :private) do |m|
304
+ m.param(:options)
305
+ m.code(<<-CODE)
306
+ opts = Set.new([:client, :max_attempts, :delay, :before_attempt, :before_wait])
307
+ waiter_opts = {}
308
+ waiter_params = {}
309
+ options.each_pair do |key, value|
310
+ if opts.include?(key)
311
+ waiter_opts[key] = value
312
+ else
313
+ waiter_params[key] = value
314
+ end
315
+ end
316
+ waiter_opts[:client] ||= @client
317
+ [waiter_opts, waiter_params]
318
+ CODE
319
+ end
320
+ end
321
+ end
322
+
323
+ end
324
+ end
325
+ end