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,15 @@
1
+ module Aws
2
+ module Resources
3
+ module Errors
4
+
5
+ class UnknownOperationError < ArgumentError
6
+ def initialize(name)
7
+ super("operation `#{name}' not defined")
8
+ end
9
+ end
10
+
11
+ class DefinitionError < ArgumentError; end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ module Aws
2
+ module Resources
3
+ module OperationMethods
4
+
5
+ # @param [Symbol] name
6
+ # @return [Operation] Returns the named operation.
7
+ # @raise [Errors::UnknownOperationError]
8
+ def operation(name)
9
+ @operations[name.to_sym] or
10
+ raise Errors::UnknownOperationError.new(name)
11
+ end
12
+
13
+ # @param [Symbol] method_name
14
+ # @param [Operation] operation
15
+ # @return [void]
16
+ def add_operation(method_name, operation = nil, &definition)
17
+ operation = definition if block_given?
18
+ safe_define_method(method_name) do |*args, &block|
19
+ operation.call(resource:self, args:args, block:block)
20
+ end
21
+ @operations[method_name.to_sym] = operation
22
+ end
23
+
24
+ # @return [Hash]
25
+ def operations(&block)
26
+ @operations.dup
27
+ end
28
+
29
+ # @return [Array<Symbol>]
30
+ def operation_names
31
+ @operations.keys
32
+ end
33
+
34
+ # @api private
35
+ def inherited(subclass)
36
+ subclass.send(:instance_variable_set, "@operations", {})
37
+ end
38
+
39
+ private
40
+
41
+ def safe_define_method(method_name, &block)
42
+ if instance_methods.include?(method_name.to_sym)
43
+ msg = "unable to define method #{name}##{method_name}, "
44
+ msg << "method already exists"
45
+ raise Errors::DefinitionError, msg
46
+ else
47
+ define_method(method_name, &block)
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,294 @@
1
+ require 'jamespath'
2
+
3
+ module Aws
4
+ module Resources
5
+ module Operations
6
+
7
+ # Base class for operations. An operation is any object that responds
8
+ # to {#call} receiving a hash of options including:
9
+ #
10
+ # * `:resource` - The resource object the operation is invoked against.
11
+ # * `:args` - An array of arguments given by the caller
12
+ # * `:block` - An optional block argument
13
+ #
14
+ class Base
15
+
16
+ include Options
17
+
18
+ def initialize(options = {})
19
+ @source = options[:source]
20
+ end
21
+
22
+ # @return [Source, nil]
23
+ attr_reader :source
24
+
25
+ # @option options[required,Resource] :resource
26
+ # @option options[required,Array<Mixed>] :args
27
+ # @option options[Proc] :block
28
+ # @return [Mixed]
29
+ def call(options = {})
30
+ raise NotImplementedError
31
+ end
32
+
33
+ end
34
+
35
+ # Makes an API request using the resource client, returning the client
36
+ # response. Most operation classes extend this basic operation.
37
+ class Operation < Base
38
+
39
+ # @option options [required, Request] :request
40
+ def initialize(options = {})
41
+ @request = option(:request, options)
42
+ super
43
+ end
44
+
45
+ # @return [Request]
46
+ attr_reader :request
47
+
48
+ # @option (see Base#call)
49
+ # @return [Seahorse::Client::Response]
50
+ def call(options)
51
+ @request.call(options)
52
+ end
53
+
54
+ end
55
+
56
+ class DataOperation < Operation
57
+
58
+ # @option options [required, Request] :request
59
+ # @option options [required, String<JMESPath>] :path
60
+ def initialize(options = {})
61
+ @path = option(:path, options)
62
+ super
63
+ end
64
+
65
+ # @return [String<JMESPath>]
66
+ attr_reader :path
67
+
68
+ # @option (see Base#call)
69
+ # @return [Object] Returns the value resolved to by {#path}.
70
+ def call(options)
71
+ extract(super)
72
+ end
73
+
74
+ private
75
+
76
+ def extract(resp)
77
+ @path == '$' ? resp.data : Jamespath.search(@path, resp.data)
78
+ end
79
+
80
+ end
81
+
82
+ class EnumerateDataOperation < DataOperation
83
+
84
+ # @option options [required, Request] :request
85
+ # @option options [required, String<JMESPath>] :path
86
+ # @option options [Symbol] :limit_key
87
+ def initialize(options = {})
88
+ @limit_key = options[:limit_key]
89
+ super
90
+ end
91
+
92
+ # @option (see Base#call)
93
+ # @option options [Integer] :limit (nil)
94
+ # @return [Enumerator]
95
+ def call(options)
96
+ if options[:limit]
97
+ enum_for(:limited_each, options[:limit], options)
98
+ else
99
+ enum_for(:each, options)
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ def each(options, &block)
106
+ @request.call(options).each do |response|
107
+ extract(response).each(&block)
108
+ end
109
+ end
110
+
111
+ def limited_each(limit, options, &block)
112
+ yielded = 0
113
+ each(options) do |value|
114
+ yield(value)
115
+ yielded += 1
116
+ break if yielded == limit
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ class ResourceOperation < Operation
123
+
124
+ # @option options [required, Request] :request
125
+ # @option options [required, Builder] :builder
126
+ def initialize(options = {})
127
+ @builder = option(:builder, options)
128
+ super
129
+ end
130
+
131
+ # @return [Builder]
132
+ attr_reader :builder
133
+
134
+ # @option (see Base#call)
135
+ # @return [Resource, Array<Resource>]
136
+ def call(options)
137
+ @builder.build(options.merge(response:super))
138
+ end
139
+
140
+ end
141
+
142
+ class EnumerateResourceOperation < ResourceOperation
143
+
144
+ # @option options [required, Request] :request
145
+ # @option options [required, Builder] :builder
146
+ # @option options [Symbol] :limit_key
147
+ def initialize(options)
148
+ @limit_key = options[:limit_key]
149
+ super
150
+ end
151
+
152
+ # @return [Builder]
153
+ attr_reader :builder
154
+
155
+ # @return [Symbol, nil]
156
+ attr_reader :limit_key
157
+
158
+ # @option (see Base#call)
159
+ # @return [Collection]
160
+ def call(options)
161
+ Collection.new(self, options)
162
+ end
163
+
164
+ # @api private
165
+ # @return [Enumerator<Batch>]
166
+ def batches(options, &block)
167
+ if options[:limit]
168
+ enum_for(:limited_batches, options[:limit], options, &block)
169
+ else
170
+ enum_for(:all_batches, options, &block)
171
+ end
172
+ end
173
+
174
+ private
175
+
176
+ def all_batches(options, &block)
177
+ options = apply_batch_size(options)
178
+ @request.call(options).each do |response|
179
+ yield(@builder.build(options.merge(response:response)))
180
+ end
181
+ end
182
+
183
+ def limited_batches(limit, options, &block)
184
+ remaining = limit
185
+ all_batches(options) do |batch|
186
+ if batch.size < remaining
187
+ yield(batch)
188
+ remaining -= batch.size
189
+ else
190
+ yield(batch.first(remaining))
191
+ break
192
+ end
193
+ end
194
+ end
195
+
196
+ def apply_batch_size(options)
197
+ if batch_size = options[:batch_size]
198
+ params = (options[:params] || {}).merge(limit_key => batch_size)
199
+ options.merge(params: params)
200
+ else
201
+ options
202
+ end
203
+ end
204
+
205
+ end
206
+
207
+ class ReferenceOperation < Base
208
+
209
+ # @option options [required, Builder] :builder
210
+ def initialize(options = {})
211
+ @builder = option(:builder, options)
212
+ super
213
+ end
214
+
215
+ # @return [Builder]
216
+ attr_reader :builder
217
+
218
+ # @option (see Base#call)
219
+ # @return [Resource]
220
+ def call(options)
221
+ if argc(options) == arity
222
+ @builder.build(options)
223
+ else
224
+ msg = "wrong number of arguments (#{argc(options)} for #{arity})"
225
+ raise ArgumentError, msg
226
+ end
227
+ end
228
+
229
+ def arity
230
+ @builder.sources.count { |s| BuilderSources::Argument === s }
231
+ end
232
+
233
+ private
234
+
235
+ def argc(options)
236
+ (options[:args] || []).count
237
+ end
238
+
239
+ end
240
+
241
+ class WaiterOperation < Base
242
+
243
+ include Options
244
+
245
+ def initialize(options = {})
246
+ @waiter_name = option(:waiter_name, options)
247
+ @waiter_params = option(:waiter_params, options)
248
+ @path = options[:path]
249
+ super
250
+ end
251
+
252
+ # @return [Symbol]
253
+ attr_reader :waiter_name
254
+
255
+ # @return [Array<RequestParams::Base>]
256
+ attr_reader :waiter_params
257
+
258
+ # @return [String<JMESPathExpression>, nil]
259
+ attr_reader :path
260
+
261
+ # @option options [required,Resource] :resource
262
+ # @option options [required,Array<Mixed>] :args
263
+ def call(options, &block)
264
+
265
+ resource = options[:resource]
266
+
267
+ params_hash = {}
268
+ @waiter_params.each do |param|
269
+ param.apply(params_hash, options)
270
+ end
271
+
272
+ user_params = options[:params] || {}
273
+ params = deep_merge(user_params, params_hash)
274
+ resp = resource.client.wait_until(@waiter_name, params)
275
+
276
+ resource_opts = resource.identifiers.dup
277
+ resource_opts[:data] = Jamespath.search(@path, resp.data) if @path
278
+ resource_opts[:client] = resource.client
279
+ resource.class.new(resource_opts)
280
+ end
281
+
282
+ def deep_merge(obj1, obj2)
283
+ case obj1
284
+ when Hash then obj1.merge(obj2) { |key, v1, v2| deep_merge(v1, v2) }
285
+ when Array then obj2 + obj1
286
+ else obj2
287
+ end
288
+ end
289
+
290
+ end
291
+
292
+ end
293
+ end
294
+ end
@@ -0,0 +1,23 @@
1
+ module Aws
2
+ module Resources
3
+ module Options
4
+
5
+ private
6
+
7
+ def expect_hash(key, options)
8
+ if options.key?(key) && !(Hash === options[key])
9
+ raise ArgumentError, "expected #{key.inspect} to be a Hash"
10
+ end
11
+ end
12
+
13
+ def option(key, options)
14
+ if options[key].nil?
15
+ raise Errors::DefinitionError, "missing required option #{key.inspect}"
16
+ else
17
+ options[key]
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ module Aws
2
+ module Resources
3
+ class Request
4
+
5
+ # @option opitons [requried, String] :method_name
6
+ # @option options [Array<RequestParams::Param>] :params ([]) A list of
7
+ # request params to apply to the request when called.
8
+ def initialize(options = {})
9
+ @method_name = options[:method_name]
10
+ @params = options[:params] || []
11
+ end
12
+
13
+ # @return [String] Name of the method called on the client when this
14
+ # operation is called.
15
+ attr_reader :method_name
16
+
17
+ # @return [Array<RequestParams::Param>]
18
+ attr_reader :params
19
+
20
+ # @option options [required,Resource] :resource
21
+ # @option options [Array<Mixed>] :args
22
+ # @return [Seahorse::Client::Response]
23
+ def call(options)
24
+ client(options).send(@method_name, req_params(options), &options[:block])
25
+ end
26
+
27
+ private
28
+
29
+ def client(options)
30
+ Array(options[:resource]).first.client
31
+ end
32
+
33
+ def req_params(options)
34
+ RequestParams::ParamsHash.new(@params).build(options)
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,225 @@
1
+ module Aws
2
+ module Resources
3
+ module RequestParams
4
+
5
+ # @api private
6
+ class ParamsHash
7
+
8
+ # @param [Array<RequestParams::Base>] params
9
+ def initialize(params)
10
+ @params = params
11
+ end
12
+
13
+ # @option options [required,Resource] :resource
14
+ # @option options [required,Array<Mixed>] :args
15
+ # @return [Hash]
16
+ def build(options = {})
17
+ deep_merge(user_params(options), computed_params(options))
18
+ end
19
+
20
+ private
21
+
22
+ def user_params(options)
23
+ args = options[:args] || []
24
+ args.last.is_a?(Hash) ? args.last : {}
25
+ end
26
+
27
+ def computed_params(options)
28
+ params_hash = {}
29
+ Array(options[:resource]).each do |resource|
30
+ @params.each do |param|
31
+ param.apply(params_hash, options.merge(resource: resource))
32
+ end
33
+ end
34
+ params_hash
35
+ end
36
+
37
+ def deep_merge(obj1, obj2)
38
+ case obj1
39
+ when Hash then obj1.merge(obj2) { |key, v1, v2| deep_merge(v1, v2) }
40
+ when Array then obj2 + obj1
41
+ else obj2
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ # Base class for all request parameter types.
48
+ # @see {RequestParams::Identifier}
49
+ # @see {RequestParams::DataMember}
50
+ # @see {RequestParams::String}
51
+ # @see {RequestParams::Integer}
52
+ class Base
53
+
54
+ # @param [String] target
55
+ def initialize(target)
56
+ @target = target.to_s
57
+ @steps = []
58
+ @target.scan(/\w+|\[\]/) do |step|
59
+ case step
60
+ when /\d+/ then @steps += [:array, step.to_i]
61
+ when '[]' then @steps += [:array, -1]
62
+ else @steps += [:hash, step.to_sym]
63
+ end
64
+ end
65
+ @steps.shift
66
+ @final = @steps.pop
67
+ end
68
+
69
+ # @return [String] target
70
+ attr_reader :target
71
+
72
+ # @param [Hash] params
73
+ # @param [Object] value
74
+ # @return [Hash] Returns the modified params hash.
75
+ def apply(params, value)
76
+ if @final == -1
77
+ build_context(params) << value
78
+ else
79
+ build_context(params)[@final] = value
80
+ end
81
+ params
82
+ end
83
+
84
+ private
85
+
86
+ def build_context(params)
87
+ @steps.each_slice(2).inject(params) do |context, (key, type)|
88
+ entry = type == :array ? [] : {}
89
+ if key == -1
90
+ context << entry
91
+ entry
92
+ else
93
+ context[key] ||= entry
94
+ end
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ class Identifier < Base
101
+
102
+ # @param [String] identifier_name
103
+ # @param (see Base#initialize)
104
+ def initialize(identifier_name, target)
105
+ @identifier_name = identifier_name.to_sym
106
+ super(target)
107
+ end
108
+
109
+ # @param [Symbol] identifier_name
110
+ attr_reader :identifier_name
111
+
112
+ # @param [Hash] params_hash
113
+ # @option [requried, Resource] :resource
114
+ def apply(params_hash, options)
115
+ value = options[:resource].identifiers[identifier_name]
116
+ super(params_hash, value)
117
+ end
118
+
119
+ # @api private
120
+ def self.literal?
121
+ false
122
+ end
123
+
124
+ end
125
+
126
+ class DataMember < Base
127
+
128
+ # @param [String] member_name
129
+ # @param (see Base#initialize)
130
+ def initialize(member_name, target)
131
+ @member_name = member_name
132
+ super(target)
133
+ end
134
+
135
+ # @return [String]
136
+ attr_reader :member_name
137
+
138
+ # @param [Hash] params_hash
139
+ # @option [requried, Resource] :resource
140
+ def apply(params_hash, options)
141
+ value = options[:resource].data[member_name.to_sym]
142
+ super(params_hash, value)
143
+ end
144
+
145
+ # @api private
146
+ def self.literal?
147
+ false
148
+ end
149
+
150
+ end
151
+
152
+ class String < Base
153
+
154
+ # @param [String] value
155
+ # @param (see Base#initialize)
156
+ def initialize(value, target)
157
+ @value = value
158
+ super(target)
159
+ end
160
+
161
+ # @return [String]
162
+ attr_reader :value
163
+
164
+ # @param [Hash] params_hash
165
+ def apply(params_hash, options = {})
166
+ super(params_hash, value)
167
+ end
168
+
169
+ # @api private
170
+ def self.literal?
171
+ true
172
+ end
173
+
174
+ end
175
+
176
+ class Integer < Base
177
+
178
+ # @param [String] value
179
+ # @param (see Base#initialize)
180
+ def initialize(value, target)
181
+ @value = value.to_i
182
+ super(target)
183
+ end
184
+
185
+ # @return [Integer]
186
+ attr_reader :value
187
+
188
+ # @param [Hash] params_hash
189
+ def apply(params_hash, options = {})
190
+ super(params_hash, value)
191
+ end
192
+
193
+ # @api private
194
+ def self.literal?
195
+ true
196
+ end
197
+
198
+ end
199
+
200
+ class Boolean < Base
201
+
202
+ # @param [String<'true'>,String<'false'>] value
203
+ # @param (see Base#initialize)
204
+ def initialize(value, target)
205
+ @value = (value == 'true')
206
+ super(target)
207
+ end
208
+
209
+ # @return [Integer]
210
+ attr_reader :value
211
+
212
+ # @param [Hash] params_hash
213
+ def apply(params_hash, options = {})
214
+ super(params_hash, value)
215
+ end
216
+
217
+ # @api private
218
+ def self.literal?
219
+ true
220
+ end
221
+
222
+ end
223
+ end
224
+ end
225
+ end