aws-sdk-core 2.0.1 → 2.0.2

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.
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: