aws-sdk-resources 2.0.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 (31) hide show
  1. checksums.yaml +7 -0
  2. data/lib/aws-sdk-resources.rb +36 -0
  3. data/lib/aws-sdk-resources/batch.rb +100 -0
  4. data/lib/aws-sdk-resources/builder.rb +86 -0
  5. data/lib/aws-sdk-resources/builder_sources.rb +136 -0
  6. data/lib/aws-sdk-resources/collection.rb +137 -0
  7. data/lib/aws-sdk-resources/definition.rb +363 -0
  8. data/lib/aws-sdk-resources/documenter.rb +18 -0
  9. data/lib/aws-sdk-resources/documenter/base_operation_documenter.rb +269 -0
  10. data/lib/aws-sdk-resources/documenter/data_operation_documenter.rb +47 -0
  11. data/lib/aws-sdk-resources/documenter/enumerate_data_operation_documenter.rb +50 -0
  12. data/lib/aws-sdk-resources/documenter/enumerate_resource_operation_documenter.rb +69 -0
  13. data/lib/aws-sdk-resources/documenter/operation_documenter.rb +43 -0
  14. data/lib/aws-sdk-resources/documenter/reference_operation_documenter.rb +102 -0
  15. data/lib/aws-sdk-resources/documenter/resource_operation_documenter.rb +65 -0
  16. data/lib/aws-sdk-resources/documenter/waiter_operation_documenter.rb +81 -0
  17. data/lib/aws-sdk-resources/errors.rb +15 -0
  18. data/lib/aws-sdk-resources/operation_methods.rb +53 -0
  19. data/lib/aws-sdk-resources/operations.rb +294 -0
  20. data/lib/aws-sdk-resources/options.rb +23 -0
  21. data/lib/aws-sdk-resources/request.rb +39 -0
  22. data/lib/aws-sdk-resources/request_params.rb +225 -0
  23. data/lib/aws-sdk-resources/resource.rb +137 -0
  24. data/lib/aws-sdk-resources/source.rb +39 -0
  25. data/lib/aws-sdk-resources/validator.rb +152 -0
  26. data/lib/aws-sdk-resources/validator/context.rb +60 -0
  27. data/lib/aws-sdk-resources/validator/identifier_validator.rb +107 -0
  28. data/lib/aws-sdk-resources/validator/operation_validator.rb +352 -0
  29. data/lib/aws-sdk-resources/validator/rule.rb +45 -0
  30. data/lib/aws-sdk-resources/validator/shape_validator.rb +47 -0
  31. metadata +87 -0
@@ -0,0 +1,352 @@
1
+ module Aws
2
+ module Resources
3
+ module Validator
4
+ class OperationValidator
5
+
6
+ PARAM_SOURCES = %w(identifier dataMember string integer boolean)
7
+
8
+ # @param [Validator::Context] context
9
+ def initialize(context)
10
+ @context = context
11
+ @operation = context.value
12
+ @definition = context.definition
13
+ @api = context.api
14
+ @path = context.path
15
+ end
16
+
17
+ # @return [Hash] The service resource definition model.
18
+ attr_reader :definition
19
+
20
+ # @return [Hash] The api model.
21
+ attr_reader :api
22
+
23
+ # @return [String] The JSON path inside the definition document.
24
+ attr_reader :path
25
+
26
+ # @return [Boolean] Returns `true` if the operation defines a request.
27
+ def request_set?
28
+ @operation.key?('request')
29
+ end
30
+
31
+ # @return [Boolean] Returns `true` if the operation defines how to
32
+ # build a resource.
33
+ def resource_set?
34
+ @operation.key?('resource')
35
+ end
36
+
37
+ # @return [Boolean] Returns `true` if the operation defines a path.
38
+ def path_set?
39
+ @operation.key?('path')
40
+ end
41
+
42
+ # Performs generic request validation including:
43
+ # * request is defined
44
+ # * request operation is defined in the api
45
+ # * request params resolve as input parameters
46
+ # * etc.
47
+ # Yields to the given block if the request is defined and exists in
48
+ # the api.
49
+ # @return [Boolean]
50
+ def validate_request(&block)
51
+ if
52
+ validate_request_set &&
53
+ validate_operation_exists
54
+ then
55
+ yield if block_given?
56
+ validate_params
57
+ end
58
+ end
59
+
60
+ # @return [Boolean] Returns `true` if the operation does not define
61
+ # a request. Only hasSome/hasOne references should not have a
62
+ # request defined.
63
+ def validate_request_not_set
64
+ if @operation['request']
65
+ error("'#{path}/request' is not valid in this context.")
66
+ else
67
+ true
68
+ end
69
+ end
70
+
71
+ # @return [Boolean] Returns `true` if the operation does not define
72
+ # how to build a resource. Only load operations may not define
73
+ # a resource.
74
+ def validate_resource_not_set
75
+ if @operation.key?('resource')
76
+ error("'#{path}/resource' is not valid in this context.")
77
+ else
78
+ true
79
+ end
80
+ end
81
+
82
+ # Performs basic validation on the resource definition.
83
+ # @return [Boolean]
84
+ def validate_resource(&block)
85
+ if resource_set?
86
+ validate_resource_exists
87
+ else
88
+ error("'#{path}/resource' must be set.")
89
+ end
90
+ end
91
+
92
+ # @return [Boolean] Returns `true` if the operation defines a path.
93
+ # Load operations require a path.
94
+ def validate_path_set
95
+ if path_set?
96
+ true
97
+ else
98
+ error("'#{path}/path' must be set.")
99
+ end
100
+ end
101
+
102
+ # Validates a path by resolving it against the resource definition
103
+ # and the API model. You must specify the `:origin` and optionally
104
+ # the `:target`.
105
+ #
106
+ # == Origins
107
+ #
108
+ # * :response - Resolves the path starting from the operation output.
109
+ #
110
+ # * :request - Resolves the path starting from the operation input.
111
+ #
112
+ # * :self - Resolves the path starting from the resource data/shape.
113
+ #
114
+ # == Target
115
+ #
116
+ # * :resource - Requires the path to resolve to the shape of the operation
117
+ # resource entry.
118
+ #
119
+ # * :self - Requries the path to resolve to the shape of the
120
+ # current resource.
121
+ #
122
+ # @option options [:response, :request, :self] :origin
123
+ # @option options [:self, :resource] :target
124
+ def validate_path(options = {})
125
+ if path_set?
126
+ validate_path_resolves(options)
127
+ else
128
+ true
129
+ end
130
+ end
131
+
132
+ # @return [Boolean] Returns `true` if the path resolves to an array.
133
+ # Has many operations require plural paths and at least one plural
134
+ # input.
135
+ def validate_path_is_plural
136
+ if @operation['path'].match(/\[/)
137
+ true
138
+ else
139
+ error("'#{path}/path' must be plural.")
140
+ end
141
+ end
142
+
143
+ # @return [Boolean] Returns `true` if none of the request params
144
+ # are for the given `source_type`. Load operations may not use
145
+ # "dataMember" source types.
146
+ def validate_param_source_type_not_used(source_type)
147
+ (@operation['request']['params'] || []).each.with_index do |param, n|
148
+ if param['sourceType'] == source_type
149
+ error("'#{path}/request/params/#{n}/sourceType' is set to '#{source_type}' which is not valid in this context.")
150
+ end
151
+ end
152
+ end
153
+
154
+ private
155
+
156
+ def error(msg)
157
+ @context.error(msg)
158
+ end
159
+
160
+ # @option options [:response, :request, :self] :origin
161
+ # @option options [:self, :response] :target
162
+ def validate_path_resolves(options)
163
+ if origin_exists?(options)
164
+ resolve_path(options)
165
+ else
166
+ error("'#{path}/path' requires that '#{origin_path(options)}' be set.")
167
+ end
168
+ end
169
+
170
+ def validate_resource_exists
171
+ if definition['resources'].key?(operation_resource_name)
172
+ true
173
+ else
174
+ error("'#{path}/resource/type' references '#{operation_resource_name}' which is not defined.")
175
+ end
176
+ end
177
+
178
+ def resolve_path(options)
179
+ if resolved_shape = resolve(@operation['path'], origin(options))
180
+ validate_resolved_shape(resolved_shape, options)
181
+ else
182
+ error("'#{path}/path' does not resolve.")
183
+ end
184
+ end
185
+
186
+ def validate_resolved_shape(resolved_shape, options)
187
+ if options[:target]
188
+ validate_target_exists(options) &&
189
+ validate_resolved_shape_matches(resolved_shape, options)
190
+ else
191
+ true
192
+ end
193
+ end
194
+
195
+ def validate_target_exists(options)
196
+ if target(options)
197
+ true
198
+ else
199
+ error("'#{path}/path' requires that '#/resources/#{target_resource_name(options)}/shape' is set.")
200
+ end
201
+ end
202
+
203
+ def validate_resolved_shape_matches(resolved_shape, options)
204
+ if resolved_shape == target(options)
205
+ true
206
+ else
207
+ error("'#{path}/path' did not resolve to a '#{target(options)}' shape.")
208
+ end
209
+ end
210
+
211
+ def origin(options)
212
+ case options[:origin]
213
+ when :request then api_operation['input']
214
+ when :response then api_operation['output']
215
+ when :self then { 'shape' => resource_shape_name }
216
+ else
217
+ msg = "expected :origin to be one of :output, :input, or :self"
218
+ raise ArgumentError, msg
219
+ end
220
+ end
221
+
222
+ def target_resource_name(options)
223
+ case options[:target]
224
+ when :resource then operation_resource_name
225
+ when :self then resource_name
226
+ else
227
+ raise ArgumentError, "expected `:target` as :resource, or :self"
228
+ end
229
+ end
230
+
231
+ def target(options)
232
+ @definition['resources'][target_resource_name(options)]['shape']
233
+ end
234
+
235
+ def origin_path(options)
236
+ case options[:origin]
237
+ when :request then "api#/operations/#{operation_name}/input"
238
+ when :response then "api#/operations/#{operation_name}/output"
239
+ when :self then raise 'not tested'; "api#/shapes/#{resource_shape_name}"
240
+ else raise "unhandled origin #{options[:origin].inspect}"
241
+ end
242
+ end
243
+
244
+ def origin_exists?(options)
245
+ case options[:origin]
246
+ when :request then !!(api_operation && api_operation['input'])
247
+ when :response then !!(api_operation && api_operation['output'])
248
+ when :self then !!api['shapes'][resource_shape_name]
249
+ else raise "unhandled origin #{options[:origin].inspect}"
250
+ end
251
+ end
252
+
253
+ def operation_resource_name
254
+ @operation['resource']['type']
255
+ end
256
+
257
+ def resolve(jamespath, from)
258
+ ref = jamespath.scan(/\w+|\[.*?\]/).inject(from) do |ref, part|
259
+ shape = api['shapes'][ref['shape']]
260
+ if part[0] == '['
261
+ return nil unless shape['type'] == 'list'
262
+ shape['member']
263
+ else
264
+ return nil unless shape['type'] == 'structure'
265
+ return nil unless shape['members'][part]
266
+ shape['members'][part]
267
+ end
268
+ end
269
+ ref && ref['shape']
270
+ end
271
+
272
+ def validate_request_set
273
+ if @operation['request']
274
+ true
275
+ else
276
+ error("'#{path}/request' is required in this context.")
277
+ end
278
+ end
279
+
280
+ def validate_params
281
+ if params = @operation['request']['params']
282
+ if validate_operation_accepts_input
283
+ params.each.with_index do |param, index|
284
+ validate_request_param(param, index)
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ def validate_operation_accepts_input
291
+ if api_operation['input']
292
+ true
293
+ else
294
+ error("'#{path}/request/params' is set but '#{operation_name}' does not accept input.")
295
+ end
296
+ end
297
+
298
+ def validate_request_param(param, index)
299
+ validate_request_param_target_resolves(param, index)
300
+ validate_static_params_match_coral_type(param, index)
301
+ end
302
+
303
+ def validate_request_param_target_resolves(param, index)
304
+ if resolve(param['target'], api_operation['input'])
305
+ true
306
+ else
307
+ error("'#{path}/request/params/#{index}/target' has the expression '#{param['target']}' which does not resolve from 'api#/operations/#{operation_name}/input'.")
308
+ end
309
+ end
310
+
311
+ def validate_static_params_match_coral_type(param, index)
312
+ if %w(string integer boolean).include?(param['sourceType'])
313
+ resolved_shape = resolve(param['target'], api_operation['input'])
314
+ resolved_type = @api['shapes'][resolved_shape]['type']
315
+ unless param['sourceType'] == resolved_type
316
+ error("'#{path}/request/params/#{index}/sourceType' given as '#{param['sourceType']}' but resolves to a '#{resolved_type}' shape.")
317
+ end
318
+ end
319
+ end
320
+
321
+ def validate_operation_exists
322
+ if api_operation
323
+ true
324
+ else
325
+ error("'#{path}/request/operation' is set but is not defined at 'api#/operations/#{operation_name}'.")
326
+ end
327
+ end
328
+
329
+ def resource_name
330
+ @context.matches[1]
331
+ end
332
+
333
+ def resource
334
+ definition['resources'][resource_name]
335
+ end
336
+
337
+ def resource_shape_name
338
+ resource['shape']
339
+ end
340
+
341
+ def operation_name
342
+ @operation['request']['operation']
343
+ end
344
+
345
+ def api_operation
346
+ api['operations'][operation_name]
347
+ end
348
+
349
+ end
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,45 @@
1
+ module Aws
2
+ module Resources
3
+ module Validator
4
+ # @api private
5
+ class Rule
6
+
7
+ # @param [String] pattern
8
+ def initialize(pattern, &block)
9
+ @pattern = Regexp.new('^' + pattern + '$')
10
+ @block = block
11
+ end
12
+
13
+ # @param [String] path
14
+ # @return [Boolean]
15
+ def applies?(path)
16
+ !!path.match(@pattern)
17
+ end
18
+
19
+ # @param [String] path
20
+ # @return [MatchData]
21
+ def matches(path)
22
+ path.match(@pattern)
23
+ end
24
+
25
+ # @param [String] path
26
+ # @param [Object] value
27
+ # @param [Hash] definition
28
+ # @param [Hash] api
29
+ # @return [Array<String>]
30
+ def validate(path, value, definition, api)
31
+ context = Validator::Context.new(
32
+ path: path,
33
+ value: value,
34
+ definition: definition,
35
+ api: api,
36
+ matches: matches(path),
37
+ )
38
+ @block.call(context)
39
+ context.errors
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ module Aws
2
+ module Resources
3
+ module Validator
4
+ class ShapeValidator
5
+
6
+ # @param [Validator::Context] context
7
+ # @param [String] shape_name
8
+ def initialize(context, shape_name)
9
+ @context = context
10
+ @shape_name = shape_name
11
+ @path = context.path
12
+ end
13
+
14
+ attr_reader :shape_name
15
+
16
+ attr_reader :path
17
+
18
+ def validate
19
+ validate_shape_is_defined && validate_shape_is_a_structure
20
+ end
21
+
22
+ private
23
+
24
+ def validate_shape_is_defined
25
+ if shape
26
+ true
27
+ else
28
+ @context.error("'#{path}' not found at api#/shapes/#{shape_name}.")
29
+ end
30
+ end
31
+
32
+ def validate_shape_is_a_structure
33
+ if shape['type'] == 'structure'
34
+ true
35
+ else
36
+ @context.error("'#{path}' must resolve to a structure shape.")
37
+ end
38
+ end
39
+
40
+ def shape
41
+ @context.api['shapes'][shape_name]
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws-sdk-resources
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Amazon Web Services
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ description: Provides resource-oriented abstractions for AWS.
28
+ email:
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/aws-sdk-resources/batch.rb
34
+ - lib/aws-sdk-resources/builder.rb
35
+ - lib/aws-sdk-resources/builder_sources.rb
36
+ - lib/aws-sdk-resources/collection.rb
37
+ - lib/aws-sdk-resources/definition.rb
38
+ - lib/aws-sdk-resources/documenter/base_operation_documenter.rb
39
+ - lib/aws-sdk-resources/documenter/data_operation_documenter.rb
40
+ - lib/aws-sdk-resources/documenter/enumerate_data_operation_documenter.rb
41
+ - lib/aws-sdk-resources/documenter/enumerate_resource_operation_documenter.rb
42
+ - lib/aws-sdk-resources/documenter/operation_documenter.rb
43
+ - lib/aws-sdk-resources/documenter/reference_operation_documenter.rb
44
+ - lib/aws-sdk-resources/documenter/resource_operation_documenter.rb
45
+ - lib/aws-sdk-resources/documenter/waiter_operation_documenter.rb
46
+ - lib/aws-sdk-resources/documenter.rb
47
+ - lib/aws-sdk-resources/errors.rb
48
+ - lib/aws-sdk-resources/operation_methods.rb
49
+ - lib/aws-sdk-resources/operations.rb
50
+ - lib/aws-sdk-resources/options.rb
51
+ - lib/aws-sdk-resources/request.rb
52
+ - lib/aws-sdk-resources/request_params.rb
53
+ - lib/aws-sdk-resources/resource.rb
54
+ - lib/aws-sdk-resources/source.rb
55
+ - lib/aws-sdk-resources/validator/context.rb
56
+ - lib/aws-sdk-resources/validator/identifier_validator.rb
57
+ - lib/aws-sdk-resources/validator/operation_validator.rb
58
+ - lib/aws-sdk-resources/validator/rule.rb
59
+ - lib/aws-sdk-resources/validator/shape_validator.rb
60
+ - lib/aws-sdk-resources/validator.rb
61
+ - lib/aws-sdk-resources.rb
62
+ homepage: http://github.com/aws/aws-sdk-core-ruby
63
+ licenses:
64
+ - Apache 2.0
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - '>'
78
+ - !ruby/object:Gem::Version
79
+ version: 1.3.1
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.1.11
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: AWS SDK for Ruby - Resources
86
+ test_files: []
87
+ has_rdoc: