aws-sdk-resources 2.0.21.pre → 2.0.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aws-sdk-resources.rb +15 -26
- data/lib/aws-sdk-resources/request.rb +2 -2
- metadata +6 -14
- data/lib/aws-sdk-resources/services/sqs.rb +0 -5
- data/lib/aws-sdk-resources/services/sqs/queue.rb +0 -102
- data/lib/aws-sdk-resources/validator.rb +0 -239
- data/lib/aws-sdk-resources/validator/context.rb +0 -56
- data/lib/aws-sdk-resources/validator/dsl.rb +0 -88
- data/lib/aws-sdk-resources/validator/operation_validator.rb +0 -352
- data/lib/aws-sdk-resources/validator/path_resolver.rb +0 -34
- data/lib/aws-sdk-resources/validator/rule.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 406e521dc5e2fa2e3036612ca85bf81dafb64838
|
4
|
+
data.tar.gz: 220362ebb755c163929c895b3067a75c878284d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b0215e8a68171958a3433faceb54c06ce5a455663931b710b5a2cdc39166ac93357ef41ad9675c7cf33fac39d7e4a4bb1c4597dce9df3dd90de94371e6d0fc7
|
7
|
+
data.tar.gz: b22a0721824c84b24340aa4dce0b24125edd0fdbb38d2342b45a4e85d6cb44c7c10355f58a77cc133c7318e87eacda1d1eb55aea6f2cbbd60ee77fceb49648c4
|
data/lib/aws-sdk-resources.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'aws-sdk-core'
|
2
2
|
|
3
3
|
module Aws
|
4
|
-
module Resources
|
5
4
|
|
5
|
+
module Resources
|
6
6
|
autoload :Batch, 'aws-sdk-resources/batch'
|
7
7
|
autoload :Builder, 'aws-sdk-resources/builder'
|
8
8
|
autoload :BuilderSources, 'aws-sdk-resources/builder_sources'
|
@@ -10,46 +10,35 @@ module Aws
|
|
10
10
|
autoload :Definition, 'aws-sdk-resources/definition'
|
11
11
|
autoload :Documenter, 'aws-sdk-resources/documenter'
|
12
12
|
autoload :Errors, 'aws-sdk-resources/errors'
|
13
|
-
autoload :Operations, 'aws-sdk-resources/operations'
|
14
13
|
autoload :OperationMethods, 'aws-sdk-resources/operation_methods'
|
14
|
+
autoload :Operations, 'aws-sdk-resources/operations'
|
15
15
|
autoload :Options, 'aws-sdk-resources/options'
|
16
16
|
autoload :Request, 'aws-sdk-resources/request'
|
17
17
|
autoload :RequestParams, 'aws-sdk-resources/request_params'
|
18
18
|
autoload :Resource, 'aws-sdk-resources/resource'
|
19
19
|
autoload :Source, 'aws-sdk-resources/source'
|
20
|
-
autoload :Validator, 'aws-sdk-resources/validator'
|
21
|
-
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def define_resource_classes(svc_module, definition)
|
29
|
-
build_definition(definition).apply(svc_module)
|
30
|
-
end
|
31
|
-
|
32
|
-
def build_definition(definition)
|
33
|
-
case definition
|
22
|
+
service_added do |name, svc_module, options|
|
23
|
+
definition = options[:resources]
|
24
|
+
definition = case definition
|
34
25
|
when nil then Resources::Definition.new({})
|
35
26
|
when Resources::Definition then definition
|
36
27
|
when Hash then Resources::Definition.new(definition)
|
37
|
-
when String
|
28
|
+
when String
|
29
|
+
Resources::Definition.new(Aws.load_json(definition), source_path: definition)
|
38
30
|
else raise ArgumentError, "invalid resource definition #{definition}"
|
39
|
-
end
|
40
31
|
end
|
32
|
+
definition.apply(svc_module)
|
41
33
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
34
|
+
# load customizations
|
35
|
+
svc = File.join(
|
36
|
+
File.dirname(__FILE__),
|
37
|
+
'aws-sdk-resources',
|
38
|
+
'services',
|
39
|
+
"#{name.downcase}.rb")
|
49
40
|
|
50
|
-
|
51
|
-
define_resource_classes(svc_module, options[:resources])
|
52
|
-
load_resource_customizations(svc_name)
|
41
|
+
require(svc) if File.exists?(svc)
|
53
42
|
end
|
54
43
|
|
55
44
|
end
|
@@ -2,7 +2,7 @@ module Aws
|
|
2
2
|
module Resources
|
3
3
|
class Request
|
4
4
|
|
5
|
-
# @option
|
5
|
+
# @option options [required, String] :method_name
|
6
6
|
# @option options [Array<RequestParams::Param>] :params ([]) A list of
|
7
7
|
# request params to apply to the request when called.
|
8
8
|
def initialize(options = {})
|
@@ -17,7 +17,7 @@ module Aws
|
|
17
17
|
# @return [Array<RequestParams::Param>]
|
18
18
|
attr_reader :params
|
19
19
|
|
20
|
-
# @option options [required,Resource] :resource
|
20
|
+
# @option options [required, Resource] :resource
|
21
21
|
# @option options [Array<Mixed>] :args
|
22
22
|
# @return [Seahorse::Client::Response]
|
23
23
|
def call(options)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-sdk-resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-core
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.0.
|
19
|
+
version: 2.0.22
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.0.
|
26
|
+
version: 2.0.22
|
27
27
|
description: Provides resource-oriented abstractions for AWS.
|
28
28
|
email:
|
29
29
|
executables: []
|
@@ -76,15 +76,7 @@ files:
|
|
76
76
|
- lib/aws-sdk-resources/services/s3/object.rb
|
77
77
|
- lib/aws-sdk-resources/services/s3/object_summary.rb
|
78
78
|
- lib/aws-sdk-resources/services/s3/public_url.rb
|
79
|
-
- lib/aws-sdk-resources/services/sqs.rb
|
80
|
-
- lib/aws-sdk-resources/services/sqs/queue.rb
|
81
79
|
- lib/aws-sdk-resources/source.rb
|
82
|
-
- lib/aws-sdk-resources/validator.rb
|
83
|
-
- lib/aws-sdk-resources/validator/context.rb
|
84
|
-
- lib/aws-sdk-resources/validator/dsl.rb
|
85
|
-
- lib/aws-sdk-resources/validator/operation_validator.rb
|
86
|
-
- lib/aws-sdk-resources/validator/path_resolver.rb
|
87
|
-
- lib/aws-sdk-resources/validator/rule.rb
|
88
80
|
homepage: http://github.com/aws/aws-sdk-core-ruby
|
89
81
|
licenses:
|
90
82
|
- Apache 2.0
|
@@ -100,9 +92,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
92
|
version: '0'
|
101
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
94
|
requirements:
|
103
|
-
- - "
|
95
|
+
- - ">="
|
104
96
|
- !ruby/object:Gem::Version
|
105
|
-
version:
|
97
|
+
version: '0'
|
106
98
|
requirements: []
|
107
99
|
rubyforge_project:
|
108
100
|
rubygems_version: 2.2.2
|
@@ -1,102 +0,0 @@
|
|
1
|
-
module Aws
|
2
|
-
module SQS
|
3
|
-
class Queue
|
4
|
-
class << self
|
5
|
-
|
6
|
-
private
|
7
|
-
|
8
|
-
def queue_str_attr(method_name, options = {})
|
9
|
-
name = options[:name] || attr_name(method_name)
|
10
|
-
define_method(method_name) do
|
11
|
-
attributes[name]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def queue_int_attr(method_name, options = {})
|
16
|
-
name = options[:name] || attr_name(method_name)
|
17
|
-
define_method(method_name) do
|
18
|
-
if value = attributes[name]
|
19
|
-
value.to_i
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def queue_time_attr(method_name, options = {})
|
25
|
-
name = options[:name] || attr_name(method_name)
|
26
|
-
define_method(method_name) do
|
27
|
-
if value = attributes[name]
|
28
|
-
Time.at(value.to_i)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def attr_name(method_name)
|
34
|
-
method_name.to_s.split('_').map { |s| s[0].upcase + s[1..-1] }.join
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
# @group Queue Attributes
|
40
|
-
# @return [String] the queue's policy.
|
41
|
-
queue_str_attr :policy
|
42
|
-
|
43
|
-
# @group Queue Attributes
|
44
|
-
# @return [Integer] the visibility timeout for the queue. For more information about visibility timeout, see [Visibility Timeout](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html) in the Amazon SQS Developer Guide.
|
45
|
-
queue_int_attr :visibility_timeout
|
46
|
-
|
47
|
-
# @group Queue Attributes
|
48
|
-
# @return [Integer] the limit of how many bytes a message can contain before
|
49
|
-
# Amazon SQS rejects it.
|
50
|
-
queue_int_attr :maximum_message_size
|
51
|
-
|
52
|
-
# @group Queue Attributes
|
53
|
-
# @return [Integer] the number of seconds Amazon SQS retains a message.
|
54
|
-
queue_int_attr :message_retention_period
|
55
|
-
|
56
|
-
# @group Queue Attributes
|
57
|
-
# @return [Integer] the approximate number of visible messages in a queue.
|
58
|
-
# For more information, see [Resources Required to Process Messages](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/ApproximateNumber.html) in the Amazon SQS Developer Guide.
|
59
|
-
queue_int_attr :approximate_number_of_messages
|
60
|
-
|
61
|
-
# @group Queue Attributes
|
62
|
-
# @return [Integer] returns the approximate number of messages that are not timed-out and not deleted. For more information, see [Resources Required to Process Messages](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/ApproximateNumber.html) in the Amazon SQS Developer Guide.
|
63
|
-
queue_int_attr :approximate_number_of_messages_not_visible
|
64
|
-
|
65
|
-
# @group Queue Attributes
|
66
|
-
# @return [Time] the time when the queue was created.
|
67
|
-
queue_time_attr :created_timestamp
|
68
|
-
|
69
|
-
# @group Queue Attributes
|
70
|
-
# @return [Time] the time when the queue was last changed.
|
71
|
-
queue_time_attr :last_modified_timestamp
|
72
|
-
|
73
|
-
# @group Queue Attributes
|
74
|
-
# @return [String] the queue's Amazon resource name (ARN).
|
75
|
-
queue_str_attr :arn, name: 'QueueArn'
|
76
|
-
|
77
|
-
alias queue_arn arn
|
78
|
-
|
79
|
-
# @group Queue Attributes
|
80
|
-
# @return [Integer] returns the approximate number of messages that
|
81
|
-
# are pending to be added to the queue.
|
82
|
-
queue_int_attr :approximate_number_of_messages_delayed
|
83
|
-
|
84
|
-
# @group Queue Attributes
|
85
|
-
# @return [Integer] the default delay on the queue in seconds.
|
86
|
-
queue_int_attr :delay_seconds
|
87
|
-
|
88
|
-
# @group Queue Attributes
|
89
|
-
# @return [Integer] the time for which a {Client#receive_message} call
|
90
|
-
# will wait for a message to arrive.
|
91
|
-
queue_int_attr :receive_message_wait_time_seconds
|
92
|
-
|
93
|
-
# @group Queue Attributes
|
94
|
-
# @return [String] the parameters for dead letter queue functionality of
|
95
|
-
# the source queue. For more information about RedrivePolicy and dead
|
96
|
-
# letter queues, see [Using Amazon SQS Dead Letter Queues](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/SQSDeadLetterQueue.html)
|
97
|
-
# in the Amazon SQS Developer Guide.
|
98
|
-
queue_str_attr :redrive_policy
|
99
|
-
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,239 +0,0 @@
|
|
1
|
-
require 'json-schema'
|
2
|
-
require 'aws-sdk-resources/validator/context'
|
3
|
-
require 'aws-sdk-resources/validator/dsl'
|
4
|
-
require 'aws-sdk-resources/validator/path_resolver'
|
5
|
-
require 'aws-sdk-resources/validator/rule'
|
6
|
-
require 'aws-sdk-resources/validator/operation_validator'
|
7
|
-
|
8
|
-
module Aws
|
9
|
-
module Resources
|
10
|
-
module Validator
|
11
|
-
|
12
|
-
extend Validator::DSL
|
13
|
-
|
14
|
-
# identifiers_may_not_be_prefixed_by_their_resource_name
|
15
|
-
match('#/resources/(\w+)/identifiers/\d+/name') do |c, matches|
|
16
|
-
resource_name = matches[1]
|
17
|
-
if c.value.match(/^#{resource_name}/)
|
18
|
-
c.error("#{c.path} must not be prefixed with '#{resource_name}'")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# identifiers_must_have_unique_names
|
23
|
-
match('#/resources/\w+/identifiers') do |c|
|
24
|
-
identifiers = c.value.map { |v| v['name'] }
|
25
|
-
identifiers.each.with_index do |identifier, n|
|
26
|
-
unless identifiers.count(identifier) == 1
|
27
|
-
c.error("#{c.path}/#{n}/name must be uniq within #{c.path}/*/name")
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# identifiers_with_memberName_require_the_resource_to_have_a_shape
|
33
|
-
match('#/resources/(\w+)/identifiers/(\d+)/memberName') do |c, matches|
|
34
|
-
resource_name = matches[1]
|
35
|
-
shape_path = "#/resources/#{resource_name}/shape"
|
36
|
-
unless c.definition['resources'][resource_name]['shape']
|
37
|
-
c.error("#{c.path} requires #{shape_path} to be set")
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# identifiers_with_memberName_require_the_resource_shape_to_have_that_member
|
42
|
-
match('#/resources/(\w+)/identifiers/(\d+)/memberName') do |c, matches|
|
43
|
-
resource_name = matches[1]
|
44
|
-
shape_path = "#/resources/#{resource_name}/shape"
|
45
|
-
shape_name = c.definition['resources'][resource_name]['shape']
|
46
|
-
if
|
47
|
-
shape_name &&
|
48
|
-
c.api['shapes'][shape_name] &&
|
49
|
-
c.api['shapes'][shape_name]['type'] == 'structure' &&
|
50
|
-
!c.api['shapes'][shape_name]['members'].key?(c.value)
|
51
|
-
then
|
52
|
-
c.error("#{c.path} is not defined at api#/shapes/#{shape_name}/members/#{c.value}")
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# shape_must_be_defined_in_the_api
|
57
|
-
match('#/resources/\w+/shape') do |c|
|
58
|
-
unless c.api['shapes'][c.value]
|
59
|
-
c.error("#{c.path} not found at api#/shapes/#{c.value}")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# shape_must_be_a_structure
|
64
|
-
# load_requires_shape_to_be_a_structure
|
65
|
-
match('#/resources/\w+/shape') do |c|
|
66
|
-
shape = c.api['shapes'][c.value]
|
67
|
-
if shape && shape['type'] != 'structure'
|
68
|
-
c.error("#{c.path} must resolve to a structure")
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# load_requires_shape_to_be_set
|
73
|
-
match('#/resources/(\w+)/load') do |c, matches|
|
74
|
-
resource = matches[1]
|
75
|
-
unless c.definition['resources'][resource]['shape']
|
76
|
-
c.error("#{c.path} requires #/resources/#{resource}/shape to be set")
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
# load_operation_must_exist
|
82
|
-
# TODO : add assertions for service/actions, service/hasMany, actions, etc
|
83
|
-
match(*%w(
|
84
|
-
#/service/actions/\w+/request/operation
|
85
|
-
#/service/hasMany/\w+/request/operation
|
86
|
-
#/resources/\w+/load/request/operation
|
87
|
-
#/resources/\w+/actions/\w+/request/operation
|
88
|
-
#/resources/\w+/batchActions/\w+/request/operation
|
89
|
-
#/resources/\w+/hasMany/\w+/request/operation
|
90
|
-
)) do |c|
|
91
|
-
unless c.api['operations'][c.value]
|
92
|
-
c.error("#{c.path} is set but is not defined at api#/operations/#{c.value}")
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# load_operation_must_accept_input_if_params_given
|
97
|
-
match(*%w(
|
98
|
-
#/service/actions/\w+/request
|
99
|
-
#/service/hasMany/\w+/request
|
100
|
-
#/resources/\w+/load/request
|
101
|
-
#/resources/\w+/actions/\w+/request
|
102
|
-
#/resources/\w+/batchActions/\w+/request
|
103
|
-
#/resources/\w+/hasMany/\w+/request
|
104
|
-
)) do |c|
|
105
|
-
# ...
|
106
|
-
end
|
107
|
-
|
108
|
-
# load_path_must_resolve_to_shape
|
109
|
-
match('#/resources/(\w+)/load/path') do |c, matches|
|
110
|
-
operation_name =
|
111
|
-
c.definition['resources'][matches[1]]['load']['request']['operation']
|
112
|
-
if operation = c.api['operations'][operation_name]
|
113
|
-
if from = operation['output']
|
114
|
-
if shape_name = c.definition['resources'][matches[1]]['shape']
|
115
|
-
resolved = PathResolver.new(c.api).resolve(c.value, from)
|
116
|
-
unless resolved == shape_name
|
117
|
-
c.error("#{c.path} must resolve to a '#{shape_name}' shape")
|
118
|
-
end
|
119
|
-
else
|
120
|
-
# resource defines load but does not define shape
|
121
|
-
end
|
122
|
-
else
|
123
|
-
# resource load operation does not have output shape reference
|
124
|
-
end
|
125
|
-
else
|
126
|
-
# resource load operation not in API model
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
match(*%w(
|
131
|
-
#/service/actions/\w+/request
|
132
|
-
#/resources/\w+/load/request
|
133
|
-
#/resources/\w+/actions/\w+/request
|
134
|
-
#/resources/\w+/batchActions/\w+/request
|
135
|
-
#/resources/\w+/hasMany/\w+/request
|
136
|
-
)) do |c|
|
137
|
-
end
|
138
|
-
|
139
|
-
match(*%w(
|
140
|
-
#/service/hasMany/\w+/resource/type
|
141
|
-
#/resources/\w+/actions/\w+/resource/type
|
142
|
-
#/resources/\w+/batchActions/\w+/resource/type
|
143
|
-
#/resources/\w+/hasMany/\w+/resource/type
|
144
|
-
)) do |c|
|
145
|
-
end
|
146
|
-
|
147
|
-
match(*%w(
|
148
|
-
#/service/hasMany/\w+/resource/identifiers
|
149
|
-
#/resources/\w+/actions/\w+/resource/identifiers
|
150
|
-
#/resources/\w+/batchActions/\w+/resource/identifiers
|
151
|
-
#/resources/\w+/hasMany/\w+/resource/identifiers
|
152
|
-
)) do |c|
|
153
|
-
# must provide ALL of the identifiers for the target resource
|
154
|
-
# each identifier must resolve from its
|
155
|
-
end
|
156
|
-
|
157
|
-
match(*%w(
|
158
|
-
#/service/hasMany/\w+/resource/path
|
159
|
-
#/resources/\w+/actions/\w+/resource/path
|
160
|
-
#/resources/\w+/batchActions/\w+/resource/path
|
161
|
-
#/resources/\w+/hasMany/\w+/resource/path
|
162
|
-
)) do |c|
|
163
|
-
type = c.parent['type']
|
164
|
-
from = c.parent.parent['request']['operation']
|
165
|
-
from = c.api['operations'][from]['output']
|
166
|
-
expected = c.definition['resources'][type]['shape']
|
167
|
-
resolved = PathResolver.new(c.api).resolve(c.value, from)
|
168
|
-
unless expected == resolved
|
169
|
-
c.error("#{c.path} must resolve to a \"#{expected}\" shape")
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# load_params_can_be_nested
|
174
|
-
# load_params_must_match_their_static_types
|
175
|
-
# load_params_must_not_be_dataMembers
|
176
|
-
# load_params_must_resolve
|
177
|
-
# load_path_accepts_dollar_signs
|
178
|
-
# load_path_accepts_nested_paths
|
179
|
-
|
180
|
-
match('#/resources/(\w+)/load') do |context|
|
181
|
-
v = OperationValidator.new(context)
|
182
|
-
v.validate_request do
|
183
|
-
v.validate_param_source_type_not_used('data')
|
184
|
-
#v.validate_path(origin: :response, target: :self)
|
185
|
-
end
|
186
|
-
v.validate_path_set
|
187
|
-
v.validate_resource_not_set
|
188
|
-
end
|
189
|
-
|
190
|
-
match('#/resources/(\w+)/actions/\w+') do |context|
|
191
|
-
v = OperationValidator.new(context)
|
192
|
-
v.validate_request
|
193
|
-
if v.resource_set?
|
194
|
-
v.validate_resource
|
195
|
-
v.validate_path(origin: :response, target: :resource)
|
196
|
-
else
|
197
|
-
v.validate_path(origin: :response)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
match('#/resources/(\w+)/batchActions/\w+') do |context|
|
202
|
-
# TODO : much like a normal action???
|
203
|
-
end
|
204
|
-
|
205
|
-
match('#/resources/(\w+)/hasMany/\w+') do |context|
|
206
|
-
v = OperationValidator.new(context)
|
207
|
-
v.validate_request
|
208
|
-
v.validate_resource do
|
209
|
-
# at least one of the identifier sources must be plural
|
210
|
-
end
|
211
|
-
if v.path_set?
|
212
|
-
v.validate_path(origin: :response, target: :resource)
|
213
|
-
v.validate_path_is_plural
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
match('#/resources/(\w+)/has/\w+') do |context, matches|
|
218
|
-
v = OperationValidator.new(context)
|
219
|
-
v.validate_request_not_set
|
220
|
-
v.validate_resource do
|
221
|
-
# disallow requestParameter
|
222
|
-
# disallow responsepath
|
223
|
-
end
|
224
|
-
# path must resolve FROM the resource data shape
|
225
|
-
# to the target resource data
|
226
|
-
v.validate_path(origin: :self, target: :resource)
|
227
|
-
|
228
|
-
if matches[2] == 'hasSome'
|
229
|
-
# at least one identifier source must be plural
|
230
|
-
# path must be plural if given
|
231
|
-
else
|
232
|
-
# identifier sources must be singular
|
233
|
-
# path must be singular if given
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
module Aws
|
2
|
-
module Resources
|
3
|
-
module Validator
|
4
|
-
class Context
|
5
|
-
|
6
|
-
def initialize(options = {})
|
7
|
-
@parent = options[:parent]
|
8
|
-
@path = options[:path]
|
9
|
-
@value = options[:value]
|
10
|
-
@definition = options[:definition]
|
11
|
-
@api = options[:api]
|
12
|
-
@errors = options[:errors] || []
|
13
|
-
end
|
14
|
-
|
15
|
-
def child(at)
|
16
|
-
Context.new(
|
17
|
-
parent: self,
|
18
|
-
path: "#{path}/#{at}",
|
19
|
-
value: value[at],
|
20
|
-
definition: definition,
|
21
|
-
api: api,
|
22
|
-
errors: errors
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
# @return [Context,nil]
|
27
|
-
attr_reader :parent
|
28
|
-
|
29
|
-
# @return [String]
|
30
|
-
attr_reader :path
|
31
|
-
|
32
|
-
# @return [Object]
|
33
|
-
attr_reader :value
|
34
|
-
|
35
|
-
# @return [Hash]
|
36
|
-
attr_reader :definition
|
37
|
-
|
38
|
-
# @return [Hash]
|
39
|
-
attr_reader :api
|
40
|
-
|
41
|
-
# @return [Array<String>]
|
42
|
-
attr_reader :errors
|
43
|
-
|
44
|
-
def [] key
|
45
|
-
@value[key]
|
46
|
-
end
|
47
|
-
|
48
|
-
def error(msg)
|
49
|
-
@errors << msg
|
50
|
-
false
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
module Aws
|
2
|
-
module Resources
|
3
|
-
module Validator
|
4
|
-
module DSL
|
5
|
-
|
6
|
-
def self.extended(base)
|
7
|
-
|
8
|
-
# @api private
|
9
|
-
base.const_set(:RULES, [])
|
10
|
-
|
11
|
-
# @api private
|
12
|
-
base.const_set(:SCHEMA_PATH, File.expand_path(File.join([
|
13
|
-
File.dirname(__FILE__), '..', '..', '..', 'resources.schema.json'
|
14
|
-
])))
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def match(*patterns, &block)
|
19
|
-
patterns.each do |pattern|
|
20
|
-
RULES << Rule.new(pattern, &block)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# @param [Hash] definition
|
25
|
-
# @param [Hash] api
|
26
|
-
# @return [Array<String>]
|
27
|
-
def validate(definition, api)
|
28
|
-
errors = validate_against_schema(definition)
|
29
|
-
if errors.empty?
|
30
|
-
lint(new_context(definition, api))
|
31
|
-
else
|
32
|
-
errors
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def new_context(definition, api)
|
39
|
-
Validator::Context.new(
|
40
|
-
path: '#',
|
41
|
-
value: definition,
|
42
|
-
definition: definition,
|
43
|
-
api: api,
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Validates the resource definition document against the JSON
|
48
|
-
# schema for resources.
|
49
|
-
# @param [Hash] definition
|
50
|
-
# @return [Array<String>] Returns an array of schema validation errors.
|
51
|
-
# Returns an empty array if there are no errors.
|
52
|
-
def validate_against_schema(definition)
|
53
|
-
schema = MultiJson.load(File.read(SCHEMA_PATH))
|
54
|
-
JSON::Validator.fully_validate(schema, definition)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Recursively lints the resource definition hash against the given
|
58
|
-
# api.
|
59
|
-
# @param [Context] context
|
60
|
-
# @return [Array<String>] Returns an array of schema validation errors.
|
61
|
-
# Returns an empty array if there are no errors.
|
62
|
-
def lint(context)
|
63
|
-
lint_node(context)
|
64
|
-
case context.value
|
65
|
-
when Hash
|
66
|
-
context.value.keys.each do |key, value|
|
67
|
-
lint(context.child(key))
|
68
|
-
end
|
69
|
-
when Array
|
70
|
-
(0...context.value.size).each do |index|
|
71
|
-
lint(context.child(index))
|
72
|
-
end
|
73
|
-
end
|
74
|
-
context.errors
|
75
|
-
end
|
76
|
-
|
77
|
-
def lint_node(context)
|
78
|
-
RULES.each do |rule|
|
79
|
-
if matches = rule.matches(context.path)
|
80
|
-
rule.apply(context, matches)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,352 +0,0 @@
|
|
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['source'] == 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
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Aws
|
2
|
-
module Resources
|
3
|
-
module Validator
|
4
|
-
# @api private
|
5
|
-
class PathResolver
|
6
|
-
|
7
|
-
def initialize(api)
|
8
|
-
@api = api
|
9
|
-
end
|
10
|
-
|
11
|
-
# @param [String<JMESPathExpression>] expression
|
12
|
-
# @param [Hash<Shape Reference>] from The shape reference, typically
|
13
|
-
# an operation, to resolve the path starting from.
|
14
|
-
# @return [String, nil] Returns the class name resolved, or `nil`
|
15
|
-
# if the path does not resolve in the model.
|
16
|
-
def resolve(expression, from)
|
17
|
-
ref = expression.scan(/\w+|\[.*?\]/).inject(from) do |ref, part|
|
18
|
-
shape = @api['shapes'][ref['shape']]
|
19
|
-
if part[0] == '['
|
20
|
-
return nil unless shape['type'] == 'list'
|
21
|
-
shape['member']
|
22
|
-
else
|
23
|
-
return nil unless shape['type'] == 'structure'
|
24
|
-
return nil unless shape['members'][part]
|
25
|
-
shape['members'][part]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
ref && ref['shape']
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Aws
|
2
|
-
module Resources
|
3
|
-
module Validator
|
4
|
-
# @api private
|
5
|
-
class Rule
|
6
|
-
|
7
|
-
def initialize(pattern, &block)
|
8
|
-
@pattern = Regexp.new('^' + pattern + '$')
|
9
|
-
@block = block
|
10
|
-
end
|
11
|
-
|
12
|
-
def matches(path)
|
13
|
-
path.match(@pattern)
|
14
|
-
end
|
15
|
-
|
16
|
-
def apply(context, matches)
|
17
|
-
@block.call(context, matches)
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|