kerryb-amazon-ec2 0.3.6

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/lib/EC2.rb ADDED
@@ -0,0 +1,270 @@
1
+ #--
2
+ # Amazon Web Services EC2 Query API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2008 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ %w[ base64 cgi openssl digest/sha1 net/https rexml/document time ostruct ].each { |f| require f }
12
+
13
+ # Require any lib files that we have bundled with this Ruby Gem in the lib/EC2 directory.
14
+ # Parts of the EC2 module and Base class are broken out into separate
15
+ # files for maintainability and are organized by the functional groupings defined
16
+ # in the EC2 API developers guide.
17
+ Dir[File.join(File.dirname(__FILE__), 'EC2/**/*.rb')].sort.each { |lib| require lib }
18
+
19
+ module EC2
20
+
21
+ # Which host FQDN will we connect to for all API calls to AWS?
22
+ # If EC2_URL is defined in the users ENV we can use that. It is
23
+ # expected that this var is set with something like:
24
+ # export EC2_URL='https://ec2.amazonaws.com'
25
+ #
26
+ if ENV['EC2_URL']
27
+ EC2_URL = ENV['EC2_URL']
28
+ VALID_HOSTS = ['https://ec2.amazonaws.com', 'https://us-east-1.ec2.amazonaws.com', 'https://eu-west-1.ec2.amazonaws.com']
29
+ raise ArgumentError, "Invalid EC2_URL environment variable : #{EC2_URL}" unless VALID_HOSTS.include?(EC2_URL)
30
+ DEFAULT_HOST = URI.parse(EC2_URL).host
31
+ else
32
+ # default US host
33
+ DEFAULT_HOST = 'ec2.amazonaws.com'
34
+ end
35
+
36
+ # This is the version of the API as defined by Amazon Web Services
37
+ API_VERSION = '2008-12-01'
38
+
39
+ # Builds the canonical string for signing. This strips out all '&', '?', and '='
40
+ # from the query string to be signed.
41
+ # Note: The parameters in the path passed in must already be sorted in
42
+ # case-insensitive alphabetical order and must not be url encoded.
43
+ def EC2.canonical_string(params, host = DEFAULT_HOST, method="POST", base="/")
44
+ # Sort, and encode parameters into a canonical string.
45
+ sorted_params = params.sort {|x,y| x[0] <=> y[0]}
46
+ encoded_params = sorted_params.collect do |p|
47
+ encoded = (CGI::escape(p[0].to_s) +
48
+ "=" + CGI::escape(p[1].to_s))
49
+ # Ensure spaces are encoded as '%20', not '+'
50
+ encoded.gsub('+', '%20')
51
+ end
52
+ sigquery = encoded_params.join("&")
53
+
54
+ # Generate the request description string
55
+ req_desc =
56
+ method + "\n" +
57
+ host + "\n" +
58
+ base + "\n" +
59
+ sigquery
60
+
61
+ end
62
+
63
+ # Encodes the given string with the secret_access_key, by taking the
64
+ # hmac-sha1 sum, and then base64 encoding it. Optionally, it will also
65
+ # url encode the result of that to protect the string if it's going to
66
+ # be used as a query string parameter.
67
+ def EC2.encode(secret_access_key, str, urlencode=true)
68
+ digest = OpenSSL::Digest::Digest.new('sha1')
69
+ b64_hmac =
70
+ Base64.encode64(
71
+ OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","")
72
+
73
+ if urlencode
74
+ return CGI::escape(b64_hmac)
75
+ else
76
+ return b64_hmac
77
+ end
78
+ end
79
+
80
+
81
+ #Introduction:
82
+ #
83
+ # The library exposes one main interface class, 'EC2::Base'.
84
+ # This class provides all the methods for using the EC2 service
85
+ # including the handling of header signing and other security issues .
86
+ # This class uses Net::HTTP to interface with the EC2 Query API interface.
87
+ #
88
+ #Required Arguments:
89
+ #
90
+ # :access_key_id => String (default : "")
91
+ # :secret_access_key => String (default : "")
92
+ #
93
+ #Optional Arguments:
94
+ #
95
+ # :use_ssl => Boolean (default : true)
96
+ # :server => String (default : 'ec2.amazonaws.com')
97
+ # :proxy_server => String (default : nil)
98
+ #
99
+ class Base
100
+
101
+ attr_reader :use_ssl, :server, :proxy_server, :port
102
+
103
+ def initialize( options = {} )
104
+
105
+ options = { :access_key_id => "",
106
+ :secret_access_key => "",
107
+ :use_ssl => true,
108
+ :server => DEFAULT_HOST,
109
+ :proxy_server => nil
110
+ }.merge(options)
111
+
112
+ @server = options[:server]
113
+ @proxy_server = options[:proxy_server]
114
+ @use_ssl = options[:use_ssl]
115
+
116
+ raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty?
117
+ raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty?
118
+ raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil?
119
+ raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false
120
+ raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty?
121
+
122
+ if options[:port]
123
+ # user-specified port
124
+ @port = options[:port]
125
+ elsif @use_ssl
126
+ # https
127
+ @port = 443
128
+ else
129
+ # http
130
+ @port = 80
131
+ end
132
+
133
+ @access_key_id = options[:access_key_id]
134
+ @secret_access_key = options[:secret_access_key]
135
+
136
+ # Use proxy server if defined
137
+ # Based on patch by Mathias Dalheimer. 20070217
138
+ proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new
139
+ @http = Net::HTTP::Proxy( proxy.host,
140
+ proxy.port,
141
+ proxy.user,
142
+ proxy.password).new(options[:server], @port)
143
+
144
+ @http.use_ssl = @use_ssl
145
+
146
+ # Don't verify the SSL certificates. Avoids SSL Cert warning in log on every GET.
147
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
148
+
149
+ end
150
+
151
+
152
+ private
153
+
154
+ # pathlist is a utility method which takes a key string and and array as input.
155
+ # It converts the array into a Hash with the hash key being 'Key.n' where
156
+ # 'n' increments by 1 for each iteration. So if you pass in args
157
+ # ("ImageId", ["123", "456"]) you should get
158
+ # {"ImageId.1"=>"123", "ImageId.2"=>"456"} returned.
159
+ def pathlist(key, arr)
160
+ params = {}
161
+ arr.each_with_index do |value, i|
162
+ params["#{key}.#{i+1}"] = value
163
+ end
164
+ params
165
+ end
166
+
167
+
168
+ # Make the connection to AWS EC2 passing in our request. This is generally called from
169
+ # within a 'Response' class object or one of its sub-classes so the response is interpreted
170
+ # in its proper context. See lib/EC2/responses.rb
171
+ def make_request(action, params, data='')
172
+
173
+ @http.start do
174
+
175
+ # remove any keys that have nil or empty values
176
+ params.reject! { |key, value| value.nil? or value.empty?}
177
+
178
+ params.merge!( {"Action" => action,
179
+ "SignatureVersion" => "2",
180
+ "SignatureMethod" => 'HmacSHA1',
181
+ "AWSAccessKeyId" => @access_key_id,
182
+ "Version" => API_VERSION,
183
+ "Timestamp"=>Time.now.getutc.iso8601} )
184
+
185
+ sig = get_aws_auth_param(params, @secret_access_key)
186
+
187
+ query = params.sort.collect do |param|
188
+ CGI::escape(param[0]) + "=" + CGI::escape(param[1])
189
+ end.join("&") + "&Signature=" + sig
190
+
191
+ req = Net::HTTP::Post.new("/")
192
+ req.content_type = 'application/x-www-form-urlencoded'
193
+ req['User-Agent'] = "github-amazon-ec2-ruby-gem"
194
+
195
+ response = @http.request(req, query)
196
+
197
+ # Make a call to see if we need to throw an error based on the response given by EC2
198
+ # All error classes are defined in EC2/exceptions.rb
199
+ ec2_error?(response)
200
+
201
+ return response
202
+
203
+ end
204
+
205
+ end
206
+
207
+ # Set the Authorization header using AWS signed header authentication
208
+ def get_aws_auth_param(params, secret_access_key)
209
+ canonical_string = EC2.canonical_string(params)
210
+ encoded_canonical = EC2.encode(secret_access_key, canonical_string)
211
+ end
212
+
213
+ # allow us to have a one line call in each method which will do all of the work
214
+ # in making the actual request to AWS.
215
+ def response_generator( options = {} )
216
+
217
+ options = {
218
+ :action => "",
219
+ :params => {}
220
+ }.merge(options)
221
+
222
+ raise ArgumentError, ":action must be provided to response_generator" if options[:action].nil? || options[:action].empty?
223
+
224
+ http_response = make_request(options[:action], options[:params])
225
+ http_xml = http_response.body
226
+ return Response.parse(:xml => http_xml)
227
+
228
+ end
229
+
230
+ # Raises the appropriate error if the specified Net::HTTPResponse object
231
+ # contains an Amazon EC2 error; returns +false+ otherwise.
232
+ def ec2_error?(response)
233
+
234
+ # return false if we got a HTTP 200 code,
235
+ # otherwise there is some type of error (40x,50x) and
236
+ # we should try to raise an appropriate exception
237
+ # from one of our exception classes defined in
238
+ # exceptions.rb
239
+ return false if response.is_a?(Net::HTTPSuccess)
240
+
241
+ # parse the XML document so we can walk through it
242
+ doc = REXML::Document.new(response.body)
243
+
244
+ # Check that the Error element is in the place we would expect.
245
+ # and if not raise a generic error exception
246
+ unless doc.root.elements['Errors'].elements['Error'].name == 'Error'
247
+ raise Error, "Unexpected error format. response.body is: #{response.body}"
248
+ end
249
+
250
+ # An valid error response looks like this:
251
+ # <?xml version="1.0"?><Response><Errors><Error><Code>InvalidParameterCombination</Code><Message>Unknown parameter: foo</Message></Error></Errors><RequestID>291cef62-3e86-414b-900e-17246eccfae8</RequestID></Response>
252
+ # AWS EC2 throws some exception codes that look like Error.SubError. Since we can't name classes this way
253
+ # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this
254
+ # non '.' name as well.
255
+ error_code = doc.root.elements['Errors'].elements['Error'].elements['Code'].text.gsub('.', '')
256
+ error_message = doc.root.elements['Errors'].elements['Error'].elements['Message'].text
257
+
258
+ # Raise one of our specific error classes if it exists.
259
+ # otherwise, throw a generic EC2 Error with a few details.
260
+ if EC2.const_defined?(error_code)
261
+ raise EC2.const_get(error_code), error_message
262
+ else
263
+ raise EC2::Error, error_message
264
+ end
265
+
266
+ end
267
+
268
+ end
269
+
270
+ end
data/test/test_EC2.rb ADDED
@@ -0,0 +1,68 @@
1
+ #--
2
+ # Amazon Web Services EC2 Query API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2008 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ require File.dirname(__FILE__) + '/test_helper.rb'
12
+
13
+ context "The EC2 method " do
14
+
15
+ setup do
16
+ end
17
+
18
+ specify "EC2::Base attribute readers should be available" do
19
+ @ec2 = EC2::Base.new( :access_key_id => "not a key",
20
+ :secret_access_key => "not a secret",
21
+ :use_ssl => true,
22
+ :server => "foo.example.com" )
23
+
24
+ @ec2.use_ssl.should.equal true
25
+ @ec2.port.should.equal 443
26
+ @ec2.server.should.equal "foo.example.com"
27
+ end
28
+
29
+ specify "EC2::Base should work with insecure connections as well" do
30
+ @ec2 = EC2::Base.new( :access_key_id => "not a key",
31
+ :secret_access_key => "not a secret",
32
+ :use_ssl => false,
33
+ :server => "foo.example.com" )
34
+
35
+ @ec2.use_ssl.should.equal false
36
+ @ec2.port.should.equal 80
37
+ @ec2.server.should.equal "foo.example.com"
38
+ end
39
+
40
+ specify "EC2::Base should allow specification of port" do
41
+ @ec2 = EC2::Base.new( :access_key_id => "not a key",
42
+ :secret_access_key => "not a secret",
43
+ :use_ssl => true,
44
+ :server => "foo.example.com",
45
+ :port => 8443 )
46
+
47
+ @ec2.use_ssl.should.equal true
48
+ @ec2.port.should.equal 8443
49
+ @ec2.server.should.equal "foo.example.com"
50
+ end
51
+
52
+ specify "EC2.canonical_string(path) should conform to Amazon's requirements " do
53
+ path = {"name1" => "value1", "name2" => "value2", "name3" => "value3"}
54
+ if ENV['EC2_URL'].nil? || ENV['EC2_URL'] == 'https://ec2.amazonaws.com'
55
+ EC2.canonical_string(path).should.equal "POST\nec2.amazonaws.com\n/\nname1=value1&name2=value2&name3=value3"
56
+ elsif ENV['EC2_URL'] == 'https://us-east-1.ec2.amazonaws.com'
57
+ EC2.canonical_string(path).should.equal "POST\nus-east-1.ec2.amazonaws.com\n/\nname1=value1&name2=value2&name3=value3"
58
+ elsif ENV['EC2_URL'] == 'https://eu-west-1.ec2.amazonaws.com'
59
+ EC2.canonical_string(path).should.equal "POST\neu-west-1.ec2.amazonaws.com\n/\nname1=value1&name2=value2&name3=value3"
60
+ end
61
+ end
62
+
63
+ specify "EC2.encode should return the expected string" do
64
+ EC2.encode("secretaccesskey", "foobar123", urlencode=true).should.equal "e3jeuDc3DIX2mW8cVqWiByj4j5g%3D"
65
+ EC2.encode("secretaccesskey", "foobar123", urlencode=false).should.equal "e3jeuDc3DIX2mW8cVqWiByj4j5g="
66
+ end
67
+
68
+ end
@@ -0,0 +1,49 @@
1
+ #--
2
+ # Amazon Web Services EC2 Query API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2008 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ require File.dirname(__FILE__) + '/test_helper.rb'
12
+
13
+ context "EC2 availability zones" do
14
+
15
+ setup do
16
+ @ec2 = EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
17
+
18
+ @describe_availability_zones_response_body = <<-RESPONSE
19
+ <DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/2008-02-01/">
20
+ <availabilityZoneInfo>
21
+ <item>
22
+ <zoneName>us-east-1a</zoneName>
23
+ <zoneState>available</zoneState>
24
+ </item>
25
+ <item>
26
+ <zoneName>us-east-1b</zoneName>
27
+ <zoneState>available</zoneState>
28
+ </item>
29
+ </availabilityZoneInfo>
30
+ </DescribeAvailabilityZonesResponse>
31
+ RESPONSE
32
+
33
+ end
34
+
35
+ specify "should be able to be described with describe_availability_zones" do
36
+ @ec2.stubs(:make_request).with('DescribeAvailabilityZones', { "ZoneName.1" => "us-east-1a", "ZoneName.2" => "us-east-1b" }).
37
+ returns stub(:body => @describe_availability_zones_response_body, :is_a? => true)
38
+ @ec2.describe_availability_zones( :zone_name => ["us-east-1a", "us-east-1b"] ).should.be.an.instance_of Hash
39
+
40
+ response = @ec2.describe_availability_zones( :zone_name => ["us-east-1a", "us-east-1b"] )
41
+
42
+ response.availabilityZoneInfo.item[0].zoneName.should.equal "us-east-1a"
43
+ response.availabilityZoneInfo.item[0].zoneState.should.equal "available"
44
+
45
+ response.availabilityZoneInfo.item[1].zoneName.should.equal "us-east-1b"
46
+ response.availabilityZoneInfo.item[1].zoneState.should.equal "available"
47
+ end
48
+
49
+ end
@@ -0,0 +1,54 @@
1
+ #--
2
+ # Amazon Web Services EC2 Query API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2008 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ require File.dirname(__FILE__) + '/test_helper.rb'
12
+
13
+ context "The EC2 console " do
14
+
15
+ setup do
16
+ @ec2 = EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
17
+
18
+ @get_console_output_response_body = <<-RESPONSE
19
+ <GetConsoleOutputResponse xmlns="http://ec2.amazonaws.com/doc/2007-03-01">
20
+ <instanceId>i-28a64341</instanceId>
21
+ <timestamp>2007-01-03 15:00:00</timestamp>
22
+ <output>
23
+ YyB2ZXJzaW9uIDQuMC4xIDIwMDUwNzI3IChSZWQgSGF0IDQuMC4xLTUpKSAjMSBTTVAgVGh1IE9j
24
+ dCAyNiAwODo0MToyNiBTQVNUIDIwMDYKQklPUy1wcm92aWRlZCBwaHlzaWNhbCBSQU0gbWFwOgpY
25
+ ZW46IDAwMDAwMDAwMDAwMDAwMDAgLSAwMDAwMDAwMDZhNDAwMDAwICh1c2FibGUpCjk4ME1CIEhJ
26
+ R0hNRU0gYXZhaWxhYmxlLgo3MjdNQiBMT1dNRU0gYXZhaWxhYmxlLgpOWCAoRXhlY3V0ZSBEaXNh
27
+ YmxlKSBwcm90ZWN0aW9uOiBhY3RpdmUKSVJRIGxvY2t1cCBkZXRlY3Rpb24gZGlzYWJsZWQKQnVp
28
+ bHQgMSB6b25lbGlzdHMKS2VybmVsIGNvbW1hbmQgbGluZTogcm9vdD0vZGV2L3NkYTEgcm8gNApF
29
+ bmFibGluZyBmYXN0IEZQVSBzYXZlIGFuZCByZXN0b3JlLi4uIGRvbmUuCg==
30
+ </output>
31
+ </GetConsoleOutputResponse>
32
+ RESPONSE
33
+
34
+ end
35
+
36
+
37
+ specify "should return info written to a specific instances console" do
38
+ @ec2.stubs(:make_request).with('GetConsoleOutput', {"InstanceId"=>"i-2ea64347"}).
39
+ returns stub(:body => @get_console_output_response_body, :is_a? => true)
40
+ @ec2.get_console_output( :instance_id => "i-2ea64347" ).should.be.an.instance_of Hash
41
+ response = @ec2.get_console_output( :instance_id => "i-2ea64347" )
42
+ response.instanceId.should.equal "i-28a64341"
43
+ response.timestamp.should.equal "2007-01-03 15:00:00"
44
+ end
45
+
46
+
47
+ specify "method get_console_output should raise an exception when called without nil/empty string arguments" do
48
+ lambda { @ec2.get_console_output() }.should.raise(EC2::ArgumentError)
49
+ lambda { @ec2.get_console_output(:instance_id => nil) }.should.raise(EC2::ArgumentError)
50
+ lambda { @ec2.get_console_output(:instance_id => "") }.should.raise(EC2::ArgumentError)
51
+ end
52
+
53
+
54
+ end
@@ -0,0 +1,144 @@
1
+ #--
2
+ # Amazon Web Services EC2 Query API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2008 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ require File.dirname(__FILE__) + '/test_helper.rb'
12
+
13
+ context "EC2 elastic IP addresses " do
14
+
15
+ setup do
16
+ @ec2 = EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
17
+
18
+ @allocate_address_body = <<-RESPONSE
19
+ <AllocateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2008-02-01">
20
+ <publicIp>67.202.55.255</publicIp>
21
+ </AllocateAddressResponse>
22
+ RESPONSE
23
+
24
+ @describe_addresses_response_body = <<-RESPONSE
25
+ <DescribeAddressesResponse xmlns="http://ec2.amazonaws.com/doc/2008-02-01">
26
+ <addressesSet>
27
+ <item>
28
+ <instanceId>i-28a64341</instanceId>
29
+ <publicIp>67.202.55.255</publicIp>
30
+ </item>
31
+ </addressesSet>
32
+ </DescribeAddressesResponse>
33
+ RESPONSE
34
+
35
+ @release_address_response_body = <<-RESPONSE
36
+ <ReleaseAddressResponse xmlns="http://ec2.amazonaws.com/doc/2008-02-01">
37
+ <return>true</return>
38
+ </ReleaseAddressResponse>
39
+ RESPONSE
40
+
41
+ @associate_address_response_body = <<-RESPONSE
42
+ <AssociateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2008-02-01">
43
+ <return>true</return>
44
+ </AssociateAddressResponse>
45
+ RESPONSE
46
+
47
+ @disassociate_address_response_body = <<-RESPONSE
48
+ <DisassociateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2008-02-01">
49
+ <return>true</return>
50
+ </DisassociateAddressResponse>
51
+ RESPONSE
52
+
53
+ end
54
+
55
+
56
+ specify "should be able to be created" do
57
+ @ec2.stubs(:make_request).with('AllocateAddress', {}).
58
+ returns stub(:body => @allocate_address_body, :is_a? => true)
59
+
60
+ @ec2.allocate_address.should.be.an.instance_of Hash
61
+
62
+ response = @ec2.allocate_address
63
+ response.publicIp.should.equal "67.202.55.255"
64
+ end
65
+
66
+
67
+ #specify "method create_keypair should reject bad arguments" do
68
+ # @ec2.stubs(:make_request).with('CreateKeyPair', {"KeyName"=>"example-key-name"}).
69
+ # returns stub(:body => @create_keypair_response_body, :is_a? => true)
70
+ #
71
+ # lambda { @ec2.create_keypair( :key_name => "example-key-name" ) }.should.not.raise(EC2::ArgumentError)
72
+ # lambda { @ec2.create_keypair() }.should.raise(EC2::ArgumentError)
73
+ # lambda { @ec2.create_keypair( :key_name => nil ) }.should.raise(EC2::ArgumentError)
74
+ # lambda { @ec2.create_keypair( :key_name => "" ) }.should.raise(EC2::ArgumentError)
75
+ #end
76
+
77
+
78
+ specify "should be able to be described with describe_addresses" do
79
+ @ec2.stubs(:make_request).with('DescribeAddresses', {"PublicIp.1"=>"67.202.55.255"}).
80
+ returns stub(:body => @describe_addresses_response_body, :is_a? => true)
81
+
82
+ @ec2.describe_addresses( :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash
83
+
84
+ response = @ec2.describe_addresses( :public_ip => "67.202.55.255" )
85
+ response.addressesSet.item[0].instanceId.should.equal "i-28a64341"
86
+ response.addressesSet.item[0].publicIp.should.equal "67.202.55.255"
87
+ end
88
+
89
+
90
+ specify "should be able to be released with release_address" do
91
+ @ec2.stubs(:make_request).with('ReleaseAddress', {"PublicIp" => "67.202.55.255"}).
92
+ returns stub(:body => @release_address_response_body, :is_a? => true)
93
+
94
+ @ec2.release_address( :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash
95
+
96
+ response = @ec2.release_address( :public_ip => "67.202.55.255" )
97
+ response.return.should.equal "true"
98
+ end
99
+
100
+
101
+ specify "should be able to be associated with an instance with associate_address" do
102
+ @ec2.stubs(:make_request).with('AssociateAddress', {"InstanceId" => "i-2ea64347", "PublicIp"=>"67.202.55.255"}).
103
+ returns stub(:body => @associate_address_response_body, :is_a? => true)
104
+
105
+ @ec2.associate_address( :instance_id => "i-2ea64347", :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash
106
+
107
+ response = @ec2.associate_address( :instance_id => "i-2ea64347", :public_ip => "67.202.55.255" )
108
+ response.return.should.equal "true"
109
+ end
110
+
111
+
112
+ specify "method associate_address should reject bad arguments" do
113
+ @ec2.stubs(:make_request).with('AssociateAddress', {"InstanceId" => "i-2ea64347", "PublicIp"=>"67.202.55.255"}).
114
+ returns stub(:body => @associate_address_response_body, :is_a? => true)
115
+
116
+ lambda { @ec2.associate_address( :instance_id => "i-2ea64347", :public_ip => "67.202.55.255" ) }.should.not.raise(EC2::ArgumentError)
117
+ lambda { @ec2.associate_address() }.should.raise(EC2::ArgumentError)
118
+ lambda { @ec2.associate_address( :instance_id => nil ) }.should.raise(EC2::ArgumentError)
119
+ lambda { @ec2.associate_address( :public_ip => "" ) }.should.raise(EC2::ArgumentError)
120
+ end
121
+
122
+
123
+ specify "should be able to be disassociated with an instance with disassociate_address" do
124
+ @ec2.stubs(:make_request).with('DisassociateAddress', {'PublicIp' => '67.202.55.255'}).
125
+ returns stub(:body => @disassociate_address_response_body, :is_a? => true)
126
+
127
+ @ec2.disassociate_address( :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash
128
+
129
+ response = @ec2.disassociate_address( :public_ip => "67.202.55.255" )
130
+ response.return.should.equal "true"
131
+ end
132
+
133
+
134
+ specify "method disassociate_address should reject bad arguments" do
135
+ @ec2.stubs(:make_request).with('DisassociateAddress', {'PublicIp' => '67.202.55.255'}).
136
+ returns stub(:body => @disassociate_address_response_body, :is_a? => true)
137
+
138
+ lambda { @ec2.disassociate_address( :public_ip => "67.202.55.255" ) }.should.not.raise(EC2::ArgumentError)
139
+ lambda { @ec2.disassociate_address() }.should.raise(EC2::ArgumentError)
140
+ lambda { @ec2.disassociate_address( :public_ip => "" ) }.should.raise(EC2::ArgumentError)
141
+ end
142
+
143
+
144
+ end