amazon-ec2 0.1.0 → 0.2.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 +166 -95
- data/License.txt +67 -20
- data/Manifest.txt +17 -6
- data/README.txt +112 -2
- data/Rakefile +15 -5
- data/bin/ec2-gem-example.rb +61 -0
- data/bin/ec2sh +73 -0
- data/bin/setup.rb +19 -0
- data/lib/EC2.rb +142 -61
- data/lib/EC2/console.rb +44 -0
- data/lib/EC2/exceptions.rb +136 -0
- data/lib/EC2/image_attributes.rb +137 -29
- data/lib/EC2/images.rb +120 -73
- data/lib/EC2/instances.rb +168 -98
- data/lib/EC2/keypairs.rb +79 -23
- data/lib/EC2/responses.rb +142 -321
- data/lib/EC2/security_groups.rb +209 -117
- data/lib/EC2/version.rb +11 -2
- data/test/test_EC2.rb +44 -13
- data/test/test_EC2_console.rb +54 -0
- data/test/test_EC2_image_attributes.rb +188 -0
- data/test/test_EC2_images.rb +191 -0
- data/test/test_EC2_instances.rb +303 -0
- data/test/test_EC2_keypairs.rb +123 -0
- data/test/test_EC2_responses.rb +102 -0
- data/test/test_EC2_security_groups.rb +205 -0
- data/test/test_EC2_version.rb +44 -0
- data/test/test_helper.rb +16 -8
- data/website/index.html +378 -86
- data/website/index.txt +339 -88
- data/website/stylesheets/screen.css +8 -8
- metadata +89 -16
- data/examples/ec2-example.rb +0 -48
- data/test/test_responses.rb +0 -17
data/Rakefile
CHANGED
@@ -12,8 +12,8 @@ require 'hoe'
|
|
12
12
|
include FileUtils
|
13
13
|
require File.join(File.dirname(__FILE__), 'lib', 'EC2', 'version')
|
14
14
|
|
15
|
-
AUTHOR = ["
|
16
|
-
EMAIL = "
|
15
|
+
AUTHOR = ["Glenn Rempe"] # can also be an array of Authors
|
16
|
+
EMAIL = "glenn@elasticworkbench.com"
|
17
17
|
DESCRIPTION = "An interface library that allows Ruby or Ruby on Rails applications to easily connect to the HTTP 'Query API' for the Amazon Web Services Elastic Compute Cloud (EC2) and manipulate server instances."
|
18
18
|
GEM_NAME = "amazon-ec2" # what ppl will type to install your gem
|
19
19
|
|
@@ -74,10 +74,13 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
|
74
74
|
|
75
75
|
# == Optional
|
76
76
|
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
77
|
-
|
78
|
-
#
|
77
|
+
|
78
|
+
# An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
79
|
+
p.extra_deps = [['xml-simple', '>= 1.0.11'], ['mocha', '>= 0.4.0'], ['test-spec', '>= 0.3.0'], ['rcov', '>= 0.8.0.2'], ['syntax', '>= 1.0.0'], ['RedCloth', '>= 3.0.4']]
|
80
|
+
|
81
|
+
# A hash of extra values to set in the gemspec.
|
79
82
|
p.spec_extras = {
|
80
|
-
:extra_rdoc_files => ["README.txt", "History.txt"],
|
83
|
+
:extra_rdoc_files => ["README.txt", "History.txt", "License.txt"],
|
81
84
|
:rdoc_options => RDOC_OPTS,
|
82
85
|
:autorequire => "EC2"
|
83
86
|
}
|
@@ -106,6 +109,9 @@ end
|
|
106
109
|
desc 'Generate and upload website files'
|
107
110
|
task :website => [:website_generate, :website_upload]
|
108
111
|
|
112
|
+
desc 'Run all types of tests that we have defined'
|
113
|
+
task :test_all => [:test, :test_deps, :test_coverage]
|
114
|
+
|
109
115
|
desc 'Release the website and new gem version'
|
110
116
|
task :deploy => [:check_version, :website, :release] do
|
111
117
|
puts "Remember to create SVN tag:"
|
@@ -129,4 +135,8 @@ task :check_version do
|
|
129
135
|
end
|
130
136
|
end
|
131
137
|
|
138
|
+
desc 'Runs RCOV and generates test coverage reports which are stored in coverage/ dir'
|
139
|
+
task :test_coverage do
|
140
|
+
sh %{rcov -T test/*.rb}
|
141
|
+
end
|
132
142
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Amazon Web Services EC2 Query API Ruby library
|
4
|
+
#
|
5
|
+
# Ruby Gem Name:: amazon-ec2
|
6
|
+
# Author:: Glenn Rempe (mailto:glenn@elasticworkbench.com)
|
7
|
+
# Copyright:: Copyright (c) 2007 Glenn Rempe
|
8
|
+
# License:: Distributes under the same terms as Ruby
|
9
|
+
# Home:: http://amazon-ec2.rubyforge.org
|
10
|
+
#++
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require File.dirname(__FILE__) + '/../lib/EC2'
|
14
|
+
|
15
|
+
# pull these from the local shell environment variables set in ~/.bash_login
|
16
|
+
# or using appropriate methods specific to your login shell.
|
17
|
+
#
|
18
|
+
# e.g. in ~/.bash_login
|
19
|
+
#
|
20
|
+
# # For amazon-ec2 and amazon s3 ruby gems
|
21
|
+
# export AMAZON_ACCESS_KEY_ID="FOO"
|
22
|
+
# export AMAZON_SECRET_ACCESS_KEY="BAR"
|
23
|
+
|
24
|
+
ACCESS_KEY_ID = ENV['AMAZON_ACCESS_KEY_ID']
|
25
|
+
SECRET_ACCESS_KEY = ENV['AMAZON_SECRET_ACCESS_KEY']
|
26
|
+
|
27
|
+
if ACCESS_KEY_ID.nil? || ACCESS_KEY_ID.empty?
|
28
|
+
puts "Error : You must add the shell environment variables AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY before calling #{$0}!"
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
ec2 = EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY )
|
33
|
+
|
34
|
+
puts "----- GEM Version -----"
|
35
|
+
puts EC2::VERSION::STRING
|
36
|
+
|
37
|
+
puts "----- ec2.methods.sort -----"
|
38
|
+
p ec2.methods.sort
|
39
|
+
|
40
|
+
puts "----- listing images owned by 'amazon' -----"
|
41
|
+
ec2.describe_images(:owner_id => "amazon").imagesSet.item.each do |image|
|
42
|
+
image.members.each do |member|
|
43
|
+
puts "#{member} => #{image[member]}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "----- listing all running instances -----"
|
48
|
+
puts ec2.describe_instances()
|
49
|
+
|
50
|
+
puts "----- creating a security group -----"
|
51
|
+
puts ec2.create_security_group(:group_name => "ec2-example-rb-test-group", :group_description => "ec-example.rb test group description.")
|
52
|
+
|
53
|
+
puts "----- listing security groups -----"
|
54
|
+
puts ec2.describe_security_groups()
|
55
|
+
|
56
|
+
puts "----- deleting a security group -----"
|
57
|
+
puts ec2.delete_security_group(:group_name => "ec2-example-rb-test-group")
|
58
|
+
|
59
|
+
puts "----- listing my keypairs (verbose mode) -----"
|
60
|
+
puts ec2.describe_keypairs()
|
61
|
+
|
data/bin/ec2sh
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Amazon Web Services EC2 Query API Ruby library
|
4
|
+
#
|
5
|
+
# Ruby Gem Name:: amazon-ec2
|
6
|
+
# Author:: Glenn Rempe (mailto:glenn@elasticworkbench.com)
|
7
|
+
# Copyright:: Copyright (c) 2007 Glenn Rempe
|
8
|
+
# License:: Distributes under the same terms as Ruby
|
9
|
+
# Home:: http://amazon-ec2.rubyforge.org
|
10
|
+
#++
|
11
|
+
|
12
|
+
# CREDITS : Credit for this bit of shameful ripoff coolness
|
13
|
+
# goes to Marcel Molina and his AWS::S3 gem. Thanks!
|
14
|
+
|
15
|
+
# Usage : running this starts up an irb session and
|
16
|
+
# sets up the connection to EC2 as a class variable called
|
17
|
+
# '@ec2'. So just do something like the following on the
|
18
|
+
# shell command line:
|
19
|
+
|
20
|
+
# macbook-pro:~ glenn$ ec2sh
|
21
|
+
# >> @ec2.describe_images
|
22
|
+
# => [#<EC2::Item image_location...
|
23
|
+
|
24
|
+
ec2_lib = File.dirname(__FILE__) + '/../lib/EC2'
|
25
|
+
setup = File.dirname(__FILE__) + '/setup'
|
26
|
+
irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
27
|
+
|
28
|
+
if ( ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY'] )
|
29
|
+
|
30
|
+
welcome_message = <<-MESSAGE
|
31
|
+
|
32
|
+
'ec2sh' usage :
|
33
|
+
This is an interactive 'irb' command shell that allows you to use all
|
34
|
+
commands available to the amazon-ec2 gem. You'll find this to be a
|
35
|
+
great tool to help you debug issues and practice running commands
|
36
|
+
against the live EC2 servers prior to putting them in your code.
|
37
|
+
|
38
|
+
The EC2 connection is wired to the class instance '@ec2'. Make method calls
|
39
|
+
on this to execute commands on EC2. Adding a #to_s
|
40
|
+
at the end of any command should give you a full String representation of the
|
41
|
+
response. The #xml data is available for each response
|
42
|
+
which allows you to view the full and complete XML response returned by
|
43
|
+
EC2 without any parsing applied. This is useful for viewing the
|
44
|
+
hierarchy of an entire response in a friendly way (if XML is friendly
|
45
|
+
to you!). Understanding the hierarchy of the XML response is critical
|
46
|
+
to making effective use of this library.
|
47
|
+
|
48
|
+
Examples to try:
|
49
|
+
|
50
|
+
returns : all ec2 public methods
|
51
|
+
>> @ec2.methods.sort
|
52
|
+
|
53
|
+
returns : a string representation of ALL images
|
54
|
+
>> @ec2.describe_images.to_s
|
55
|
+
|
56
|
+
returns : an Array of EC2::Response objects, each an EC2 image and its data
|
57
|
+
>> @ec2.describe_images.imagesSet.item
|
58
|
+
>> @ec2.describe_images.imagesSet.item[0] (an OpenStruct of a single item in that array)
|
59
|
+
>> @ec2.describe_images.imagesSet.item[0].to_s (a String representation of that OpenStruct item)
|
60
|
+
|
61
|
+
returns : an XML representation of all images
|
62
|
+
>> puts @ec2.describe_images.xml
|
63
|
+
|
64
|
+
returns : an XML representation of all images owned by Amazon
|
65
|
+
>> puts @ec2.describe_images(:owner_id => 'amazon').xml
|
66
|
+
|
67
|
+
MESSAGE
|
68
|
+
|
69
|
+
puts welcome_message
|
70
|
+
exec "#{irb_name} -r #{ec2_lib} -r #{setup} --simple-prompt"
|
71
|
+
else
|
72
|
+
puts "You must define AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY as shell environment variables before running #{$0}!"
|
73
|
+
end
|
data/bin/setup.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Amazon Web Services EC2 Query API Ruby library
|
4
|
+
#
|
5
|
+
# Ruby Gem Name:: amazon-ec2
|
6
|
+
# Author:: Glenn Rempe (mailto:glenn@elasticworkbench.com)
|
7
|
+
# Copyright:: Copyright (c) 2007 Glenn Rempe
|
8
|
+
# License:: Distributes under the same terms as Ruby
|
9
|
+
# Home:: http://amazon-ec2.rubyforge.org
|
10
|
+
#++
|
11
|
+
|
12
|
+
if ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY']
|
13
|
+
@ec2 = EC2::Base.new(
|
14
|
+
:access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
|
15
|
+
:secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
include EC2
|
data/lib/EC2.rb
CHANGED
@@ -1,31 +1,17 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
1
|
+
#--
|
2
|
+
# Amazon Web Services EC2 Query API Ruby library
|
3
|
+
#
|
4
|
+
# Ruby Gem Name:: amazon-ec2
|
5
|
+
# Author:: Glenn Rempe (mailto:glenn@elasticworkbench.com)
|
6
|
+
# Copyright:: Copyright (c) 2007 Glenn Rempe
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
# Home:: http://amazon-ec2.rubyforge.org
|
9
|
+
#++
|
8
10
|
|
9
|
-
|
10
|
-
# This software code is made available "AS IS" without warranties of any
|
11
|
-
# kind. You may copy, display, modify and redistribute the software
|
12
|
-
# code either by itself or as incorporated into your code; provided that
|
13
|
-
# you do not remove any proprietary notices. Your use of this software
|
14
|
-
# code is at your own risk and you waive any claim against Amazon Web
|
15
|
-
# Services LLC or its affiliates with respect to your use of this software
|
16
|
-
# code. (c) 2006 Amazon Web Services LLC or its affiliates. All rights
|
17
|
-
# reserved.
|
18
|
-
|
19
|
-
require 'base64'
|
20
|
-
require 'cgi'
|
21
|
-
require 'openssl'
|
22
|
-
require 'digest/sha1'
|
23
|
-
require 'net/https'
|
24
|
-
require 'rexml/document'
|
25
|
-
require 'time'
|
11
|
+
%w[ base64 cgi openssl digest/sha1 net/https rexml/document time ostruct ].each { |f| require f }
|
26
12
|
|
27
13
|
# Require any lib files that we have bundled with this Ruby Gem in the lib/EC2 directory.
|
28
|
-
# Parts of the EC2 module and
|
14
|
+
# Parts of the EC2 module and Base class are broken out into separate
|
29
15
|
# files for maintainability and are organized by the functional groupings defined
|
30
16
|
# in the EC2 API developers guide.
|
31
17
|
Dir[File.join(File.dirname(__FILE__), 'EC2/**/*.rb')].sort.each { |lib| require lib }
|
@@ -35,11 +21,8 @@ module EC2
|
|
35
21
|
# Which host FQDN will we connect to for all API calls to AWS?
|
36
22
|
DEFAULT_HOST = 'ec2.amazonaws.com'
|
37
23
|
|
38
|
-
# Define the ports to use for SSL(true) or Non-SSL(false) connections.
|
39
|
-
PORTS_BY_SECURITY = { true => 443, false => 80 }
|
40
|
-
|
41
24
|
# This is the version of the API as defined by Amazon Web Services
|
42
|
-
API_VERSION = '2007-01-
|
25
|
+
API_VERSION = '2007-01-19'
|
43
26
|
|
44
27
|
# This release version is passed in with each request as part
|
45
28
|
# of the HTTP 'User-Agent' header. Set this be the same value
|
@@ -60,15 +43,15 @@ module EC2
|
|
60
43
|
return buf
|
61
44
|
end
|
62
45
|
|
63
|
-
# Encodes the given string with the
|
46
|
+
# Encodes the given string with the secret_access_key, by taking the
|
64
47
|
# hmac-sha1 sum, and then base64 encoding it. Optionally, it will also
|
65
48
|
# url encode the result of that to protect the string if it's going to
|
66
49
|
# be used as a query string parameter.
|
67
|
-
def EC2.encode(
|
50
|
+
def EC2.encode(secret_access_key, str, urlencode=true)
|
68
51
|
digest = OpenSSL::Digest::Digest.new('sha1')
|
69
52
|
b64_hmac =
|
70
53
|
Base64.encode64(
|
71
|
-
OpenSSL::HMAC.digest(digest,
|
54
|
+
OpenSSL::HMAC.digest(digest, secret_access_key, str)).strip
|
72
55
|
|
73
56
|
if urlencode
|
74
57
|
return CGI::escape(b64_hmac)
|
@@ -78,27 +61,62 @@ module EC2
|
|
78
61
|
end
|
79
62
|
|
80
63
|
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
|
64
|
+
#Introduction:
|
65
|
+
#
|
66
|
+
# The library exposes one main interface class, 'EC2::Base'.
|
67
|
+
# This class provides all the methods for using the EC2 service
|
68
|
+
# including the handling of header signing and other security issues .
|
69
|
+
# This class uses Net::HTTP to interface with the EC2 Query API interface.
|
70
|
+
#
|
71
|
+
#Required Arguments:
|
72
|
+
#
|
73
|
+
# :access_key_id => String (default : "")
|
74
|
+
# :secret_access_key => String (default : "")
|
75
|
+
#
|
76
|
+
#Optional Arguments:
|
77
|
+
#
|
78
|
+
# :use_ssl => Boolean (default : true)
|
79
|
+
# :server => String (default : 'ec2.amazonaws.com')
|
80
|
+
#
|
81
|
+
class Base
|
86
82
|
|
87
|
-
|
88
|
-
# If 'true' some 'puts' are done to view variable contents.
|
89
|
-
attr_accessor :verbose
|
83
|
+
attr_reader :use_ssl, :server, :port
|
90
84
|
|
91
|
-
def initialize(
|
92
|
-
server=DEFAULT_HOST, port=PORTS_BY_SECURITY[is_secure])
|
85
|
+
def initialize( options = {} )
|
93
86
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
87
|
+
options = { :access_key_id => "",
|
88
|
+
:secret_access_key => "",
|
89
|
+
:use_ssl => true,
|
90
|
+
:server => DEFAULT_HOST
|
91
|
+
}.merge(options)
|
92
|
+
|
93
|
+
@server = options[:server]
|
94
|
+
@use_ssl = options[:use_ssl]
|
95
|
+
|
96
|
+
raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty?
|
97
|
+
raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty?
|
98
|
+
raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil?
|
99
|
+
raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false
|
100
|
+
raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty?
|
101
|
+
|
102
|
+
|
103
|
+
# based on the :use_ssl boolean, determine which port we should connect to
|
104
|
+
case @use_ssl
|
105
|
+
when true
|
106
|
+
# https
|
107
|
+
@port = 443
|
108
|
+
when false
|
109
|
+
# http
|
110
|
+
@port = 80
|
111
|
+
end
|
112
|
+
|
113
|
+
@access_key_id = options[:access_key_id]
|
114
|
+
@secret_access_key = options[:secret_access_key]
|
115
|
+
@http = Net::HTTP.new(options[:server], @port)
|
116
|
+
@http.use_ssl = @use_ssl
|
100
117
|
|
101
|
-
|
118
|
+
# Don't verify the SSL certificates. Avoids SSL Cert warning in log on every GET.
|
119
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
102
120
|
|
103
121
|
end
|
104
122
|
|
@@ -126,20 +144,23 @@ module EC2
|
|
126
144
|
|
127
145
|
@http.start do
|
128
146
|
|
129
|
-
|
130
|
-
|
131
|
-
|
147
|
+
# remove any keys that have nil or empty values
|
148
|
+
params.reject! { |key, value| value.nil? or value.empty?}
|
149
|
+
|
150
|
+
params.merge!( {"Action" => action,
|
151
|
+
"SignatureVersion" => "1",
|
152
|
+
"AWSAccessKeyId" => @access_key_id,
|
153
|
+
"Version" => API_VERSION,
|
154
|
+
"Timestamp"=>Time.now.getutc.iso8601} )
|
132
155
|
|
133
156
|
sigpath = "?" + params.sort_by { |param| param[0].downcase }.collect { |param| param.join("=") }.join("&")
|
134
157
|
|
135
|
-
sig = get_aws_auth_param(sigpath, @
|
158
|
+
sig = get_aws_auth_param(sigpath, @secret_access_key)
|
136
159
|
|
137
160
|
path = "?" + params.sort.collect do |param|
|
138
161
|
CGI::escape(param[0]) + "=" + CGI::escape(param[1])
|
139
162
|
end.join("&") + "&Signature=" + sig
|
140
163
|
|
141
|
-
puts path if @verbose
|
142
|
-
|
143
164
|
req = Net::HTTP::Get.new("/#{path}")
|
144
165
|
|
145
166
|
# Ruby will automatically add a random content-type on some verbs, so
|
@@ -149,20 +170,80 @@ module EC2
|
|
149
170
|
req['Content-Type'] ||= ''
|
150
171
|
req['User-Agent'] = "rubyforge-amazon-ec2-ruby-gem-query-api v-#{RELEASE_VERSION}"
|
151
172
|
|
152
|
-
data = nil unless req.request_body_permitted?
|
153
|
-
@http.request(req,
|
173
|
+
#data = nil unless req.request_body_permitted?
|
174
|
+
response = @http.request(req, nil)
|
175
|
+
|
176
|
+
# Make a call to see if we need to throw an error based on the response given by EC2
|
177
|
+
# All error classes are defined in EC2/exceptions.rb
|
178
|
+
ec2_error?(response)
|
179
|
+
|
180
|
+
return response
|
154
181
|
|
155
182
|
end
|
156
183
|
|
157
184
|
end
|
158
185
|
|
159
|
-
|
160
186
|
# Set the Authorization header using AWS signed header authentication
|
161
|
-
def get_aws_auth_param(path,
|
187
|
+
def get_aws_auth_param(path, secret_access_key)
|
162
188
|
canonical_string = EC2.canonical_string(path)
|
163
|
-
encoded_canonical = EC2.encode(
|
189
|
+
encoded_canonical = EC2.encode(secret_access_key, canonical_string)
|
164
190
|
end
|
165
|
-
|
191
|
+
|
192
|
+
# allow us to have a one line call in each method which will do all of the work
|
193
|
+
# in making the actual request to AWS.
|
194
|
+
def response_generator( options = {} )
|
195
|
+
|
196
|
+
options = {
|
197
|
+
:action => "",
|
198
|
+
:params => {}
|
199
|
+
}.merge(options)
|
200
|
+
|
201
|
+
raise ArgumentError, ":action must be provided to response_generator" if options[:action].nil? || options[:action].empty?
|
202
|
+
|
203
|
+
http_response = make_request(options[:action], options[:params])
|
204
|
+
http_xml = http_response.body
|
205
|
+
return Response.parse(:xml => http_xml)
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
# Raises the appropriate error if the specified Net::HTTPResponse object
|
210
|
+
# contains an Amazon EC2 error; returns +false+ otherwise.
|
211
|
+
def ec2_error?(response)
|
212
|
+
|
213
|
+
# return false if we got a HTTP 200 code,
|
214
|
+
# otherwise there is some type of error (40x,50x) and
|
215
|
+
# we should try to raise an appropriate exception
|
216
|
+
# from one of our exception classes defined in
|
217
|
+
# exceptions.rb
|
218
|
+
return false if response.is_a?(Net::HTTPSuccess)
|
219
|
+
|
220
|
+
# parse the XML document so we can walk through it
|
221
|
+
doc = REXML::Document.new(response.body)
|
222
|
+
|
223
|
+
# Check that the Error element is in the place we would expect.
|
224
|
+
# and if not raise a generic error exception
|
225
|
+
unless doc.root.elements['Errors'].elements['Error'].name == 'Error'
|
226
|
+
raise Error, "Unexpected error format. response.body is: #{response.body}"
|
227
|
+
end
|
228
|
+
|
229
|
+
# An valid error response looks like this:
|
230
|
+
# <?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>
|
231
|
+
# AWS EC2 throws some exception codes that look like Error.SubError. Since we can't name classes this way
|
232
|
+
# we need to strip out the '.' in the error 'Code' and we name the error exceptions with this
|
233
|
+
# non '.' name as well.
|
234
|
+
error_code = doc.root.elements['Errors'].elements['Error'].elements['Code'].text.gsub('.', '')
|
235
|
+
error_message = doc.root.elements['Errors'].elements['Error'].elements['Message'].text
|
236
|
+
|
237
|
+
# Raise one of our specific error classes if it exists.
|
238
|
+
# otherwise, throw a generic EC2 Error with a few details.
|
239
|
+
if EC2.const_defined?(error_code)
|
240
|
+
raise EC2.const_get(error_code), error_message
|
241
|
+
else
|
242
|
+
raise Error, "This is an undefined error code which needs to be added to exceptions.rb : error_code => #{error_code} : error_message => #{error_message}"
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
166
247
|
end
|
167
248
|
|
168
249
|
end
|