aws-sdk-resources 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
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: