aws-sdk-core 2.0.0.rc15 → 2.0.0.rc16

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/apis/DynamoDB.paginators.json +0 -1
  3. data/apis/EC2.resources.json +16 -0
  4. data/apis/ElasticBeanstalk.api.json +4 -1
  5. data/apis/Glacier.resources.json +5 -9
  6. data/apis/IAM.resources.json +1 -1
  7. data/apis/Kinesis.api.json +158 -0
  8. data/apis/Kinesis.paginators.json +0 -6
  9. data/apis/OpsWorks.api.json +36 -5
  10. data/apis/OpsWorks.resources.json +181 -0
  11. data/apis/S3.resources.json +13 -2
  12. data/apis/SQS.resources.json +0 -10
  13. data/bin/aws.rb +9 -0
  14. data/lib/aws.rb +30 -1
  15. data/lib/aws/api/docstrings.rb +35 -0
  16. data/lib/aws/api/documenter.rb +31 -28
  17. data/lib/aws/client.rb +83 -0
  18. data/lib/aws/credential_provider_chain.rb +3 -1
  19. data/lib/aws/errors.rb +16 -7
  20. data/lib/aws/pageable_response.rb +1 -1
  21. data/lib/aws/plugins/csd_conditional_signing.rb +5 -0
  22. data/lib/aws/plugins/response_paging.rb +9 -3
  23. data/lib/aws/plugins/s3_url_encoded_keys.rb +7 -7
  24. data/lib/aws/query/handler.rb +4 -5
  25. data/lib/aws/version.rb +1 -1
  26. data/lib/aws/waiters/errors.rb +30 -0
  27. data/lib/aws/waiters/null_provider.rb +12 -0
  28. data/lib/aws/waiters/provider.rb +54 -0
  29. data/lib/aws/waiters/waiter.rb +194 -0
  30. data/lib/aws/xml/default_list.rb +10 -0
  31. data/lib/aws/xml/parser.rb +6 -1
  32. data/lib/seahorse.rb +0 -2
  33. data/lib/seahorse/client/base.rb +45 -20
  34. data/lib/seahorse/client/handler_list.rb +7 -0
  35. data/lib/seahorse/client/param_converter.rb +2 -2
  36. data/lib/seahorse/client/plugins/restful_bindings.rb +1 -1
  37. data/lib/seahorse/client/request.rb +1 -1
  38. data/lib/seahorse/client/response.rb +0 -2
  39. data/lib/seahorse/model/shapes.rb +6 -2
  40. metadata +15 -11
  41. data/LICENSE.txt +0 -12
  42. data/README.md +0 -301
  43. data/lib/seahorse/client/plugins/api.rb +0 -11
@@ -9,7 +9,7 @@ module Aws
9
9
  def resolve
10
10
  providers.each do |method_name, options|
11
11
  credentials = send(method_name, options.merge(config: @config))
12
- return credentials if credentials.set?
12
+ return credentials if credentials && credentials.set?
13
13
  end
14
14
  nil
15
15
  end
@@ -50,6 +50,8 @@ module Aws
50
50
 
51
51
  def shared_credentials(options = {})
52
52
  SharedCredentials.new(profile_name: options[:config].profile)
53
+ rescue Errors::NoSuchProfileError
54
+ nil
53
55
  end
54
56
 
55
57
  def instance_profile_credentials(*args)
data/lib/aws/errors.rb CHANGED
@@ -34,10 +34,6 @@ module Aws
34
34
  # This error indicates a checksum failed.
35
35
  class ChecksumError < RuntimeError; end
36
36
 
37
- # Raised when a {Service} is constructed an no suitable API
38
- # version is found based on configuration.
39
- class NoSuchApiVersionError < RuntimeError; end
40
-
41
37
  # Raised when a {Service} is constructed and the specified shared
42
38
  # credentials profile does not exist.
43
39
  class NoSuchProfileError < RuntimeError; end
@@ -80,9 +76,7 @@ module Aws
80
76
  #
81
77
  # @api private
82
78
  def error_class(error_code)
83
- constant = error_code.to_s
84
- constant = constant.gsub(/http:\/\/.*$/, '') # remove http namespaces
85
- constant = constant.gsub(/[^a-zA-Z0-9]/, '').to_sym
79
+ constant = error_class_constant(error_code)
86
80
  if error_const_set?(constant)
87
81
  const_get(constant)
88
82
  else
@@ -92,6 +86,21 @@ module Aws
92
86
 
93
87
  private
94
88
 
89
+ # Convert an error code to an error class name/constant.
90
+ # This requires filtering non-safe characters from the constant
91
+ # name and ensuring it begins with an uppercase letter.
92
+ # @param [String] error_code
93
+ # @return [Symbol] Returns a symbolized constant name for the given
94
+ # `error_code`.
95
+ def error_class_constant(error_code)
96
+ constant = error_code.to_s
97
+ constant = constant.gsub(/https?:.*$/, '')
98
+ constant = constant.gsub(/[^a-zA-Z0-9]/, '')
99
+ constant = 'Error' + constant unless constant.match(/^[a-z]/i)
100
+ constant = constant[0].upcase + constant[1..-1]
101
+ constant.to_sym
102
+ end
103
+
95
104
  def set_error_constant(constant)
96
105
  @const_set_mutex.synchronize do
97
106
  # Ensure the const was not defined while blocked by the mutex
@@ -101,7 +101,7 @@ module Aws
101
101
  # @return [Hash] Returns the hash of request parameters for the
102
102
  # next page, merging any given params.
103
103
  def next_page_params(params)
104
- context.params.merge(@pager.next_tokens(self).merge(params))
104
+ context[:original_params].merge(@pager.next_tokens(self).merge(params))
105
105
  end
106
106
 
107
107
  # Raised when calling {PageableResponse#next_page} on a pager that
@@ -11,6 +11,11 @@ module Aws
11
11
  #
12
12
  class CSDConditionalSigning < Seahorse::Client::Plugin
13
13
 
14
+ # Adding region as an option to avoid an issue when `Aws.config[:region]`
15
+ # is populated and the global configuration plugin merges options onto
16
+ # this client.
17
+ option(:region)
18
+
14
19
  option(:sigv4_region) do |cfg|
15
20
  # extract the region name from the cloud search domain endpoint
16
21
  if cfg.endpoint
@@ -6,13 +6,19 @@ module Aws
6
6
  class Handler < Seahorse::Client::Handler
7
7
 
8
8
  def call(context)
9
- pager = context.client.class.paginators.pager(context.operation.name)
10
- PageableResponse.new(@handler.call(context), pager)
9
+ context[:original_params] = context.params
10
+ PageableResponse.new(@handler.call(context), pager(context))
11
+ end
12
+
13
+ private
14
+
15
+ def pager(context)
16
+ context.client.class.paginators.pager(context.operation.name)
11
17
  end
12
18
 
13
19
  end
14
20
 
15
- handler(Handler)
21
+ handler(Handler, step: :initialize, priority: 90)
16
22
 
17
23
  end
18
24
  end
@@ -46,8 +46,8 @@ module Aws
46
46
  decode(:next_marker, data)
47
47
  decode(:prefix, data)
48
48
  decode(:delimiter, data)
49
- data.contents.each { |o| decode(:key, o) }
50
- data.common_prefixes.each { |o| decode(:prefix, o) }
49
+ data.contents.each { |o| decode(:key, o) } if data.contents
50
+ data.common_prefixes.each { |o| decode(:prefix, o) } if data.common_prefixes
51
51
  end
52
52
 
53
53
  def decode_list_object_versions_keys(data)
@@ -55,9 +55,9 @@ module Aws
55
55
  decode(:next_key_marker, data)
56
56
  decode(:prefix, data)
57
57
  decode(:delimiter, data)
58
- data.versions.each { |o| decode(:key, o) }
59
- data.delete_markers.each { |o| decode(:key, o) }
60
- data.common_prefixes.each { |o| decode(:prefix, o) }
58
+ data.versions.each { |o| decode(:key, o) } if data.versions
59
+ data.delete_markers.each { |o| decode(:key, o) } if data.delete_markers
60
+ data.common_prefixes.each { |o| decode(:prefix, o) } if data.common_prefixes
61
61
  end
62
62
 
63
63
  def decode_list_multipart_uploads_keys(data)
@@ -65,8 +65,8 @@ module Aws
65
65
  decode(:next_key_marker, data)
66
66
  decode(:prefix, data)
67
67
  decode(:delimiter, data)
68
- data.uploads.each { |o| decode(:key, o) }
69
- data.common_prefixes.each { |o| decode(:prefix, o) }
68
+ data.uploads.each { |o| decode(:key, o) } if data.uploads
69
+ data.common_prefixes.each { |o| decode(:prefix, o) } if data.common_prefixes
70
70
  end
71
71
 
72
72
  def decode(member, struct)
@@ -33,9 +33,8 @@ module Aws
33
33
 
34
34
  def parse_xml(context)
35
35
  if rules = context.operation.output
36
- rules = apply_wrapper(rules)
37
- data = Xml::Parser.new(rules).parse(xml(context))
38
- remove_wrapper(data, context)
36
+ data = Xml::Parser.new(apply_wrapper(rules)).parse(xml(context))
37
+ remove_wrapper(data, context, rules)
39
38
  else
40
39
  EmptyStructure.new
41
40
  end
@@ -59,10 +58,10 @@ module Aws
59
58
  }, shape_map: shape.shape_map)
60
59
  end
61
60
 
62
- def remove_wrapper(data, context)
61
+ def remove_wrapper(data, context, rules)
63
62
  if context.operation.output.metadata('resultWrapper')
64
63
  context[:request_id] = data.response_metadata.request_id
65
- data[data.members.first]
64
+ data[data.members.first] || Structure.new(rules.member_names)
66
65
  else
67
66
  data
68
67
  end
data/lib/aws/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Aws
2
- VERSION = '2.0.0.rc15'
2
+ VERSION = '2.0.0.rc16'
3
3
  end
@@ -0,0 +1,30 @@
1
+ require 'jamespath'
2
+
3
+ module Aws
4
+ module Waiters
5
+ module Errors
6
+
7
+ # Raised when a waiter detects a condition where the waiter can never
8
+ # succeed.
9
+ class WaiterFailed < StandardError; end
10
+
11
+ # Raised when attempting to get a waiter by name and the waiter has not
12
+ # been defined.
13
+ class NoSuchWaiter < ArgumentError
14
+ def initialize(waiter_name, waiter_names)
15
+ msg = "no definition found for #{waiter_name.inspect}"
16
+ msg << "; valid waiter names are:"
17
+ waiter_names.sort.each.with_index do |name, n|
18
+ if n % 3 == 0
19
+ msg << "\n #{name.inspect}"
20
+ else
21
+ msg << ", #{name.inspect}"
22
+ end
23
+ end
24
+ super(msg)
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ module Aws
2
+ module Waiters
3
+ # @api private
4
+ class NullProvider < Provider
5
+
6
+ def initialize
7
+ super('waiters' => {})
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,54 @@
1
+ require 'set'
2
+
3
+ module Aws
4
+ module Waiters
5
+ # @api private
6
+ class Provider
7
+
8
+ def initialize(definitions)
9
+ @waiter_names = Set.new
10
+ @definitions = definitions['waiters'].each.with_object({}) do |(k,v),h|
11
+ if k.match(/^__/)
12
+ h[k] = v
13
+ else
14
+ underscore(k).to_sym.tap do |name|
15
+ @waiter_names << name
16
+ h[name] = v
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ # @return [Array<Symbol>]
23
+ def waiter_names
24
+ @waiter_names.to_a
25
+ end
26
+
27
+ # @param [Symbol] waiter_name
28
+ # @return [Waiter]
29
+ # @raise [ArgumentError]
30
+ def waiter(waiter_name)
31
+ if @waiter_names.include?(waiter_name)
32
+ Waiter.new(resolve('extends' => waiter_name))
33
+ else
34
+ raise Errors::NoSuchWaiter.new(waiter_name, waiter_names)
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def resolve(definition)
41
+ if extends = definition.delete('extends')
42
+ resolve(@definitions[extends].merge(definition))
43
+ else
44
+ (@definitions['__default__'] || {}).merge(definition)
45
+ end
46
+ end
47
+
48
+ def underscore(str)
49
+ str.gsub(/\w+/) { |part| Seahorse::Util.underscore(part) }
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,194 @@
1
+ require 'jamespath'
2
+
3
+ module Aws
4
+ module Waiters
5
+ class Waiter
6
+
7
+ # @api private
8
+ RAISE_HANDLER = Seahorse::Client::Plugins::RaiseResponseErrors::Handler
9
+
10
+ # @api private
11
+ def initialize(definition = {})
12
+ @definition = definition
13
+ @interval = definition['interval']
14
+ @max_attempts = definition['max_attempts']
15
+ @before_attempt = []
16
+ @before_wait = []
17
+ end
18
+
19
+ # Register a callback that is invoked before every polling attempt.
20
+ # Yields the number of attempts made so far.
21
+ #
22
+ # waiter.before_attempt do |attempts|
23
+ # puts "#{attempts} made, about to make attempt #{attempts + 1}"
24
+ # end
25
+ #
26
+ # Throwing `:success` or `:failure` from the given block will stop
27
+ # the waiter and return or raise. You can pass a custom message to the
28
+ # throw:
29
+ #
30
+ # # raises Aws::Waiters::Errors::WaiterFailed
31
+ # waiter.before_attempt do |attempts|
32
+ # throw :failure, 'custom-error-message'
33
+ # end
34
+ #
35
+ # # cause the waiter to stop polling and return
36
+ # waiter.before_attempt do |attempts|
37
+ # throw :success
38
+ # end
39
+ #
40
+ # @yieldparam [Integer] attempts The number of attempts made.
41
+ def before_attempt(&block)
42
+ @before_attempt << Proc.new
43
+ end
44
+
45
+ # Register a callback that is invoked after an attempt but before
46
+ # sleeping. Yields the number of attempts made and the previous response.
47
+ #
48
+ # waiter.before_wait do |attempts, response|
49
+ # puts "#{attempts} made"
50
+ # puts response.error.inspect
51
+ # puts response.data.inspect
52
+ # end
53
+ #
54
+ # Throwing `:success` or `:failure` from the given block will stop
55
+ # the waiter and return or raise. You can pass a custom message to the
56
+ # throw:
57
+ #
58
+ # # raises Aws::Waiters::Errors::WaiterFailed
59
+ # waiter.before_attempt do |attempts|
60
+ # throw :failure, 'custom-error-message'
61
+ # end
62
+ #
63
+ # # cause the waiter to stop polling and return
64
+ # waiter.before_attempt do |attempts|
65
+ # throw :success
66
+ # end
67
+ #
68
+ #
69
+ # @yieldparam [Integer] attempts The number of attempts already made.
70
+ # @yieldparam [Seahorse::Client::Response] response The response from
71
+ # the previous polling attempts.
72
+ def before_wait(&block)
73
+ @before_wait << Proc.new
74
+ end
75
+
76
+ # @return [Float]
77
+ attr_accessor :interval
78
+
79
+ # @return [Integer]
80
+ attr_accessor :max_attempts
81
+
82
+ # @param [Client] client
83
+ # @param [Hash] params
84
+ def wait(client, params)
85
+ attempts = 0
86
+ catch(:success) do
87
+ failure = catch(:failure) do
88
+ loop do
89
+ trigger_callbacks(@before_attempt, attempts)
90
+ attempts += 1
91
+ resp = send_request(client, params)
92
+ throw :success, resp if successful?(resp)
93
+ throw :failure if failure?(resp)
94
+ throw :failure, resp.error unless error_ignored?(resp)
95
+ throw :failure, too_many(attempts) if attempts == max_attempts
96
+ trigger_callbacks(@before_wait, attempts, resp)
97
+ sleep(interval)
98
+ end
99
+ end
100
+ failure = 'waiter failed' if failure.nil?
101
+ raise String === failure ? Errors::WaiterFailed.new(failure) : failure
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def successful?(response)
108
+ acceptor_matches?(:success, response)
109
+ end
110
+
111
+ def failure?(response)
112
+ acceptor_matches?(:failure, response)
113
+ end
114
+
115
+ def trigger_callbacks(callbacks, *args)
116
+ callbacks.each { |block| block.call(*args) }
117
+ end
118
+
119
+ def send_request(client, params)
120
+ req = client.build_request(operation_name, params)
121
+ req.handlers.remove(RAISE_HANDLER)
122
+ req.send_request
123
+ end
124
+
125
+ def operation_name
126
+ underscore(@definition['operation']).to_sym
127
+ end
128
+
129
+ def acceptor_matches?(acceptor, resp)
130
+ case type(acceptor)
131
+ when 'output' then output_matches?(resp, values(acceptor), path(acceptor))
132
+ when 'error' then error_matches?(resp.error, values(acceptor))
133
+ end
134
+ end
135
+
136
+ def type(acceptor)
137
+ @definition["#{acceptor}_type"] || @definition['acceptor_type']
138
+ end
139
+
140
+ def path(acceptor)
141
+ underscore(@definition["#{acceptor}_path"] || @definition['acceptor_path'])
142
+ end
143
+
144
+ def values(acceptor)
145
+ values = @definition["#{acceptor}_value"] || @definition['acceptor_value']
146
+ values.is_a?(Array) ? values : [values]
147
+ end
148
+
149
+ def output_matches?(resp, value, path)
150
+ if resp.error
151
+ false
152
+ elsif path
153
+ output_value_matches?(value, Jamespath.search(path, resp.data))
154
+ else
155
+ true
156
+ end
157
+ end
158
+
159
+ def output_value_matches?(expected, results)
160
+ if results.is_a?(Array)
161
+ results.all? { |result| expected.include?(result) }
162
+ else
163
+ expected.include?(results)
164
+ end
165
+ end
166
+
167
+ def error_ignored?(resp)
168
+ if resp.error
169
+ error_matches?(resp.error, @definition['ignore_errors'] || [])
170
+ else
171
+ true
172
+ end
173
+ end
174
+
175
+ def error_matches?(error, errors)
176
+ if error
177
+ errors.any? { |pattern| error.class.name.match(/#{pattern}$/) }
178
+ else
179
+ false
180
+ end
181
+ end
182
+
183
+ def too_many(attempts)
184
+ "too many attempts made, #{attempts} attempts made without " +
185
+ "success or failure"
186
+ end
187
+
188
+ def underscore(str)
189
+ str.gsub(/\w+/) { |part| Seahorse::Util.underscore(part) } if str
190
+ end
191
+
192
+ end
193
+ end
194
+ end