right_aws_api 0.1.0

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 (37) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY +2 -0
  3. data/LICENSE +19 -0
  4. data/README.md +164 -0
  5. data/Rakefile +38 -0
  6. data/lib/cloud/aws/as/manager.rb +118 -0
  7. data/lib/cloud/aws/base/helpers/utils.rb +328 -0
  8. data/lib/cloud/aws/base/manager.rb +186 -0
  9. data/lib/cloud/aws/base/parsers/response_error.rb +117 -0
  10. data/lib/cloud/aws/base/routines/request_signer.rb +80 -0
  11. data/lib/cloud/aws/cf/manager.rb +171 -0
  12. data/lib/cloud/aws/cf/routines/request_signer.rb +70 -0
  13. data/lib/cloud/aws/cf/wrappers/default.rb +213 -0
  14. data/lib/cloud/aws/cfm/manager.rb +90 -0
  15. data/lib/cloud/aws/cw/manager.rb +113 -0
  16. data/lib/cloud/aws/eb/manager.rb +87 -0
  17. data/lib/cloud/aws/ec/manager.rb +91 -0
  18. data/lib/cloud/aws/ec2/manager.rb +222 -0
  19. data/lib/cloud/aws/elb/manager.rb +120 -0
  20. data/lib/cloud/aws/emr/manager.rb +86 -0
  21. data/lib/cloud/aws/iam/manager.rb +100 -0
  22. data/lib/cloud/aws/rds/manager.rb +110 -0
  23. data/lib/cloud/aws/route53/manager.rb +177 -0
  24. data/lib/cloud/aws/route53/routines/request_signer.rb +70 -0
  25. data/lib/cloud/aws/route53/wrappers/default.rb +132 -0
  26. data/lib/cloud/aws/s3/manager.rb +373 -0
  27. data/lib/cloud/aws/s3/parsers/response_error.rb +76 -0
  28. data/lib/cloud/aws/s3/routines/request_signer.rb +243 -0
  29. data/lib/cloud/aws/s3/wrappers/default.rb +315 -0
  30. data/lib/cloud/aws/sdb/manager.rb +150 -0
  31. data/lib/cloud/aws/sns/manager.rb +96 -0
  32. data/lib/cloud/aws/sqs/manager.rb +335 -0
  33. data/lib/right_aws_api.rb +45 -0
  34. data/lib/right_aws_api_version.rb +40 -0
  35. data/right_aws_api.gemspec +55 -0
  36. data/spec/describe_calls.rb +92 -0
  37. metadata +118 -0
@@ -0,0 +1,70 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ module CloudApi
26
+ module AWS
27
+ module CF
28
+
29
+ # API request signer for CF service.
30
+ class RequestSigner < CloudApi::Routine
31
+
32
+ # CF RequestSigner Error
33
+ class Error < CloudApi::Error
34
+ end
35
+
36
+ # Authenticates a CloudFront request
37
+ #
38
+ # @return [void]
39
+ #
40
+ # @example
41
+ # # qno example
42
+ #
43
+ def process
44
+ # Fix body
45
+ unless @data[:request][:body]._blank?
46
+ # Make sure 'content-type' is set if we have a body
47
+ @data[:request][:headers].set_if_blank('content-type', 'application/xml' )
48
+ # Fix body if it is a Hash instance
49
+ if @data[:request][:body].is_a?(Hash)
50
+ @data[:request][:body] = Utils::contentify_body(@data[:request][:body], @data[:request][:headers]['content-type'])
51
+ end
52
+ # Calculate 'content-md5' when possible (some API calls wanna have it set)
53
+ if @data[:request][:body].is_a?(String)
54
+ @data[:request][:headers]['content-md5'] = Base64::encode64(Digest::MD5::digest(@data[:request][:body])).strip
55
+ end
56
+ end
57
+ # Set date
58
+ @data[:request][:headers].set_if_blank('date', Time::now.utc.httpdate)
59
+ # Sign a request
60
+ signature = Utils::AWS::sign(@data[:credentials][:aws_secret_access_key], Utils::dearrayify(@data[:request][:headers]['date']))
61
+ @data[:request][:headers]['authorization'] = "AWS #{@data[:credentials][:aws_access_key_id]}:#{signature}"
62
+ # Set path
63
+ @data[:request][:path] = Utils::join_urn(@data[:connection][:uri].path, @data[:options][:api_version], @data[:request][:relative_path], @data[:request][:params])
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,213 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module RightScale
25
+ module CloudApi
26
+ module AWS
27
+ module CF
28
+
29
+ # CF wrapper namespace
30
+ module Wrapper
31
+
32
+ # Default wrapper
33
+ module DEFAULT
34
+
35
+ # Defines QUERY API like methods for the service
36
+ #
37
+ # @return [void]
38
+ #
39
+ # @example
40
+ # # no example
41
+ #
42
+ def self.extended(base)
43
+
44
+ distribution_config = {
45
+ 'DistributionConfig' => {
46
+ '@xmlns' => "http://cloudfront.amazonaws.com/doc/2010-11-01/",
47
+ 'S3Origin' => :S3Origin,
48
+ 'CustomOrigin' => :CustomOrigin,
49
+ 'CallerReference' => :CallerReference,
50
+ 'CNAME' => :CNAME,
51
+ 'Comment' => :Comment,
52
+ 'Enabled' => :Enabled,
53
+ 'DefaultRootObject' => :DefaultRootObject,
54
+ 'Logging' => :Logging,
55
+ 'TrustedSigners' => :TrustedSigners,
56
+ 'RequiredProtocols{!remove-if-blank}' => {
57
+ 'Protocol' => :Protocol
58
+ }
59
+ }
60
+ }
61
+ distribution_config_defaults = {
62
+ :S3Origin => Utils::NONE,
63
+ :CustomOrigin => Utils::NONE,
64
+ :CNAME => Utils::NONE,
65
+ :Comment => Utils::NONE,
66
+ :DefaultRootObject => Utils::NONE,
67
+ :Logging => Utils::NONE,
68
+ :Protocol => Utils::NONE,
69
+ :TrustedSigners => Utils::NONE,
70
+ }
71
+
72
+
73
+ streaming_distribution_config = {
74
+ 'StreamingDistributionConfig' => {
75
+ '@xmlns' => "http://cloudfront.amazonaws.com/doc/2010-11-01/",
76
+ 'S3Origin' => :S3Origin,
77
+ 'CallerReference' => :CallerReference,
78
+ 'CNAME' => :CNAME,
79
+ 'Comment' => :Comment,
80
+ 'Enabled' => :Enabled,
81
+ 'Logging' => :Logging,
82
+ 'TrustedSigners' => :TrustedSigners
83
+ }
84
+ }
85
+ streaming_distribution_config_defaults = {
86
+ :CNAME => Utils::NONE,
87
+ :Comment => Utils::NONE,
88
+ :DefaultRootObject => Utils::NONE,
89
+ :TrustedSigners => Utils::NONE,
90
+ :Logging => Utils::NONE
91
+ }
92
+
93
+
94
+ origin_access_identity_config = {
95
+ 'CloudFrontOriginAccessIdentityConfig' => {
96
+ '@xmlns' => 'http://cloudfront.amazonaws.com/doc/2010-11-01/',
97
+ 'CallerReference' => :CallerReference,
98
+ 'Comment' => :Comment
99
+ }
100
+ }
101
+ origin_access_identity_defaults = {
102
+ :Comment => Utils::NONE
103
+ }
104
+
105
+
106
+ #-----------------
107
+ # Distributions
108
+ #-----------------
109
+
110
+
111
+ base.query_api_pattern 'ListDistributions', :get, 'distribution'
112
+
113
+
114
+ base.query_api_pattern 'GetDistribution', :get, 'distribution/{:DistributionId}'
115
+
116
+
117
+ base.query_api_pattern 'GetDistributionConfig', :get, 'distribution/{:DistributionId}/config'
118
+
119
+
120
+ base.query_api_pattern 'CreateDistribution', :post, 'distribution',
121
+ :body => distribution_config,
122
+ :defaults => distribution_config_defaults
123
+
124
+
125
+ base.query_api_pattern 'UpdateDistribution', :put, 'distribution/{:DistributionId}/config',
126
+ :body => distribution_config,
127
+ :defaults => distribution_config_defaults
128
+
129
+
130
+ base.query_api_pattern 'DeleteDistribution', :delete, 'distribution/{:DistributionId}'
131
+
132
+
133
+ #---------------------------
134
+ # Streaming Distributions
135
+ #--------------------------
136
+
137
+
138
+ base.query_api_pattern 'ListStreamingDistributions', :get, 'streaming-distribution'
139
+
140
+
141
+ base.query_api_pattern 'GetStreamingDistribution', :get, 'streaming-distribution/{:DistributionId}'
142
+
143
+
144
+ base.query_api_pattern 'GetStreamingDistributionConfig', :get, 'streaming-distribution/{:DistributionId}/config'
145
+
146
+
147
+ base.query_api_pattern 'CreateStreamingDistribution', :post, 'streaming-distribution',
148
+ :body => streaming_distribution_config,
149
+ :defaults => streaming_distribution_config_defaults
150
+
151
+
152
+ base.query_api_pattern 'UpdateStreamingDistribution', :put, 'streaming-distribution/{:DistributionId}/config',
153
+ :body => streaming_distribution_config,
154
+ :defaults => streaming_distribution_config_defaults
155
+
156
+
157
+ base.query_api_pattern 'DeleteStreamingDistribution', :delete, 'streaming-distribution/{:DistributionId}'
158
+
159
+
160
+ #---------------------------
161
+ # Origin Access Identities
162
+ #--------------------------
163
+
164
+
165
+ base.query_api_pattern 'ListOriginAccessIdentities', :get, 'origin-access-identity/cloudfront'
166
+
167
+
168
+ base.query_api_pattern 'GetOriginAccessIdentity', :get, 'origin-access-identity/cloudfront/{:IdentityId}'
169
+
170
+
171
+ base.query_api_pattern 'GetOriginAccessIdentityConfig', :get, 'origin-access-identity/cloudfront/{:IdentityId}/config'
172
+
173
+
174
+ base.query_api_pattern 'CreateOriginAccessIdentity', :post, 'origin-access-identity/cloudfront',
175
+ :body => origin_access_identity_config,
176
+ :defaults => origin_access_identity_defaults
177
+
178
+
179
+ base.query_api_pattern 'UpdateOriginAccessIdentity', :pup, 'origin-access-identity/cloudfront/{:IdentityId}/config',
180
+ :body => origin_access_identity_config,
181
+ :defaults => origin_access_identity_defaults
182
+
183
+
184
+ base.query_api_pattern 'DeleteOriginAccessIdentity', :delete, 'origin-access-identity/cloudfront/{:IdentityId}'
185
+
186
+
187
+ #---------------------------
188
+ # Origin Access Identities
189
+ #--------------------------
190
+
191
+
192
+ base.query_api_pattern 'ListInvalidations', :get, 'distribution/{:DistributionId}/invalidation'
193
+
194
+
195
+ base.query_api_pattern 'GetInvalidation', :get, 'distribution/{:DistributionId}/invalidation/{:InvalidationId}'
196
+
197
+
198
+ base.query_api_pattern 'CreateInvalidation', :post, 'distribution/{:DistributionId}/invalidation',
199
+ :body => {
200
+ 'InvalidationBatch' => {
201
+ 'CallerReference' => :CallerReference,
202
+ 'Path' => :Path
203
+ }
204
+ }
205
+
206
+ end
207
+
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,90 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require "cloud/aws/base/manager"
25
+
26
+ module RightScale
27
+ module CloudApi
28
+ module AWS
29
+
30
+ # CloudFormation namespace
31
+ module CFM
32
+
33
+ # Amazon CloudFormation (CFM) compatible manager (thread safe).
34
+ #
35
+ # @example
36
+ # require "right_aws_api"
37
+ #
38
+ # cfm = RightScale::CloudApi::AWS::CFM::Manager::new(key, secret, 'https://cloudformation.us-east-1.amazonaws.com')
39
+ #
40
+ # # Describe the description for the specified stack
41
+ # cfm.DescribeStacks #=>
42
+ # {"DescribeStacksResponse"=>
43
+ # {"@xmlns"=>"http://cloudformation.amazonaws.com/doc/2010-05-15/",
44
+ # "DescribeStacksResult"=>{"Stacks"=>nil},
45
+ # "ResponseMetadata"=>{"RequestId"=>"363a6f90-4f60-11e2-a5b9-17ce5ae131c1"}}}
46
+ #
47
+ # @example
48
+ # # Describe a custom stack:
49
+ # cfm.DescribeStacks('StackName' => 'MyStack')
50
+ #
51
+ # @example
52
+ # # Estimate template cost:
53
+ # cfm.EstimateTemplateCost('TemplateURL' => 'https://s3.amazonaws.com/cloudformation-samples-us-east-1/Drupal_Simple.template')
54
+ #
55
+ # @see ApiManager
56
+ # @see http://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_Operations.html
57
+ #
58
+ class Manager < AWS::Manager
59
+ end
60
+
61
+
62
+ # Amazon CloudFormation (CFM) compatible manager (thread unsafe).
63
+ #
64
+ # @see Manager
65
+ #
66
+ class ApiManager < AWS::ApiManager
67
+
68
+ # Default API version for CloudFormation service.
69
+ # To override the API version use :api_version key when instantiating a manager.
70
+ #
71
+ DEFAULT_API_VERSION = '2010-05-15'
72
+
73
+ error_pattern :abort_on_timeout, :path => /Action=(Create)/
74
+ error_pattern :retry, :response => /InternalError|Unavailable/i
75
+ error_pattern :disconnect_and_abort, :code => /5..|403|408/
76
+ error_pattern :disconnect_and_abort, :code => /4../, :if => Proc.new{ |opts| rand(100) < 10 }
77
+
78
+ set :response_error_parser => Parser::AWS::ResponseErrorV2
79
+
80
+ cache_pattern :verb => /get|post/,
81
+ :path => /Action=Describe|List/,
82
+ :if => Proc::new{ |o| (o[:params].keys - COMMON_QUERY_PARAMS)._blank? },
83
+ :key => Proc::new{ |o| o[:params]['Action'] },
84
+ :sign => Proc::new{ |o| o[:response].body.to_s.sub(%r{<RequestId>.+?</RequestId>}i,'') }
85
+ end
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,113 @@
1
+ #--
2
+ # Copyright (c) 2013 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require "cloud/aws/base/manager"
25
+
26
+ module RightScale
27
+ module CloudApi
28
+ module AWS
29
+
30
+ # CloudWatch namespace
31
+ module CW
32
+
33
+ # Amazon CloudWatch (CW) compatible manager (thread safe).
34
+ #
35
+ # @example
36
+ # require "right_aws_api"
37
+ #
38
+ # cw = RightScale::CloudApi::AWS::CW::Manager::new(key, secret, 'https://monitoring.us-east-1.amazonaws.com')
39
+ #
40
+ # # Get a list of valid metrics stored for the AWS account owner.
41
+ # cw.ListMetrics #=>
42
+ # {"ListMetricsResponse"=>
43
+ # {"@xmlns"=>"http://monitoring.amazonaws.com/doc/2010-08-01/",
44
+ # "ListMetricsResult"=>
45
+ # {"Metrics"=>
46
+ # {"member"=>
47
+ # [{"Dimensions"=>
48
+ # {"member"=>{"Name"=>"InstanceId", "Value"=>"i-29fc074d"}},
49
+ # "MetricName"=>"DiskReadOps",
50
+ # "Namespace"=>"AWS/EC2"},
51
+ # {"Dimensions"=>
52
+ # {"member"=>
53
+ # {"Name"=>"QueueName",
54
+ # "Value"=>"dano7_audit_queue_server_array_test"}},
55
+ # "MetricName"=>"ApproximateNumberOfMessagesDelayed",
56
+ # "Namespace"=>"AWS/SQS"},
57
+ # {"Dimensions"=>
58
+ # {"member"=>
59
+ # {"Name"=>"QueueName",
60
+ # "Value"=>"dano_input_queue_server_array_test"}},
61
+ # "MetricName"=>"ApproximateNumberOfMessagesNotVisible",
62
+ # "Namespace"=>"AWS/SQS"}]},
63
+ # "NextToken"=>
64
+ # "w9...xhCEA=="},
65
+ # "ResponseMetadata"=>{"RequestId"=>"bd188949-4f61-11e2-9a69-59e1411d80ca"}}}
66
+ #
67
+ # @example
68
+ # # Get alarms history.
69
+ # cw.DescribeAlarmHistory #=>
70
+ # {"DescribeAlarmHistoryResponse"=>
71
+ # {"@xmlns"=>"http://monitoring.amazonaws.com/doc/2010-08-01/",
72
+ # "DescribeAlarmHistoryResult"=>{"AlarmHistoryItems"=>nil},
73
+ # "ResponseMetadata"=>{"RequestId"=>"2f087a3b-4f62-11e2-b8d8-754622cf5638"}}}
74
+ #
75
+ # # Get a history for the specified alarm.
76
+ # cw.DescribeAlarmHistory('AlarmName' => 'MyAlarm')
77
+ #
78
+ # @see ApiManager
79
+ # @see http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/Welcome.html
80
+ #
81
+ class Manager < AWS::Manager
82
+ end
83
+
84
+
85
+ # Amazon CloudWatch (CW) compatible manager (thread unsafe).
86
+ #
87
+ # @see Manager
88
+ #
89
+ class ApiManager < AWS::ApiManager
90
+
91
+ # Default API version for CloudWatch service.
92
+ # To override the API version use :api_version key when instantiating a manager.
93
+ #
94
+ DEFAULT_API_VERSION = '2010-08-01'
95
+
96
+ error_pattern :abort_on_timeout, :path => /Action=(Put)/
97
+ error_pattern :retry, :response => /InternalError|Unavailable/i
98
+ error_pattern :disconnect_and_abort, :code => /5..|403|408/
99
+ error_pattern :disconnect_and_abort, :code => /4../, :if => Proc.new{ |opts| rand(100) < 10 }
100
+
101
+ set :response_error_parser => Parser::AWS::ResponseErrorV2
102
+
103
+ cache_pattern :verb => /get|post/,
104
+ :path => /Action=List/,
105
+ :if => Proc::new{ |o| (o[:params].keys - COMMON_QUERY_PARAMS)._blank? },
106
+ :key => Proc::new{ |o| o[:params]['Action'] },
107
+ :sign => Proc::new{ |o| o[:response].body.to_s.sub(%r{<RequestId>.+?</RequestId>}i,'') }
108
+ end
109
+ end
110
+
111
+ end
112
+ end
113
+ end