right_aws 2.1.0 → 3.0.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.
- data/History.txt +38 -14
- data/Manifest.txt +1 -0
- data/Rakefile +34 -8
- data/lib/awsbase/right_awsbase.rb +176 -12
- data/lib/awsbase/version.rb +2 -2
- data/lib/ec2/right_ec2.rb +120 -37
- data/lib/ec2/right_ec2_ebs.rb +57 -41
- data/lib/ec2/right_ec2_images.rb +73 -44
- data/lib/ec2/right_ec2_instances.rb +158 -155
- data/lib/ec2/right_ec2_reserved_instances.rb +36 -26
- data/lib/ec2/right_ec2_security_groups.rb +261 -166
- data/lib/ec2/right_ec2_spot_instances.rb +72 -75
- data/lib/ec2/right_ec2_vpc.rb +15 -8
- data/lib/ec2/right_ec2_vpc2.rb +381 -0
- data/lib/elb/right_elb_interface.rb +3 -1
- data/lib/emr/right_emr_interface.rb +727 -0
- data/lib/rds/right_rds_interface.rb +102 -27
- data/lib/right_aws.rb +4 -1
- data/lib/route_53/right_route_53_interface.rb +24 -14
- data/lib/s3/right_s3.rb +16 -15
- data/lib/s3/right_s3_interface.rb +42 -10
- data/lib/sdb/right_sdb_interface.rb +14 -5
- data/lib/sns/right_sns_interface.rb +286 -0
- data/test/README.mdown +39 -0
- data/test/awsbase/test_right_awsbase.rb +0 -1
- data/test/ec2/test_right_ec2.rb +0 -1
- data/test/elb/test_helper.rb +2 -0
- data/test/elb/test_right_elb.rb +43 -0
- data/test/route_53/fixtures/a_record.xml +18 -0
- data/test/route_53/fixtures/alias_record.xml +18 -0
- data/test/route_53/test_helper.rb +2 -0
- data/test/route_53/test_right_route_53.rb +141 -0
- data/test/s3/test_right_s3.rb +97 -39
- data/test/sns/test_helper.rb +2 -0
- data/test/sns/test_right_sns.rb +153 -0
- data/test/ts_right_aws.rb +1 -0
- metadata +28 -9
@@ -38,6 +38,17 @@ module RightAws
|
|
38
38
|
ONE_YEAR_IN_SECONDS = 365 * 24 * 60 * 60
|
39
39
|
AMAZON_HEADER_PREFIX = 'x-amz-'
|
40
40
|
AMAZON_METADATA_PREFIX = 'x-amz-meta-'
|
41
|
+
S3_REQUEST_PARAMETERS = [ 'acl',
|
42
|
+
'location',
|
43
|
+
'logging', # this one is beta, no support for now
|
44
|
+
'response-content-type',
|
45
|
+
'response-content-language',
|
46
|
+
'response-expires',
|
47
|
+
'response-cache-control',
|
48
|
+
'response-content-disposition',
|
49
|
+
'response-content-encoding',
|
50
|
+
'torrent' ].sort
|
51
|
+
|
41
52
|
|
42
53
|
@@bench = AwsBenchmarkingBlock.new
|
43
54
|
def self.bench_xml
|
@@ -107,13 +118,20 @@ module RightAws
|
|
107
118
|
s3_headers.sort { |a, b| a[0] <=> b[0] }.each do |key, value|
|
108
119
|
out_string << (key[/^#{AMAZON_HEADER_PREFIX}/o] ? "#{key}:#{value}\n" : "#{value}\n")
|
109
120
|
end
|
110
|
-
|
121
|
+
# ignore everything after the question mark by default...
|
111
122
|
out_string << path.gsub(/\?.*$/, '')
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
123
|
+
# ... unless there is a parameter that we care about.
|
124
|
+
S3_REQUEST_PARAMETERS.each do |parameter|
|
125
|
+
if path[/[&?]#{parameter}(=[^&]*)?($|&)/]
|
126
|
+
if $1
|
127
|
+
value = CGI::unescape($1)
|
128
|
+
else
|
129
|
+
value = ''
|
130
|
+
end
|
131
|
+
out_string << (out_string[/[?]/] ? "&#{parameter}#{value}" : "?#{parameter}#{value}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
117
135
|
out_string
|
118
136
|
end
|
119
137
|
|
@@ -135,6 +153,7 @@ module RightAws
|
|
135
153
|
# extract bucket name and check it's dns compartibility
|
136
154
|
headers[:url].to_s[%r{^([a-z0-9._-]*)(/[^?]*)?(\?.+)?}i]
|
137
155
|
bucket_name, key_path, params_list = $1, $2, $3
|
156
|
+
key_path = key_path.gsub( '%2F', '/' ) if key_path
|
138
157
|
# select request model
|
139
158
|
if !param(:no_subdomains) && is_dns_bucket?(bucket_name)
|
140
159
|
# fix a path
|
@@ -836,6 +855,7 @@ module RightAws
|
|
836
855
|
def generate_link(method, headers={}, expires=nil) #:nodoc:
|
837
856
|
# calculate request data
|
838
857
|
server, path, path_to_sign = fetch_request_params(headers)
|
858
|
+
path_to_sign = CGI.unescape(path_to_sign)
|
839
859
|
# expiration time
|
840
860
|
expires ||= DEFAULT_EXPIRES_AFTER
|
841
861
|
expires = Time.now.utc + expires if expires.is_a?(Fixnum) && (expires < ONE_YEAR_IN_SECONDS)
|
@@ -844,7 +864,7 @@ module RightAws
|
|
844
864
|
headers.each{ |key, value| headers.delete(key) if (value.nil? || key.is_a?(Symbol)) }
|
845
865
|
#generate auth strings
|
846
866
|
auth_string = canonical_string(method, path_to_sign, headers, expires)
|
847
|
-
signature = CGI::escape(
|
867
|
+
signature = CGI::escape(AwsUtils::sign( @aws_secret_access_key, auth_string))
|
848
868
|
# path building
|
849
869
|
addon = "Signature=#{signature}&Expires=#{expires}&AWSAccessKeyId=#{@aws_access_key_id}"
|
850
870
|
path += path[/\?/] ? "&#{addon}" : "?#{addon}"
|
@@ -916,8 +936,20 @@ module RightAws
|
|
916
936
|
# s3.get_link('my_awesome_bucket',key) #=> https://s3.amazonaws.com:443/my_awesome_bucket/asia%2Fcustomers?Signature=QAO...
|
917
937
|
#
|
918
938
|
# see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html
|
919
|
-
|
920
|
-
|
939
|
+
#
|
940
|
+
# To specify +response+-* parameters, define them in the response_params hash:
|
941
|
+
#
|
942
|
+
# s3.get_link('my_awesome_bucket',key,nil,{},{ "response-content-disposition" => "attachment; filename=caf�.png", "response-content-type" => "image/png"})
|
943
|
+
#
|
944
|
+
# #=> https://s3.amazonaws.com:443/my_awesome_bucket/asia%2Fcustomers?response-content-disposition=attachment%3B%20filename%3Dcaf%25C3%25A9.png&response-content-type=image%2Fpng&Signature=wio...
|
945
|
+
#
|
946
|
+
def get_link(bucket, key, expires=nil, headers={}, response_params={})
|
947
|
+
if response_params.size > 0
|
948
|
+
response_params = '?' + response_params.map { |k, v| "#{k}=#{CGI::escape(v).gsub(/[+]/, '%20')}" }.join('&')
|
949
|
+
else
|
950
|
+
response_params = ''
|
951
|
+
end
|
952
|
+
generate_link('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}#{response_params}"), expires)
|
921
953
|
rescue
|
922
954
|
on_exception
|
923
955
|
end
|
@@ -1171,7 +1203,7 @@ module RightAws
|
|
1171
1203
|
def headers_to_string(headers)
|
1172
1204
|
result = {}
|
1173
1205
|
headers.each do |key, value|
|
1174
|
-
value = value.
|
1206
|
+
value = value.first if value.is_a?(Array) && value.size<2
|
1175
1207
|
result[key] = value
|
1176
1208
|
end
|
1177
1209
|
result
|
@@ -33,7 +33,7 @@ module RightAws
|
|
33
33
|
DEFAULT_PORT = 443
|
34
34
|
DEFAULT_PROTOCOL = 'https'
|
35
35
|
DEFAULT_PATH = '/'
|
36
|
-
API_VERSION = '
|
36
|
+
API_VERSION = '2009-04-15'
|
37
37
|
DEFAULT_NIL_REPRESENTATION = 'nil'
|
38
38
|
|
39
39
|
@@bench = AwsBenchmarkingBlock.new
|
@@ -399,12 +399,21 @@ module RightAws
|
|
399
399
|
# :box_usage => "0.0000093222",
|
400
400
|
# :request_id => "81273d21-001-1111-b3f9-512d91d29ac8" }
|
401
401
|
#
|
402
|
+
# # request all attributes using a consistent read
|
403
|
+
# # see: http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/index.html?ConsistencySummary.html
|
404
|
+
# sdb.get_attributes('family', 'toys', nil, true) # => { :attributes => {"cat" => ["clew", "Jons_socks", "mouse"] },
|
405
|
+
# "Silvia" => ["beetle", "rolling_pin", "kids"],
|
406
|
+
# "Jon" => ["vacuum_cleaner", "hammer", "spade"]},
|
407
|
+
# :box_usage => "0.0000093222",
|
408
|
+
# :request_id => "81273d21-000-1111-b3f9-512d91d29ac8" }
|
409
|
+
#
|
402
410
|
# see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_GetAttributes.html
|
403
411
|
#
|
404
|
-
def get_attributes(domain_name, item_name, attribute_name=nil)
|
405
|
-
link = generate_request("GetAttributes", 'DomainName'
|
406
|
-
'ItemName'
|
407
|
-
'AttributeName'
|
412
|
+
def get_attributes(domain_name, item_name, attribute_name=nil, consistent_read=nil)
|
413
|
+
link = generate_request("GetAttributes", 'DomainName' => domain_name,
|
414
|
+
'ItemName' => item_name,
|
415
|
+
'AttributeName' => attribute_name,
|
416
|
+
'ConsistentRead' => consistent_read )
|
408
417
|
res = request_info(link, QSdbGetAttributesParser.new)
|
409
418
|
res[:attributes].each_value do |values|
|
410
419
|
values.collect! { |e| sdb_to_ruby(e) }
|
@@ -0,0 +1,286 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2007-2008 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
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
module RightAws
|
25
|
+
class SnsInterface < RightAwsBase
|
26
|
+
include RightAwsBaseInterface
|
27
|
+
|
28
|
+
DEFAULT_HOST = 'sns.us-east-1.amazonaws.com'
|
29
|
+
DEFAULT_PORT = 443
|
30
|
+
DEFAULT_PROTOCOL = 'https'
|
31
|
+
DEFAULT_SERVICE = '/'
|
32
|
+
REQUEST_TTL = 30
|
33
|
+
|
34
|
+
# Apparently boilerplate stuff
|
35
|
+
@@bench = AwsBenchmarkingBlock.new
|
36
|
+
def self.bench_xml
|
37
|
+
@@bench.xml
|
38
|
+
end
|
39
|
+
def self.bench_service
|
40
|
+
@@bench.service
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
|
44
|
+
if params[:region]
|
45
|
+
server = "sns.#{params[:region]}.amazonaws.com"
|
46
|
+
params.delete(:region)
|
47
|
+
else
|
48
|
+
server = DEFAULT_HOST
|
49
|
+
end
|
50
|
+
init({ :name => 'SNS',
|
51
|
+
:default_host => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).host : server,
|
52
|
+
:default_port => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).port : DEFAULT_PORT,
|
53
|
+
:default_service => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).path : DEFAULT_SERVICE,
|
54
|
+
:default_protocol => ENV['SNS_URL'] ? URI.parse(ENV['SNS_URL']).scheme : DEFAULT_PROTOCOL},
|
55
|
+
aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
|
56
|
+
aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
|
57
|
+
params)
|
58
|
+
end
|
59
|
+
|
60
|
+
# TODO: RJG - Seems like generate_request and generate_rest_request could be in a sub class?
|
61
|
+
# Generates a request hash for the sns API
|
62
|
+
def generate_request(action, params={}) # :nodoc:
|
63
|
+
# Sometimes we need to use queue uri (delete queue etc)
|
64
|
+
# In that case we will use Symbol key: 'param[:queue_url]'
|
65
|
+
service = params[:sns_url] ? URI(params[:sns_url]).path : '/'
|
66
|
+
# remove unset(=optional) and symbolyc keys
|
67
|
+
params.each{ |key, value| params.delete(key) if (value.nil? || key.is_a?(Symbol)) }
|
68
|
+
# prepare output hash
|
69
|
+
service_hash = { "Action" => action,
|
70
|
+
"Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
71
|
+
"AWSAccessKeyId" => @aws_access_key_id }
|
72
|
+
#"Version" => API_VERSION }
|
73
|
+
service_hash.update(params)
|
74
|
+
service_params = signed_service_params(@aws_secret_access_key, service_hash, :get, @params[:server], service)
|
75
|
+
request = Net::HTTP::Get.new("#{AwsUtils::URLencode(service)}?#{service_params}")
|
76
|
+
# prepare output hash
|
77
|
+
{ :request => request,
|
78
|
+
:server => @params[:server],
|
79
|
+
:port => @params[:port],
|
80
|
+
:protocol => @params[:protocol] }
|
81
|
+
end
|
82
|
+
|
83
|
+
# Generates a request hash for the REST API
|
84
|
+
def generate_rest_request(method, param) # :nodoc:
|
85
|
+
sns_uri = param[:sns_url] ? URI(param[:sns_url]).path : '/'
|
86
|
+
message = param[:message] # extract message body if nesessary
|
87
|
+
# remove unset(=optional) and symbolyc keys
|
88
|
+
param.each{ |key, value| param.delete(key) if (value.nil? || key.is_a?(Symbol)) }
|
89
|
+
# created request
|
90
|
+
param_to_str = param.to_a.collect{|key,val| key.to_s + "=" + CGI::escape(val.to_s) }.join("&")
|
91
|
+
param_to_str = "?#{param_to_str}" unless param_to_str.right_blank?
|
92
|
+
request = "Net::HTTP::#{method.capitalize}".right_constantize.new("#{sns_uri}#{param_to_str}")
|
93
|
+
request.body = message if message
|
94
|
+
# set main headers
|
95
|
+
request['content-md5'] = ''
|
96
|
+
request['Content-Type'] = 'text/plain'
|
97
|
+
request['Date'] = Time.now.httpdate
|
98
|
+
# generate authorization string
|
99
|
+
auth_string = "#{method.upcase}\n#{request['content-md5']}\n#{request['Content-Type']}\n#{request['Date']}\n#{CGI::unescape(sns_uri)}"
|
100
|
+
signature = AwsUtils::sign(@aws_secret_access_key, auth_string)
|
101
|
+
# set other headers
|
102
|
+
request['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
|
103
|
+
#request['AWS-Version'] = API_VERSION
|
104
|
+
# prepare output hash
|
105
|
+
{ :request => request,
|
106
|
+
:server => @params[:server],
|
107
|
+
:port => @params[:port],
|
108
|
+
:protocol => @params[:protocol] }
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sends request to Amazon and parses the response
|
112
|
+
# Raises AwsError if any banana happened
|
113
|
+
def request_info(request, parser) # :nodoc:
|
114
|
+
request_info_impl(:sns_connection, @@bench, request, parser)
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_topic(topic_name)
|
118
|
+
req_hash = generate_request('CreateTopic', 'Name' => topic_name)
|
119
|
+
request_info(req_hash, SnsCreateTopicParser.new)
|
120
|
+
end
|
121
|
+
|
122
|
+
def list_topics()
|
123
|
+
req_hash = generate_request('ListTopics')
|
124
|
+
request_info(req_hash, SnsListTopicsParser.new)
|
125
|
+
end
|
126
|
+
|
127
|
+
def delete_topic(topic_arn)
|
128
|
+
req_hash = generate_request('DeleteTopic', 'TopicArn' => topic_arn)
|
129
|
+
request_info(req_hash, RightHttp2xxParser.new)
|
130
|
+
end
|
131
|
+
|
132
|
+
def subscribe(topic_arn, protocol, endpoint)
|
133
|
+
req_hash = generate_request('Subscribe', 'TopicArn' => topic_arn, 'Protocol' => protocol, 'Endpoint' => endpoint)
|
134
|
+
request_info(req_hash, SnsSubscribeParser.new)
|
135
|
+
end
|
136
|
+
|
137
|
+
def unsubscribe(subscription_arn)
|
138
|
+
req_hash = generate_request('Unsubscribe', 'SubscriptionArn' => subscription_arn)
|
139
|
+
request_info(req_hash, RightHttp2xxParser.new)
|
140
|
+
end
|
141
|
+
|
142
|
+
def publish(topic_arn, message, subject)
|
143
|
+
req_hash = generate_request('Publish', 'TopicArn' => topic_arn, 'Message' => message, 'Subject' => subject)
|
144
|
+
request_info(req_hash, SnsPublishParser.new)
|
145
|
+
end
|
146
|
+
|
147
|
+
def set_topic_attribute(topic_arn, attribute_name, attribute_value)
|
148
|
+
if attribute_name != 'Policy' && attribute_name != 'DisplayName'
|
149
|
+
raise(ArgumentError, "The only values accepted for the attribute_name parameter are (Policy, DisplayName)")
|
150
|
+
end
|
151
|
+
req_hash = generate_request('SetTopicAttributes', 'TopicArn' => topic_arn, 'AttributeName' => attribute_name, 'AttributeValue' => attribute_value)
|
152
|
+
request_info(req_hash, RightHttp2xxParser.new)
|
153
|
+
end
|
154
|
+
|
155
|
+
def get_topic_attributes(topic_arn)
|
156
|
+
req_hash = generate_request('GetTopicAttributes', 'TopicArn' => topic_arn)
|
157
|
+
request_info(req_hash, SnsGetTopicAttributesParser.new)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Calls either the ListSubscriptions or ListSubscriptionsByTopic depending on whether or not the topic_arn parameter is provided.
|
161
|
+
def list_subscriptions(topic_arn = nil)
|
162
|
+
req_hash = topic_arn ? generate_request('ListSubscriptionsByTopic', 'TopicArn' => topic_arn) : generate_request('ListSubscriptions')
|
163
|
+
request_info(req_hash, SnsListSubscriptionsParser.new)
|
164
|
+
end
|
165
|
+
|
166
|
+
def confirm_subscription(topic_arn, token, authenticate_on_unsubscribe=false)
|
167
|
+
req_hash = generate_request('ConfirmSubscription', 'AuthenticateOnUnsubscribe' => authenticate_on_unsubscribe.to_s, 'Token' => token, 'TopicArn' => topic_arn)
|
168
|
+
request_info(req_hash, SnsConfirmSubscriptionParser.new)
|
169
|
+
end
|
170
|
+
|
171
|
+
def add_permission(topic_arn, label, acct_action_hash_ary)
|
172
|
+
n_hash = {
|
173
|
+
'TopicArn' => topic_arn,
|
174
|
+
'Label' => label
|
175
|
+
}
|
176
|
+
|
177
|
+
acct_action_hash_ary.each_with_index do |hash_val, idx|
|
178
|
+
n_hash["AWSAccountId.member.#{idx+1}"] = hash_val[:aws_account_id]
|
179
|
+
n_hash["ActionName.member.#{idx+1}"] = hash_val[:action]
|
180
|
+
end
|
181
|
+
|
182
|
+
req_hash = generate_request('AddPermission', n_hash)
|
183
|
+
request_info(req_hash, RightHttp2xxParser.new)
|
184
|
+
end
|
185
|
+
|
186
|
+
def remove_permission(topic_arn, label)
|
187
|
+
req_hash = generate_request('RemovePermission', 'TopicArn' => topic_arn, 'Label' => label)
|
188
|
+
request_info(req_hash, RightHttp2xxParser.new)
|
189
|
+
end
|
190
|
+
|
191
|
+
class SnsCreateTopicParser < RightAWSParser # :nodoc:
|
192
|
+
def reset
|
193
|
+
@result = ''
|
194
|
+
@request_id = ''
|
195
|
+
end
|
196
|
+
def tagend(name)
|
197
|
+
case name
|
198
|
+
when 'RequestId' then @result_id = @text
|
199
|
+
when 'TopicArn' then @result = @text
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
class SnsListTopicsParser < RightAWSParser # :nodoc:
|
205
|
+
def reset
|
206
|
+
@result = []
|
207
|
+
@request_id = ''
|
208
|
+
end
|
209
|
+
def tagstart(name, attributes)
|
210
|
+
@current_key = {} if name == 'member'
|
211
|
+
end
|
212
|
+
def tagend(name)
|
213
|
+
case name
|
214
|
+
when 'RequestId' then @result_id = @text
|
215
|
+
when 'TopicArn' then @current_key[:arn] = @text
|
216
|
+
when 'member' then @result << @current_key
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
class SnsSubscribeParser < RightAWSParser # :nodoc:
|
222
|
+
def reset
|
223
|
+
@result = ''
|
224
|
+
end
|
225
|
+
def tagend(name)
|
226
|
+
case name
|
227
|
+
when 'SubscriptionArn' then @result = @text
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class SnsPublishParser < RightAWSParser # :nodoc:
|
233
|
+
def reset
|
234
|
+
@result = ''
|
235
|
+
end
|
236
|
+
def tagend(name)
|
237
|
+
case name
|
238
|
+
when 'MessageId' then @result = @text
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class SnsGetTopicAttributesParser < RightAWSParser # :nodoc:
|
244
|
+
def reset
|
245
|
+
@result = {}
|
246
|
+
end
|
247
|
+
def tagend(name)
|
248
|
+
case name
|
249
|
+
when 'key' then @current_attr = @text
|
250
|
+
when 'value' then @result[@current_attr] = @text
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class SnsListSubscriptionsParser < RightAWSParser # :nodoc:
|
256
|
+
def reset
|
257
|
+
@result = []
|
258
|
+
end
|
259
|
+
def tagstart(name, attributes)
|
260
|
+
@current_key = {} if name == 'member'
|
261
|
+
end
|
262
|
+
def tagend(name)
|
263
|
+
case name
|
264
|
+
when 'TopicArn' then @current_key[:topic_arn] = @text
|
265
|
+
when 'Protocol' then @current_key[:protocol] = @text
|
266
|
+
when 'SubscriptionArn' then @current_key[:subscription_arn] = @text
|
267
|
+
when 'Owner' then @current_key[:owner] = @text
|
268
|
+
when 'Endpoint' then @current_key[:endpoint] = @text
|
269
|
+
when 'member' then @result << @current_key
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
class SnsConfirmSubscriptionParser < RightAWSParser # :nodoc:
|
275
|
+
def reset
|
276
|
+
@result = ''
|
277
|
+
end
|
278
|
+
def tagend(name)
|
279
|
+
case name
|
280
|
+
when 'SubscriptionArn' then @result = @text
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
end
|
data/test/README.mdown
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Notes and tips for developers
|
2
|
+
|
3
|
+
## Setting up credentials for testing
|
4
|
+
|
5
|
+
Before you can run any tests, you need to set up credentials (API key and secret) that
|
6
|
+
will be used when talking to AWS. The credentials are loaded in `test/test_credentials.rb`
|
7
|
+
and are expected to be found in `~/.rightscale/testcredentials.rb` and look like this:
|
8
|
+
|
9
|
+
TestCredentials.aws_access_key_id= 'AAAAAAAAAAAAAAAAAAAA'
|
10
|
+
TestCredentials.aws_secret_access_key= 'asdfasdfsadf'
|
11
|
+
TestCredentials.account_number= '???'
|
12
|
+
|
13
|
+
If you prefer to store your secret key in the OS X keychain, you can do this:
|
14
|
+
|
15
|
+
def secret_access_key_from_keychain (key_id)
|
16
|
+
dump = `security -q find-generic-password -a "#{key_id}" -g 2>&1`
|
17
|
+
dump[/password: "(.*)"/, 1]
|
18
|
+
end
|
19
|
+
|
20
|
+
TestCredentials.aws_access_key_id= 'AAAAAAAAAAAAAAAAAAAA'
|
21
|
+
TestCredentials.aws_secret_access_key= secret_access_key_from_keychain(TestCredentials.aws_access_key_id)
|
22
|
+
TestCredentials.account_number= '???'
|
23
|
+
|
24
|
+
## Running tests
|
25
|
+
|
26
|
+
There is no test suite that runs all tests. Each module is tested separately. E.g.,
|
27
|
+
to run the Load Balancer tests, run `rake testelb`. Run `rake -T` for a full list.
|
28
|
+
|
29
|
+
Some tests need to launch services on AWS to have something to test. This means two things:
|
30
|
+
|
31
|
+
1. Running all the tests will cost you money.
|
32
|
+
2. You will need to shut down some services separately once you are done, or things
|
33
|
+
will keep running and cost you money.
|
34
|
+
|
35
|
+
As an example, the ELB and Route 53 tests need a load balancer for testing. Starting a load balancer
|
36
|
+
for every test would make every test case cost as much as running the LB for one hour, so it makes
|
37
|
+
more sense to leave it running until it's no longer needed.
|
38
|
+
|
39
|
+
The ELB tests contain instructions for shutting down the load balancer.
|