aws-sdk-core 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 095a9cf0ab8ce8b2d557d82cf246cc112d147bb9
4
- data.tar.gz: 1d25a79ad4192d181988f1e0a6afeda1711ed5b2
3
+ metadata.gz: dda8c10d942f3b2cce363ac42604f24ab31999a0
4
+ data.tar.gz: 6df8bda2ca1abc7bb922393f830dbdf20cb4e0f4
5
5
  SHA512:
6
- metadata.gz: ebb815c6c334e6a04b43ef2de7a9d03277de84ac45f0ad6e645a85f8419ce5f57c5451861e1de0d8c71eef34f5ac4df2d70f7b42fd671d038ba920d6e7a71b3e
7
- data.tar.gz: b444dd58b8fa3f6f79299c4a8b06da6a9ddf413bbbb27362d114778ef642b65a9374b9f854bc1788975dc38c0efc846e53137e5fb461b8f21ed5735257596156
6
+ metadata.gz: a9b88a6d372a63669022b97db8edb3c9f902f644f0864c600594400c39c55569db7d59a89d5f92e3d433c93b84bfebdcaed9f53aa7474335c996c93517eee73e
7
+ data.tar.gz: 6db1ee99c301f53ab3edcba2754bd26286e8fecc02a57764317940434df9e10143794ec56918977a518b3b2282b1df91b9ab608f86f839e06c7d1e1a2a08ef98
@@ -398,7 +398,11 @@
398
398
  "B":{"shape":"BinaryAttributeValue"},
399
399
  "SS":{"shape":"StringSetAttributeValue"},
400
400
  "NS":{"shape":"NumberSetAttributeValue"},
401
- "BS":{"shape":"BinarySetAttributeValue"}
401
+ "BS":{"shape":"BinarySetAttributeValue"},
402
+ "M":{"shape":"MapAttributeValue"},
403
+ "L":{"shape":"ListAttributeValue"},
404
+ "NULL":{"shape":"NullAttributeValue"},
405
+ "BOOL":{"shape":"BooleanAttributeValue"}
402
406
  }
403
407
  },
404
408
  "AttributeValueList":{
@@ -469,6 +473,7 @@
469
473
  "type":"list",
470
474
  "member":{"shape":"BinaryAttributeValue"}
471
475
  },
476
+ "BooleanAttributeValue":{"type":"boolean"},
472
477
  "BooleanObject":{"type":"boolean"},
473
478
  "Capacity":{
474
479
  "type":"structure",
@@ -502,6 +507,7 @@
502
507
  "ComparisonOperator":{"shape":"ComparisonOperator"}
503
508
  }
504
509
  },
510
+ "ConditionExpression":{"type":"string"},
505
511
  "ConditionalCheckFailedException":{
506
512
  "type":"structure",
507
513
  "members":{
@@ -569,7 +575,10 @@
569
575
  "ConditionalOperator":{"shape":"ConditionalOperator"},
570
576
  "ReturnValues":{"shape":"ReturnValue"},
571
577
  "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"},
572
- "ReturnItemCollectionMetrics":{"shape":"ReturnItemCollectionMetrics"}
578
+ "ReturnItemCollectionMetrics":{"shape":"ReturnItemCollectionMetrics"},
579
+ "ConditionExpression":{"shape":"ConditionExpression"},
580
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"},
581
+ "ExpressionAttributeValues":{"shape":"ExpressionAttributeValueMap"}
573
582
  }
574
583
  },
575
584
  "DeleteItemOutput":{
@@ -628,6 +637,18 @@
628
637
  "AttributeValueList":{"shape":"AttributeValueList"}
629
638
  }
630
639
  },
640
+ "ExpressionAttributeNameMap":{
641
+ "type":"map",
642
+ "key":{"shape":"ExpressionAttributeNameVariable"},
643
+ "value":{"shape":"AttributeName"}
644
+ },
645
+ "ExpressionAttributeNameVariable":{"type":"string"},
646
+ "ExpressionAttributeValueMap":{
647
+ "type":"map",
648
+ "key":{"shape":"ExpressionAttributeValueVariable"},
649
+ "value":{"shape":"AttributeValue"}
650
+ },
651
+ "ExpressionAttributeValueVariable":{"type":"string"},
631
652
  "FilterConditionMap":{
632
653
  "type":"map",
633
654
  "key":{"shape":"AttributeName"},
@@ -644,7 +665,9 @@
644
665
  "Key":{"shape":"Key"},
645
666
  "AttributesToGet":{"shape":"AttributeNameList"},
646
667
  "ConsistentRead":{"shape":"ConsistentRead"},
647
- "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"}
668
+ "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"},
669
+ "ProjectionExpression":{"shape":"ProjectionExpression"},
670
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"}
648
671
  }
649
672
  },
650
673
  "GetItemOutput":{
@@ -811,7 +834,9 @@
811
834
  "members":{
812
835
  "Keys":{"shape":"KeyList"},
813
836
  "AttributesToGet":{"shape":"AttributeNameList"},
814
- "ConsistentRead":{"shape":"ConsistentRead"}
837
+ "ConsistentRead":{"shape":"ConsistentRead"},
838
+ "ProjectionExpression":{"shape":"ProjectionExpression"},
839
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"}
815
840
  }
816
841
  },
817
842
  "LimitExceededException":{
@@ -821,6 +846,10 @@
821
846
  },
822
847
  "exception":true
823
848
  },
849
+ "ListAttributeValue":{
850
+ "type":"list",
851
+ "member":{"shape":"AttributeValue"}
852
+ },
824
853
  "ListTablesInput":{
825
854
  "type":"structure",
826
855
  "members":{
@@ -872,6 +901,11 @@
872
901
  "member":{"shape":"LocalSecondaryIndex"}
873
902
  },
874
903
  "Long":{"type":"long"},
904
+ "MapAttributeValue":{
905
+ "type":"map",
906
+ "key":{"shape":"AttributeName"},
907
+ "value":{"shape":"AttributeValue"}
908
+ },
875
909
  "NonKeyAttributeName":{
876
910
  "type":"string",
877
911
  "min":1,
@@ -883,6 +917,7 @@
883
917
  "min":1,
884
918
  "max":20
885
919
  },
920
+ "NullAttributeValue":{"type":"boolean"},
886
921
  "NumberAttributeValue":{"type":"string"},
887
922
  "NumberSetAttributeValue":{
888
923
  "type":"list",
@@ -903,6 +938,7 @@
903
938
  "NonKeyAttributes":{"shape":"NonKeyAttributeNameList"}
904
939
  }
905
940
  },
941
+ "ProjectionExpression":{"type":"string"},
906
942
  "ProjectionType":{
907
943
  "type":"string",
908
944
  "enum":[
@@ -952,7 +988,10 @@
952
988
  "ReturnValues":{"shape":"ReturnValue"},
953
989
  "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"},
954
990
  "ReturnItemCollectionMetrics":{"shape":"ReturnItemCollectionMetrics"},
955
- "ConditionalOperator":{"shape":"ConditionalOperator"}
991
+ "ConditionalOperator":{"shape":"ConditionalOperator"},
992
+ "ConditionExpression":{"shape":"ConditionExpression"},
993
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"},
994
+ "ExpressionAttributeValues":{"shape":"ExpressionAttributeValueMap"}
956
995
  }
957
996
  },
958
997
  "PutItemInputAttributeMap":{
@@ -993,7 +1032,11 @@
993
1032
  "ConditionalOperator":{"shape":"ConditionalOperator"},
994
1033
  "ScanIndexForward":{"shape":"BooleanObject"},
995
1034
  "ExclusiveStartKey":{"shape":"Key"},
996
- "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"}
1035
+ "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"},
1036
+ "ProjectionExpression":{"shape":"ProjectionExpression"},
1037
+ "FilterExpression":{"shape":"ConditionExpression"},
1038
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"},
1039
+ "ExpressionAttributeValues":{"shape":"ExpressionAttributeValueMap"}
997
1040
  }
998
1041
  },
999
1042
  "QueryOutput":{
@@ -1066,7 +1109,11 @@
1066
1109
  "ExclusiveStartKey":{"shape":"Key"},
1067
1110
  "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"},
1068
1111
  "TotalSegments":{"shape":"ScanTotalSegments"},
1069
- "Segment":{"shape":"ScanSegment"}
1112
+ "Segment":{"shape":"ScanSegment"},
1113
+ "ProjectionExpression":{"shape":"ProjectionExpression"},
1114
+ "FilterExpression":{"shape":"ConditionExpression"},
1115
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"},
1116
+ "ExpressionAttributeValues":{"shape":"ExpressionAttributeValueMap"}
1070
1117
  }
1071
1118
  },
1072
1119
  "ScanOutput":{
@@ -1142,6 +1189,7 @@
1142
1189
  "ACTIVE"
1143
1190
  ]
1144
1191
  },
1192
+ "UpdateExpression":{"type":"string"},
1145
1193
  "UpdateGlobalSecondaryIndexAction":{
1146
1194
  "type":"structure",
1147
1195
  "required":[
@@ -1167,7 +1215,11 @@
1167
1215
  "ConditionalOperator":{"shape":"ConditionalOperator"},
1168
1216
  "ReturnValues":{"shape":"ReturnValue"},
1169
1217
  "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"},
1170
- "ReturnItemCollectionMetrics":{"shape":"ReturnItemCollectionMetrics"}
1218
+ "ReturnItemCollectionMetrics":{"shape":"ReturnItemCollectionMetrics"},
1219
+ "UpdateExpression":{"shape":"UpdateExpression"},
1220
+ "ConditionExpression":{"shape":"ConditionExpression"},
1221
+ "ExpressionAttributeNames":{"shape":"ExpressionAttributeNameMap"},
1222
+ "ExpressionAttributeValues":{"shape":"ExpressionAttributeValueMap"}
1171
1223
  }
1172
1224
  },
1173
1225
  "UpdateItemOutput":{
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "__VolumeStatus": {
60
60
  "operation": "DescribeVolumes",
61
- "acceptor_path": "VolumeStatuses[].VolumeStatus.Status"
61
+ "acceptor_path": "Volumes[].State"
62
62
  },
63
63
  "VolumeAvailable": {
64
64
  "extends": "__VolumeStatus",
@@ -233,6 +233,33 @@
233
233
  }
234
234
  }
235
235
  },
236
+ "AccessKeyPair": {
237
+ "identifiers": [
238
+ { "name": "UserName" },
239
+ { "name": "Id" }
240
+ ],
241
+ "shape": "AccessKey",
242
+ "hasOne": {
243
+ "AccessKey": {
244
+ "resource": {
245
+ "type": "AccessKey",
246
+ "identifiers": [
247
+ { "target":"UserName", "sourceType":"identifier", "source":"UserName" },
248
+ { "target":"Id", "sourceType":"identifier", "source":"Id" }
249
+ ]
250
+ }
251
+ },
252
+ "User": {
253
+ "resource": {
254
+ "type": "AccessKey",
255
+ "identifiers": [
256
+ { "target":"UserName", "sourceType":"identifier", "source":"UserName" },
257
+ { "target":"Id", "sourceType":"identifier", "source":"Id" }
258
+ ]
259
+ }
260
+ }
261
+ }
262
+ },
236
263
  "AccountAlias": {
237
264
  "identifiers": [
238
265
  { "name": "Name" }
@@ -803,7 +830,7 @@
803
830
  ]
804
831
  },
805
832
  "resource": {
806
- "type": "AccessKey",
833
+ "type": "AccessKeyPair",
807
834
  "identifiers": [
808
835
  { "target":"UserName", "sourceType":"identifier", "source":"Name" },
809
836
  { "target":"Id", "sourceType":"responsePath", "source":"AccessKey.AccessKeyId" }
@@ -71,6 +71,20 @@
71
71
  }
72
72
  }
73
73
  },
74
+ "waiters": {
75
+ "Exists": {
76
+ "waiterName": "BucketExists",
77
+ "params": [
78
+ { "target":"Bucket", "sourceType":"identifier", "source":"Name" }
79
+ ]
80
+ },
81
+ "NotExists": {
82
+ "waiterName": "BucketNotExists",
83
+ "params": [
84
+ { "target":"Bucket", "sourceType":"identifier", "source":"Name" }
85
+ ]
86
+ }
87
+ },
74
88
  "hasMany": {
75
89
  "Objects": {
76
90
  "request": {
@@ -575,6 +589,22 @@
575
589
  }
576
590
  }
577
591
  },
592
+ "waiters": {
593
+ "Exists": {
594
+ "waiterName": "ObjectExists",
595
+ "params": [
596
+ { "target":"Bucket", "sourceType":"identifier", "source":"BucketName" },
597
+ { "target":"Key", "sourceType":"identifier", "source":"Key" }
598
+ ]
599
+ },
600
+ "NotExists": {
601
+ "waiterName": "ObjectNotExists",
602
+ "params": [
603
+ { "target":"Bucket", "sourceType":"identifier", "source":"BucketName" },
604
+ { "target":"Key", "sourceType":"identifier", "source":"Key" }
605
+ ]
606
+ }
607
+ },
578
608
  "subResources": {
579
609
  "resources": [
580
610
  "ObjectAcl",
@@ -68,6 +68,7 @@ module Aws
68
68
  end
69
69
 
70
70
  autoload :Client, 'aws-sdk-core/client'
71
+ autoload :ClientStubs, 'aws-sdk-core/client_stubs'
71
72
  autoload :CredentialProviderChain, 'aws-sdk-core/credential_provider_chain'
72
73
  autoload :Credentials, 'aws-sdk-core/credentials'
73
74
  autoload :EmptyStructure, 'aws-sdk-core/empty_structure'
@@ -137,6 +138,7 @@ module Aws
137
138
  autoload :S3SseCpk, 'aws-sdk-core/plugins/s3_sse_cpk'
138
139
  autoload :S3UrlEncodedKeys, 'aws-sdk-core/plugins/s3_url_encoded_keys'
139
140
  autoload :SQSQueueUrls, 'aws-sdk-core/plugins/sqs_queue_urls'
141
+ autoload :StubResponses, 'aws-sdk-core/plugins/stub_responses'
140
142
  autoload :SWFReadTimeouts, 'aws-sdk-core/plugins/swf_read_timeouts'
141
143
  autoload :UserAgent, 'aws-sdk-core/plugins/user_agent'
142
144
 
@@ -10,7 +10,11 @@ module Aws
10
10
  def input
11
11
  params(nil) do
12
12
  if @operation.input
13
- structure(@operation.input, [])
13
+ lines = []
14
+ if @operation.output
15
+ lines << '<div class="param"><div class="entry"><span class="key">:response_target</span> => String, Pathname, File</div>Optional path to a file or file object where the HTTP response body should be written.</div>'
16
+ end
17
+ lines + structure(@operation.input, [])
14
18
  else
15
19
  []
16
20
  end
@@ -51,7 +55,7 @@ module Aws
51
55
 
52
56
  def params(shape, &block)
53
57
  if shape && shape.name == 'AttributeValue'
54
- ['<p>An attribute value may be one of:<ul><li>`String`</li><li>`Numeric`</li><li>`IO`</li><li>`Set<String,Numeric,IO>`</li></ul></p>']
58
+ ['<p>An attribute value may be one of:<ul><li>`Hash`</li><li>`Array`</li><li>`String`</li><li>`Numeric`</li><li>`true` | `false`</li><li>`nil`</li><li>`IO`</li><li>`Set<String,Numeric,IO>`</li></ul></p>']
55
59
  else
56
60
  ['<div class="params">', api_ref(shape)] + yield + ['</div>']
57
61
  end
@@ -8,6 +8,11 @@ module Aws
8
8
  @obj_name = options[:svc_var_name]
9
9
  @method_name = options[:method_name]
10
10
  @operation = options[:operation]
11
+ @streaming_output = !!(
12
+ @operation.output &&
13
+ @operation.output.payload_member &&
14
+ @operation.output.payload_member.definition['streaming']
15
+ )
11
16
  end
12
17
 
13
18
  def to_str
@@ -25,6 +30,9 @@ module Aws
25
30
 
26
31
  def structure(shape, i, visited)
27
32
  lines = ['{']
33
+ if @streaming_output
34
+ lines << "#{i} response_target: '/path/to/file', # optional target file path"
35
+ end
28
36
  shape.members.each do |member_name, member_shape|
29
37
  if shape.required.include?(member_name)
30
38
  lines << "#{i} # required"
@@ -72,7 +80,7 @@ module Aws
72
80
  recursive << "#{i}}"
73
81
  return recursive.join("\n")
74
82
  elsif shape.name == 'AttributeValue'
75
- msg='"value", #<String,Numeric,IO,Set>'
83
+ msg='"value", #<Hash,Array,String,Numeric,Boolean,nil,IO,Set>'
76
84
  return msg
77
85
  else
78
86
  visited = visited + [shape.name]
@@ -12,6 +12,7 @@ module Aws
12
12
  'Aws::Plugins::RegionalEndpoint',
13
13
  'Aws::Plugins::ResponsePaging',
14
14
  'Aws::Plugins::RequestSigner',
15
+ 'Aws::Plugins::StubResponses',
15
16
  ]
16
17
 
17
18
  @customizations = Hash.new {|h,k| h[k] = [] }
@@ -1,8 +1,9 @@
1
1
  module Aws
2
-
3
2
  # Base class for all {Aws} service clients.
4
3
  class Client < Seahorse::Client::Base
5
4
 
5
+ include ClientStubs
6
+
6
7
  # Waits until a particular condition is satisfied. This works by
7
8
  # polling a client request and checking for particular response
8
9
  # data or errors. Waiters each have a default duration max attempts
@@ -0,0 +1,227 @@
1
+ module Aws
2
+
3
+ # This module provides the ability to specify the data and/or errors to
4
+ # return when a client is using stubbed responses. Pass
5
+ # `:stub_responses => true` to a client constructor to enable this
6
+ # behavior.
7
+ module ClientStubs
8
+
9
+ def initialize(*args)
10
+ @stubs = {}
11
+ super
12
+ end
13
+
14
+ # Configures what data / errors should be returned from the named operation
15
+ # when response stubbing is enabled.
16
+ #
17
+ # ## Basic usage
18
+ #
19
+ # By default, fake responses are generated. You can override the default
20
+ # fake data with specific response data by passing a hash.
21
+ #
22
+ # # enable response stubbing in the client constructor
23
+ # client = Aws::S3::Client.new(stub_responses: true)
24
+ #
25
+ # # specify the response data for #list_buckets
26
+ # client.stub_responses(:list_buckets, buckets:[{name:'aws-sdk'}])
27
+ #
28
+ # # no api calls made, stub returned
29
+ # client.list_buckets.map(&:name)
30
+ # #=> ['aws-sdk']
31
+ #
32
+ # ## Stubbing Errors
33
+ #
34
+ # When stubbing is enabled, the SDK will default to generate
35
+ # fake responses with placeholder values. You can override the data
36
+ # returned. You can also specify errors it should raise.
37
+ #
38
+ # client.stub_responses(:get_object, 'NotFound')
39
+ # client.get_object(bucket:'aws-sdk', key:'foo')
40
+ # #=> raises Aws::S3::Errors::NotFound
41
+ #
42
+ # client.stub_responses(:get_object, Timeout::Error)
43
+ # client.get_object(bucket:'aws-sdk', key:'foo')
44
+ # #=> raises new Timeout::Error
45
+ #
46
+ # client.stub_responses(:get_object, RuntimeError.new('custom message'))
47
+ # client.get_object(bucket:'aws-sdk', key:'foo')
48
+ # #=> raises the given runtime error object
49
+ #
50
+ # ## Stubbing Multiple Responses
51
+ #
52
+ # Calling an operation multiple times will return similar responses.
53
+ # You can configure multiple stubs and they will be returned in sequence.
54
+ #
55
+ #
56
+ # client.stub_responses(:head_object, [
57
+ # 'NotFound',
58
+ # { content_length: 150 },
59
+ # ])
60
+ #
61
+ # client.head_object(bucket:'aws-sdk', key:'foo')
62
+ # #=> raises Aws::S3::Errors::NotFound
63
+ #
64
+ # resp = client.head_object(bucket:'aws-sdk', key:'foo')
65
+ # resp.content_length #=> 150
66
+ #
67
+ # @param [Symbol] operation_name
68
+ # @param [Mixed] stubs One or more responses to return from the named
69
+ # operation.
70
+ # @return [void]
71
+ # @raise [RuntimeError] Raises a runtime error when called
72
+ # on a client that has not enabled response stubbing via
73
+ # `:stub_responses => true`.
74
+ def stub_responses(operation_name, *stubs)
75
+ if config.stub_responses
76
+ apply_stubs(operation_name, stubs.flatten)
77
+ else
78
+ msg = 'stubbing is not enabled; enable stubbing in the constructor '
79
+ msg << 'with `:stub_responses => true`'
80
+ raise msg
81
+ end
82
+ end
83
+
84
+ # @api private
85
+ def next_stub(operation_name)
86
+ stubs = @stubs[operation_name.to_sym] || []
87
+ case stubs.length
88
+ when 0 then new_stub(operation_name)
89
+ when 1 then stubs.first
90
+ else stubs.shift
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ # @param [Symbol] operation_name
97
+ # @param [Hash, nil] data
98
+ # @return [Structure]
99
+ def new_stub(operation_name, data = nil)
100
+ Stub.new(operation(operation_name).output).format(data || {})
101
+ end
102
+
103
+ def apply_stubs(operation_name, stubs)
104
+ @stubs[operation_name.to_sym] = stubs.map do |stub|
105
+ case stub
106
+ when Exception then stub
107
+ when String then service_error_class(stub)
108
+ when Hash then new_stub(operation_name, stub)
109
+ else stub
110
+ end
111
+ end
112
+ end
113
+
114
+ def service_error_class(name)
115
+ svc_module = Aws.const_get(self.class.name.split('::')[1])
116
+ svc_module.const_get(:Errors).const_get(name)
117
+ end
118
+
119
+ class Stub
120
+
121
+ # @param [Seahorse::Models::Shapes::Structure] output_shape This should
122
+ # be the output shape for an operation.
123
+ def initialize(output_shape)
124
+ @shape = output_shape
125
+ end
126
+
127
+ # @param [Hash] data An optional hash of data to format into the stubbed
128
+ # object.
129
+ def format(data = {})
130
+ if @shape.nil?
131
+ empty_stub(data)
132
+ else
133
+ validate_data(data)
134
+ stub(@shape, data)
135
+ end
136
+ end
137
+
138
+ private
139
+
140
+ def stub(shape, value)
141
+ case shape
142
+ when Seahorse::Model::Shapes::Structure then stub_structure(shape, value)
143
+ when Seahorse::Model::Shapes::List then stub_list(shape, value || [])
144
+ when Seahorse::Model::Shapes::Map then stub_map(shape, value || {})
145
+ else stub_scalar(shape, value)
146
+ end
147
+ end
148
+
149
+ def stub_structure(shape, hash)
150
+ if hash
151
+ structure_obj(shape, hash)
152
+ else
153
+ nil
154
+ end
155
+ end
156
+
157
+ def structure_obj(shape, hash)
158
+ stubs = Structure.new(shape.member_names)
159
+ shape.members.each do |member_name, member_shape|
160
+ value = structure_value(shape, member_name, member_shape, hash)
161
+ stubs[member_name] = stub(member_shape, value)
162
+ end
163
+ stubs
164
+ end
165
+
166
+ def structure_value(shape, member_name, member_shape, hash)
167
+ if hash.key?(member_name)
168
+ hash[member_name]
169
+ elsif
170
+ Seahorse::Model::Shapes::Structure === member_shape &&
171
+ shape.required.include?(member_name)
172
+ then
173
+ {}
174
+ else
175
+ nil
176
+ end
177
+ end
178
+
179
+ def stub_list(shape, array)
180
+ stubs = []
181
+ array.each do |value|
182
+ stubs << stub(shape.member, value)
183
+ end
184
+ stubs
185
+ end
186
+
187
+ def stub_map(shape, value)
188
+ stubs = {}
189
+ value.each do |key, value|
190
+ stubs[key] = stub(shape.value, value)
191
+ end
192
+ stubs
193
+ end
194
+
195
+ def stub_scalar(shape, value)
196
+ if value.nil?
197
+ case shape
198
+ when Seahorse::Model::Shapes::String then shape.name
199
+ when Seahorse::Model::Shapes::Integer then 0
200
+ when Seahorse::Model::Shapes::Float then 0.0
201
+ when Seahorse::Model::Shapes::Boolean then false
202
+ when Seahorse::Model::Shapes::Timestamp then Time.now
203
+ else nil
204
+ end
205
+ else
206
+ value
207
+ end
208
+ end
209
+
210
+ def empty_stub(data)
211
+ if data.empty?
212
+ Structure.new(data)
213
+ else
214
+ msg = 'unable to generate a stubbed response from the given data; '
215
+ msg << 'this operation does not return data'
216
+ raise ArgumentError, msg
217
+ end
218
+ end
219
+
220
+ def validate_data(data)
221
+ args = [@shape, { validate_required:false }]
222
+ Seahorse::Client::ParamValidator.new(*args).validate!(data)
223
+ end
224
+
225
+ end
226
+ end
227
+ end
@@ -24,13 +24,23 @@ module Aws
24
24
 
25
25
  def format(obj)
26
26
  case obj
27
+ when Hash
28
+ obj.each.with_object(m:{}) do |(key, value), map|
29
+ map[:m][key.to_s] = format(value)
30
+ end
31
+ when Array
32
+ obj.each.with_object(l:[]) do |value, list|
33
+ list[:l] << format(value)
34
+ end
27
35
  when String then { s: obj }
28
36
  when Numeric then { n: obj.to_s }
29
37
  when StringIO, IO then { b: obj.read }
30
38
  when Set then format_set(obj)
39
+ when true, false then { bool: obj }
40
+ when nil then { null: true }
31
41
  else
32
- msg = "unsupported type, expected Set, String, Numeric, or "
33
- msg << "IO object, got #{obj.class.name}"
42
+ msg = "unsupported type, expected Hash, Array, Set, String, Numeric, "
43
+ msg << "IO, true, false, or nil, got #{obj.class.name}"
34
44
  raise ArgumentError, msg
35
45
  end
36
46
  end
@@ -55,9 +65,16 @@ module Aws
55
65
  def format(obj)
56
66
  type, value = extract_type_and_value(obj)
57
67
  case type
68
+ when :m
69
+ value.each.with_object({}) do |(key, value), map|
70
+ map[key] = format(value)
71
+ end
72
+ when :l then value.map { |v| format(v) }
58
73
  when :s then value
59
74
  when :n then BigDecimal.new(value)
60
75
  when :b then StringIO.new(value)
76
+ when :null then nil
77
+ when :bool then value
61
78
  when :ss then Set.new(value)
62
79
  when :ns then Set.new(value.map { |n| BigDecimal.new(n) })
63
80
  when :bs then Set.new(value.map { |b| StringIO.new(b) })
@@ -22,6 +22,8 @@ module Aws
22
22
  ]
23
23
 
24
24
  # @param [Hash] options
25
+ # @option options [Integer] :retries (0) Number of times to retry
26
+ # when retrieving credentials.
25
27
  # @option options [String] :ip_address ('169.254.169.254')
26
28
  # @option options [Integer] :port (80)
27
29
  # @option options [Float] :http_open_timeout (1)
@@ -30,6 +32,7 @@ module Aws
30
32
  # traces are sent to this object. You can specify something
31
33
  # like $stdout.
32
34
  def initialize options = {}
35
+ @retries = options[:retries] || 0
33
36
  @ip_address = options[:ip_address] || '169.254.169.254'
34
37
  @port = options[:port] || 80
35
38
  @http_open_timeout = options[:http_open_timeout] || 1
@@ -39,6 +42,10 @@ module Aws
39
42
  refresh!
40
43
  end
41
44
 
45
+ # @return [Integer] The number of times to retry failed atttempts to
46
+ # fetch credentials from the instance metadata service. Defaults to 0.
47
+ attr_reader :retries
48
+
42
49
  # @return [String,nil]
43
50
  def access_key_id
44
51
  refresh_if_stale
@@ -86,13 +93,26 @@ module Aws
86
93
  end
87
94
 
88
95
  def get_credentials
89
- open_connection do |conn|
90
- path = '/latest/meta-data/iam/security-credentials/'
91
- profile_name = http_get(conn, path).lines.first.strip
92
- http_get(conn, path + profile_name)
96
+ failed_attempts = 0
97
+ begin
98
+ open_connection do |conn|
99
+ path = '/latest/meta-data/iam/security-credentials/'
100
+ profile_name = http_get(conn, path).lines.first.strip
101
+ http_get(conn, path + profile_name)
102
+ end
103
+ rescue *FAILURES => e
104
+ if failed_attempts < @retries
105
+ backoff(failed_attempts)
106
+ failed_attempts += 1
107
+ retry
108
+ else
109
+ '{}'
110
+ end
93
111
  end
94
- rescue *FAILURES => e
95
- '{}'
112
+ end
113
+
114
+ def backoff(failed_attempts)
115
+ Kernel.sleep(2 ** failed_attempts)
96
116
  end
97
117
 
98
118
  def open_connection
@@ -21,7 +21,12 @@ module Aws
21
21
  # id: 'uuid',
22
22
  # age: 35,
23
23
  # tags: Set.new(%w(simple attributes)),
24
- # data: StringIO.new('data')
24
+ # data: StringIO.new('data'),
25
+ # scores: [5, 4.5, 4.9, nil],
26
+ # name: {
27
+ # first: 'John',
28
+ # last: 'Doe',
29
+ # }
25
30
  # }
26
31
  # )
27
32
  #
@@ -36,6 +41,20 @@ module Aws
36
41
  # 'age' => { n: '35' },
37
42
  # 'tags' => { ss: ['simple', 'attributes'] },
38
43
  # 'data' => { b: 'data' },
44
+ # 'scores' => {
45
+ # l: [
46
+ # { n: '5' },
47
+ # { n: '4.5' },
48
+ # { n: '4.9' },
49
+ # { null: true },
50
+ # ]
51
+ # },
52
+ # 'name' => {
53
+ # m: {
54
+ # 'first' => { s: 'John' },
55
+ # 'last' => { s: 'Doe' },
56
+ # }
57
+ # }
39
58
  # }
40
59
  # )
41
60
  #
@@ -49,7 +68,12 @@ module Aws
49
68
  # id: 'uuid',
50
69
  # age: 35,
51
70
  # tags: Set.new(%w(simple attributes)),
52
- # data: StringIO.new('data')
71
+ # data: StringIO.new('data'),
72
+ # scores: [5, 4.5, 4.9, nil],
73
+ # name: {
74
+ # first: 'John',
75
+ # last: 'Doe',
76
+ # }
53
77
  # }
54
78
  #
55
79
  # With this plugin **disabled**, `simple_attributes: false`:
@@ -58,15 +82,14 @@ module Aws
58
82
  # resp = dynamodb.get(table_name: 'aws-sdk', key: { 'id' => { s: 'uuid' }})
59
83
  # resp.item
60
84
  # # {
61
- # # "id"=> <struct s='uuid', n=nil, b=nil, ss=nil, ns=nil, bs=nil>,
62
- # # "age"=> <struct s=nil, n="35", b=nil, ss=nil, ns=nil, bs=nil>,
63
- # # "tags"=> <struct s=nil, n=nil, b=nil, ss=['simple', 'attributes'], ns=nil, bs=nil>,
64
- # # "data"=> <struct s=nil, n=nil, b="data", ss=nil, ns=nil, bs=nil>,
85
+ # # "id"=> <struct s='uuid', n=nil, b=nil, ss=nil, ns=nil, bs=nil, m=nil, l=nil, null=nil, bool=nil>
86
+ # # "age"=> <struct s=nil, n="35", b=nil, ss=nil, ns=nil, bs=nil, m=nil, l=nil, null=nil, bool=nil>
87
+ # # ...
65
88
  # # }
66
89
  #
67
90
  # @seahorse.client.option [Boolean] :simple_attributes (true)
68
- # Enables working with DynamoDB attribute values using simple
69
- # Ruby natives.
91
+ # Enables working with DynamoDB attribute values using
92
+ # hashes, arrays, sets, integers, floats, booleans, and nil.
70
93
  #
71
94
  # Disabling this option requires that all attribute values have
72
95
  # their types specified, e.g. `{ s: 'abc' }` instead of simply
@@ -0,0 +1,51 @@
1
+ module Aws
2
+ module Plugins
3
+
4
+ # @seahorse.client.option [Boolean] :stub_responses (false)
5
+ # Causes the client to return stubbed responses. By default
6
+ # fake responses are generated and returned. You can specify
7
+ # the response data to return or errors to raise by calling
8
+ # {ClientStubs#stub_responses}. See {ClientStubs} for more information.
9
+ #
10
+ # ** Please note ** When response stubbing is enabled, no HTTP
11
+ # requests are made, and retries are disabled.
12
+ #
13
+ class StubResponses < Seahorse::Client::Plugin
14
+
15
+ option(:stub_responses, false)
16
+
17
+ def add_handlers(handlers, config)
18
+ handlers.add(Handler, step: :send) if config.stub_responses
19
+ end
20
+
21
+ def after_initialize(client)
22
+ # disable retries when stubbing responses
23
+ client.config.retry_limit = 0 if client.config.stub_responses
24
+ end
25
+
26
+ class Handler < Seahorse::Client::Handler
27
+
28
+ def call(context)
29
+ response = Seahorse::Client::Response.new(context: context)
30
+ apply_stub(response, context.client.next_stub(context.operation_name))
31
+ response
32
+ end
33
+
34
+ private
35
+
36
+ def apply_stub(resp, stub)
37
+ if Exception === stub
38
+ resp.error = stub
39
+ elsif Class === stub && stub.ancestors.include?(Errors::ServiceError)
40
+ resp.error = stub.new(resp.context, 'stubbed error')
41
+ elsif Class === stub && stub.ancestors.include?(Exception)
42
+ resp.error = stub.new
43
+ else
44
+ resp.data = stub
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module Aws
2
- VERSION = '2.0.1'
2
+ VERSION = '2.0.2'
3
3
  end
@@ -79,7 +79,7 @@ module Aws
79
79
  def parse_shape(shape, value)
80
80
  if value.nil?
81
81
  case shape
82
- when Seahorse::Model::Shapes::Structure then nil
82
+ when Seahorse::Model::Shapes::Structure then structure(shape, {})
83
83
  when Seahorse::Model::Shapes::Map then {}
84
84
  when Seahorse::Model::Shapes::List then []
85
85
  when Seahorse::Model::Shapes::String then ''
@@ -56,38 +56,8 @@ module Seahorse
56
56
  self.class.api.operation_names
57
57
  end
58
58
 
59
- # @api private
60
- def respond_to?(method_name, *args)
61
- if request_method?(method_name)
62
- true
63
- else
64
- super
65
- end
66
- end
67
-
68
- # @api private
69
- def method_missing(method_name, *args, &block)
70
- if request_method?(method_name)
71
- make_request(method_name, *args, &block)
72
- else
73
- super
74
- end
75
- end
76
-
77
59
  private
78
60
 
79
- # @return [Boolean] Returns `true` if the method name is an API operation.t
80
- def request_method?(method_name)
81
- operation_names.include?(method_name.to_sym)
82
- end
83
-
84
- # Builds and sends a request.
85
- def make_request(name, *args, &block)
86
- params = args[0] || {}
87
- options = args[1] || {}
88
- build_request(name, params).send_request(options, &block)
89
- end
90
-
91
61
  # Constructs a {Configuration} object and gives each plugin the
92
62
  # opportunity to register options with default values.
93
63
  def build_config(plugins, options)
@@ -214,6 +184,8 @@ module Seahorse
214
184
  else
215
185
  @api = api
216
186
  end
187
+ define_operation_methods
188
+ @api
217
189
  end
218
190
 
219
191
  # @option options [Model::Api, Hash] :api ({})
@@ -232,6 +204,16 @@ module Seahorse
232
204
 
233
205
  private
234
206
 
207
+ def define_operation_methods
208
+ @api.operation_names.each do |method_name|
209
+ define_method(method_name) do |*args, &block|
210
+ params = args[0] || {}
211
+ options = args[1] || {}
212
+ build_request(method_name, params).send_request(options, &block)
213
+ end
214
+ end
215
+ end
216
+
235
217
  def build_plugins
236
218
  plugins.map { |plugin| plugin.is_a?(Class) ? plugin.new : plugin }
237
219
  end
@@ -2,11 +2,13 @@ require 'stringio'
2
2
  require 'date'
3
3
  require 'time'
4
4
  require 'tempfile'
5
+ require 'thread'
5
6
 
6
7
  module Seahorse
7
8
  module Client
8
9
  class ParamConverter
9
10
 
11
+ @mutex = Mutex.new
10
12
  @converters = Hash.new { |h,k| h[k] = {} }
11
13
 
12
14
  # @param [Model::Shapes::Shape] shape
@@ -110,7 +112,11 @@ module Seahorse
110
112
 
111
113
  def converter_for(shape_class, value)
112
114
  unless @converters[shape_class].key?(value.class)
113
- @converters[shape_class][value.class] = find(shape_class, value)
115
+ @mutex.synchronize {
116
+ unless @converters[shape_class].key?(value.class)
117
+ @converters[shape_class][value.class] = find(shape_class, value)
118
+ end
119
+ }
114
120
  end
115
121
  @converters[shape_class][value.class]
116
122
  end
@@ -10,8 +10,10 @@ module Seahorse
10
10
  end
11
11
 
12
12
  # @param [Model::Shapes::Shape] shape
13
- def initialize(shape)
13
+ # @option options [Boolean] :validate_required (true)
14
+ def initialize(shape, options = {})
14
15
  @shape = shape || Seahorse::Model::Shapes::Structure.new
16
+ @validate_required = options[:validate_required] != false
15
17
  end
16
18
 
17
19
  # @param [Hash] params
@@ -29,10 +31,12 @@ module Seahorse
29
31
  return unless hash?(values, errors, context)
30
32
 
31
33
  # ensure required members are present
32
- structure.required.each do |member_name|
33
- if values[member_name].nil?
34
- param = "#{context}[#{member_name.inspect}]"
35
- errors << "missing required parameter #{param}"
34
+ if @validate_required
35
+ structure.required.each do |member_name|
36
+ if values[member_name].nil?
37
+ param = "#{context}[#{member_name.inspect}]"
38
+ errors << "missing required parameter #{param}"
39
+ end
36
40
  end
37
41
  end
38
42
 
@@ -66,20 +66,23 @@ module Seahorse
66
66
  # @return [Response]
67
67
  #
68
68
  def send_request(options = {}, &block)
69
- set_target(options, &block)
70
- resp = @handlers.to_stack.call(@context)
69
+ set_response_target(options, &block)
70
+ @handlers.to_stack.call(@context)
71
+ ensure
71
72
  close_managed_files
72
- resp
73
73
  end
74
74
 
75
75
  private
76
76
 
77
- def set_target(options, &block)
78
- if target = options[:target] || block
77
+ def set_response_target(options, &block)
78
+ target = options[:target]
79
+ target ||= block
80
+ target ||= context.params.delete(:response_target)
81
+ if target
79
82
  @context.http_response.body =
80
83
  case target
81
84
  when Proc then BlockIO.new(&target)
82
- when String, Pathname then ManagedFile.new(target, 'r+b')
85
+ when String, Pathname then ManagedFile.new(target, 'w+b')
83
86
  else target
84
87
  end
85
88
  end
@@ -220,7 +220,11 @@ module Seahorse
220
220
 
221
221
  # @return [Shape, nil]
222
222
  def payload_member
223
- @payload_member ||= member(payload)
223
+ if payload
224
+ @payload_member ||= member(payload)
225
+ else
226
+ nil
227
+ end
224
228
  end
225
229
 
226
230
  # @param [Symbol] name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-sdk-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
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: 2014-09-29 00:00:00.000000000 Z
11
+ date: 2014-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -82,6 +82,7 @@ files:
82
82
  - lib/aws-sdk-core/api/service_customizations.rb
83
83
  - lib/aws-sdk-core/autoscaling.rb
84
84
  - lib/aws-sdk-core/client.rb
85
+ - lib/aws-sdk-core/client_stubs.rb
85
86
  - lib/aws-sdk-core/cloudformation.rb
86
87
  - lib/aws-sdk-core/cloudfront.rb
87
88
  - lib/aws-sdk-core/cloudsearch.rb
@@ -152,6 +153,7 @@ files:
152
153
  - lib/aws-sdk-core/plugins/s3_sse_cpk.rb
153
154
  - lib/aws-sdk-core/plugins/s3_url_encoded_keys.rb
154
155
  - lib/aws-sdk-core/plugins/sqs_queue_urls.rb
156
+ - lib/aws-sdk-core/plugins/stub_responses.rb
155
157
  - lib/aws-sdk-core/plugins/swf_read_timeouts.rb
156
158
  - lib/aws-sdk-core/plugins/user_agent.rb
157
159
  - lib/aws-sdk-core/query/ec2_param_builder.rb
@@ -347,4 +349,3 @@ signing_key:
347
349
  specification_version: 4
348
350
  summary: AWS SDK for Ruby - Core
349
351
  test_files: []
350
- has_rdoc: