amazon-ec2 0.3.2 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/README.rdoc +9 -12
- data/Rakefile +2 -1
- data/bin/ec2sh +17 -28
- data/bin/setup.rb +9 -2
- data/lib/EC2.rb +24 -13
- data/lib/EC2/responses.rb +1 -1
- data/test/test_EC2.rb +3 -3
- data/test/test_EC2_instances.rb +2 -2
- data/test/test_EC2_s3_xmlsimple.rb +80 -0
- metadata +3 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
=== 0.3.4 2009-01-31
|
2
|
+
* Added support in the helper binaries for EC2_URL server url for Euro servers
|
3
|
+
|
4
|
+
=== 0.3.3 2009-01-24
|
5
|
+
* Removed docs related to the ability to get Response#xml which is deprecated
|
6
|
+
* Fixed conflict when aws/s3 gem was included in user code
|
7
|
+
|
1
8
|
=== 0.3.2 2008-12-11
|
2
9
|
* Updated API version to 2008-12-01
|
3
10
|
* Note : The new European EC2 zone should just work if you specify ':server => "eu-west-1.ec2.amazonaws.com"' when initializing EC2::Base.new(). Please report any issues you have with using this new service.
|
data/README.rdoc
CHANGED
@@ -74,6 +74,12 @@ Edit the file ~/.bash_login and add the following to the existing contents:
|
|
74
74
|
export AMAZON_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID"
|
75
75
|
export AMAZON_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY_ID"
|
76
76
|
|
77
|
+
If you are using EC2 in the EU region, make sure you also set:
|
78
|
+
|
79
|
+
export EC2_URL="https://eu-west-1.ec2.amazonaws.com"
|
80
|
+
|
81
|
+
(which you have already if you configured standard EC2 command line tools to work with this region).
|
82
|
+
|
77
83
|
Once you save the file you should close and re-open your terminal so the new variables are made available. You’ll need to do this close/re-open step for each terminal window you have open (or issue the ‘source ~/.bash_login’ command in each). Make sure that this file is only readable by your user so you don’t inadvertently expose your credentials to other users on your system.
|
78
84
|
|
79
85
|
You can verify that this setup is complete by running the ‘set’ in a command window and seeing that your credentials are in the list of shell variables.
|
@@ -141,12 +147,6 @@ If you're not in front of a terminal shell now (perhaps you’re browsing this s
|
|
141
147
|
>> @ec2.describe_images.imagesSet.item[0] (an OpenStruct of a single item in that array)
|
142
148
|
>> @ec2.describe_images.imagesSet.item[0].to_s (a String representation of that OpenStruct item)
|
143
149
|
|
144
|
-
returns : an XML representation of all images
|
145
|
-
>> puts @ec2.describe_images.xml
|
146
|
-
|
147
|
-
returns : an XML representation of all images owned by Amazon
|
148
|
-
>> puts @ec2.describe_images(:owner_id => 'amazon').xml
|
149
|
-
|
150
150
|
>> @ec2.describe_images.imagesSet.item[0].to_s
|
151
151
|
=> "#<EC2::Response:0x100A465B4 imageId=\"ami-018e6b68\" imageLocation=\"rbuilder-online/phonehome-1.5.6-x86_10132.img.manifest.xml\" imageOwnerId=\"099034111737\" imageState=\"available\" isPublic=\"true\" parent=#<EC2::Response:0x100A469A6 ...>>"
|
152
152
|
|
@@ -240,10 +240,7 @@ Try out the following bit of code. This should walk through each image returned
|
|
240
240
|
|
241
241
|
=== Important notes regarding the structure of EC2::Response Objects
|
242
242
|
|
243
|
-
One of the key benefits of this new version of the library is that all responses from EC2 are bundled up in a real data structure and no longer require parsing of text.
|
244
|
-
|
245
|
-
$ ec2sh
|
246
|
-
>> puts @ec2.describe_images(:owner_id => 'amazon').xml
|
243
|
+
One of the key benefits of this new version of the library is that all responses from EC2 are bundled up in a real data structure and no longer require parsing of text. The hash returned is populated directly from the XML given to us by EC2 in response to any command we issue. This means that future changes to the API and what is returned by EC2 will largely be handled transparently by the gem. This is a huge benefit. What this means though, is that you may have to do a little homework on what actually gets returned by EC2 as XML. For example, when you make a #describe_images call in 'ec2sh' what AWS returns behind the scenes looks like:
|
247
244
|
|
248
245
|
<?xml version="1.0"?>
|
249
246
|
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2007-01-19/">
|
@@ -293,14 +290,14 @@ One of the key benefits of this new version of the library is that all responses
|
|
293
290
|
</imagesSet>
|
294
291
|
</DescribeImagesResponse>
|
295
292
|
|
296
|
-
You can see
|
293
|
+
You can see here the XML the structure that you will need to follow when constructing queries for information and parsing responses from EC2.
|
297
294
|
|
298
295
|
So, for example, if you wanted to get the image ID of the third image listed in the response above you would need to do:
|
299
296
|
|
300
297
|
>> puts @ec2.describe_images(:owner_id => 'amazon').imagesSet.item[2].imageId
|
301
298
|
ami-23b6534a
|
302
299
|
|
303
|
-
EC2 will typically return sets of things (imagesSet, reservationSet, etc.) which we map to ruby Arrays (.imagesSet.item in the example above). If you want to iterate over a response set you will need to iterate over this array. The Arrays will typically contain additional EC2::Response objects that represent each individual item. You’ll find that you can use the 'ec2sh' to help you understand the structure more completely if you try issuing commands there as a way to practice seeing what will be returned and making sure you get exactly what you want.
|
300
|
+
EC2 will typically return sets of things (imagesSet, reservationSet, etc.) which we map to ruby Arrays (.imagesSet.item in the example above). If you want to iterate over a response set you will need to iterate over this array. The Arrays will typically contain additional EC2::Response objects that represent each individual item. You’ll find that you can use the 'ec2sh' to help you understand the structure more completely if you try issuing commands there as a way to practice seeing what will be returned and making sure you get exactly what you want.
|
304
301
|
|
305
302
|
|
306
303
|
== Additional Resources
|
data/Rakefile
CHANGED
@@ -11,8 +11,9 @@ Rake::GemPackageTask.new(spec) do |pkg|
|
|
11
11
|
pkg.gem_spec = spec
|
12
12
|
end
|
13
13
|
|
14
|
+
desc "Package and then install the gem locally"
|
14
15
|
task :install => [:package] do
|
15
|
-
sh %{sudo gem install pkg/#{GEM}-#{
|
16
|
+
sh %{sudo gem install pkg/#{GEM}-#{VER}}
|
16
17
|
end
|
17
18
|
|
18
19
|
Rake::TestTask.new do |t|
|
data/bin/ec2sh
CHANGED
@@ -9,15 +9,15 @@
|
|
9
9
|
# Home:: http://github.com/grempe/amazon-ec2/tree/master
|
10
10
|
#++
|
11
11
|
|
12
|
-
# CREDITS : Credit for this bit of shameful ripoff coolness
|
12
|
+
# CREDITS : Credit for this bit of shameful ripoff coolness
|
13
13
|
# goes to Marcel Molina and his AWS::S3 gem. Thanks!
|
14
14
|
|
15
|
-
# Usage : running this starts up an irb session and
|
15
|
+
# Usage : running this starts up an irb session and
|
16
16
|
# sets up the connection to EC2 as a class variable called
|
17
|
-
# '@ec2'. So just do something like the following on the
|
17
|
+
# '@ec2'. So just do something like the following on the
|
18
18
|
# shell command line:
|
19
19
|
|
20
|
-
# macbook-pro:~ glenn$ ec2sh
|
20
|
+
# macbook-pro:~ glenn$ ec2sh
|
21
21
|
# >> @ec2.describe_images
|
22
22
|
# => [#<EC2::Item image_location...
|
23
23
|
|
@@ -26,46 +26,35 @@ setup = File.dirname(__FILE__) + '/setup'
|
|
26
26
|
irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
27
27
|
|
28
28
|
if ( ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY'] )
|
29
|
-
|
29
|
+
|
30
30
|
welcome_message = <<-MESSAGE
|
31
|
-
|
31
|
+
|
32
32
|
'ec2sh' usage :
|
33
|
-
This is an interactive 'irb' command shell that allows you to use all
|
33
|
+
This is an interactive 'irb' command shell that allows you to use all
|
34
34
|
commands available to the amazon-ec2 gem. You'll find this to be a
|
35
35
|
great tool to help you debug issues and practice running commands
|
36
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
|
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
40
|
at the end of any command should give you a full String representation of the
|
41
|
-
response.
|
42
|
-
|
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
|
-
|
41
|
+
response.
|
42
|
+
|
48
43
|
Examples to try:
|
49
|
-
|
44
|
+
|
50
45
|
returns : all ec2 public methods
|
51
46
|
>> @ec2.methods.sort
|
52
|
-
|
47
|
+
|
53
48
|
returns : a string representation of ALL images
|
54
49
|
>> @ec2.describe_images.to_s
|
55
|
-
|
50
|
+
|
56
51
|
returns : an Array of EC2::Response objects, each an EC2 image and its data
|
57
52
|
>> @ec2.describe_images.imagesSet.item
|
58
53
|
>> @ec2.describe_images.imagesSet.item[0] (an OpenStruct of a single item in that array)
|
59
54
|
>> @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
|
-
|
55
|
+
|
67
56
|
MESSAGE
|
68
|
-
|
57
|
+
|
69
58
|
puts welcome_message
|
70
59
|
exec "#{irb_name} -r #{ec2_lib} -r #{setup} --simple-prompt"
|
71
60
|
else
|
data/bin/setup.rb
CHANGED
@@ -10,10 +10,17 @@
|
|
10
10
|
#++
|
11
11
|
|
12
12
|
if ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY']
|
13
|
-
|
13
|
+
opts = {
|
14
14
|
:access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
|
15
15
|
:secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
|
16
|
-
|
16
|
+
}
|
17
|
+
if ENV['EC2_URL']
|
18
|
+
opts[:server] = URI.parse(ENV['EC2_URL']).host
|
19
|
+
end
|
20
|
+
@ec2 = EC2::Base.new(opts)
|
17
21
|
end
|
18
22
|
|
23
|
+
puts "Current Options:"
|
24
|
+
pp opts
|
25
|
+
|
19
26
|
include EC2
|
data/lib/EC2.rb
CHANGED
@@ -28,12 +28,24 @@ module EC2
|
|
28
28
|
# from the query string to be signed.
|
29
29
|
# Note: The parameters in the path passed in must already be sorted in
|
30
30
|
# case-insensitive alphabetical order and must not be url encoded.
|
31
|
-
def EC2.canonical_string(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
def EC2.canonical_string(params, host = DEFAULT_HOST, method="POST", base="/")
|
32
|
+
# Sort, and encode parameters into a canonical string.
|
33
|
+
sorted_params = params.sort {|x,y| x[0] <=> y[0]}
|
34
|
+
encoded_params = sorted_params.collect do |p|
|
35
|
+
encoded = (CGI::escape(p[0].to_s) +
|
36
|
+
"=" + CGI::escape(p[1].to_s))
|
37
|
+
# Ensure spaces are encoded as '%20', not '+'
|
38
|
+
encoded.gsub('+', '%20')
|
39
|
+
end
|
40
|
+
sigquery = encoded_params.join("&")
|
41
|
+
|
42
|
+
# Generate the request description string
|
43
|
+
req_desc =
|
44
|
+
method + "\n" +
|
45
|
+
host + "\n" +
|
46
|
+
base + "\n" +
|
47
|
+
sigquery
|
48
|
+
|
37
49
|
end
|
38
50
|
|
39
51
|
# Encodes the given string with the secret_access_key, by taking the
|
@@ -44,7 +56,7 @@ module EC2
|
|
44
56
|
digest = OpenSSL::Digest::Digest.new('sha1')
|
45
57
|
b64_hmac =
|
46
58
|
Base64.encode64(
|
47
|
-
OpenSSL::HMAC.digest(digest, secret_access_key, str)).
|
59
|
+
OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","")
|
48
60
|
|
49
61
|
if urlencode
|
50
62
|
return CGI::escape(b64_hmac)
|
@@ -152,14 +164,13 @@ module EC2
|
|
152
164
|
params.reject! { |key, value| value.nil? or value.empty?}
|
153
165
|
|
154
166
|
params.merge!( {"Action" => action,
|
155
|
-
"SignatureVersion" => "
|
167
|
+
"SignatureVersion" => "2",
|
168
|
+
"SignatureMethod" => 'HmacSHA1',
|
156
169
|
"AWSAccessKeyId" => @access_key_id,
|
157
170
|
"Version" => API_VERSION,
|
158
171
|
"Timestamp"=>Time.now.getutc.iso8601} )
|
159
172
|
|
160
|
-
|
161
|
-
|
162
|
-
sig = get_aws_auth_param(sigquery, @secret_access_key)
|
173
|
+
sig = get_aws_auth_param(params, @secret_access_key)
|
163
174
|
|
164
175
|
query = params.sort.collect do |param|
|
165
176
|
CGI::escape(param[0]) + "=" + CGI::escape(param[1])
|
@@ -182,8 +193,8 @@ module EC2
|
|
182
193
|
end
|
183
194
|
|
184
195
|
# Set the Authorization header using AWS signed header authentication
|
185
|
-
def get_aws_auth_param(
|
186
|
-
canonical_string = EC2.canonical_string(
|
196
|
+
def get_aws_auth_param(params, secret_access_key)
|
197
|
+
canonical_string = EC2.canonical_string(params)
|
187
198
|
encoded_canonical = EC2.encode(secret_access_key, canonical_string)
|
188
199
|
end
|
189
200
|
|
data/lib/EC2/responses.rb
CHANGED
@@ -47,7 +47,7 @@ module EC2
|
|
47
47
|
def self.parse(options = {})
|
48
48
|
options = {
|
49
49
|
:xml => "",
|
50
|
-
:parse_options => { '
|
50
|
+
:parse_options => { 'forcearray' => ['item'], 'suppressempty' => nil, 'keeproot' => false }
|
51
51
|
}.merge(options)
|
52
52
|
|
53
53
|
# NOTE: Parsing the response as a nested set of Response objects was extremely
|
data/test/test_EC2.rb
CHANGED
@@ -39,9 +39,9 @@ context "The EC2 method " do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
|
42
|
-
specify "EC2.canonical_string(path) should
|
43
|
-
path = "
|
44
|
-
EC2.canonical_string(path).should.equal "
|
42
|
+
specify "EC2.canonical_string(path) should conform to Amazon's requirements " do
|
43
|
+
path = {"name1" => "value1", "name2" => "value2", "name3" => "value3"}
|
44
|
+
EC2.canonical_string(path).should.equal "POST\nec2.amazonaws.com\n/\nname1=value1&name2=value2&name3=value3"
|
45
45
|
end
|
46
46
|
|
47
47
|
specify "EC2.encode should return the expected string" do
|
data/test/test_EC2_instances.rb
CHANGED
@@ -91,13 +91,13 @@ context "EC2 instances " do
|
|
91
91
|
<name>running</name>
|
92
92
|
</instanceState>
|
93
93
|
<privateDnsName>domU-12-31-35-00-1E-01.z-2.compute-1.internal</privateDnsName>
|
94
|
-
|
94
|
+
<dnsName>ec2-72-44-33-4.z-2.compute-1.amazonaws.com</dnsName>
|
95
95
|
<keyName>example-key-name</keyName>
|
96
96
|
<productCodesSet>
|
97
97
|
<item><productCode>774F4FF8</productCode></item>
|
98
98
|
</productCodesSet>
|
99
99
|
<instanceType>m1.small</instanceType>
|
100
|
-
|
100
|
+
<launchTime>2007-08-07T11:54:42.000Z</launchTime>
|
101
101
|
</item>
|
102
102
|
</instancesSet>
|
103
103
|
</item>
|
@@ -0,0 +1,80 @@
|
|
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
|
+
# NOTE : These tests exercise amazon-ec2 when used with the aws/s3 gem
|
14
|
+
# which was demonstrating some breaking behavior. The fix was to
|
15
|
+
# add the XmlSimple option "'keeproot' => false" in responses.rb
|
16
|
+
|
17
|
+
context "EC2 aws-s3 compat test" do
|
18
|
+
|
19
|
+
setup do
|
20
|
+
@ec2 = EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
|
21
|
+
|
22
|
+
@describe_instances_response_body = <<-RESPONSE
|
23
|
+
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2007-08-29">
|
24
|
+
<reservationSet>
|
25
|
+
<item>
|
26
|
+
<reservationId>r-44a5402d</reservationId>
|
27
|
+
<ownerId>UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM</ownerId>
|
28
|
+
<groupSet>
|
29
|
+
<item>
|
30
|
+
<groupId>default</groupId>
|
31
|
+
</item>
|
32
|
+
</groupSet>
|
33
|
+
<instancesSet>
|
34
|
+
<item>
|
35
|
+
<instanceId>i-28a64341</instanceId>
|
36
|
+
<imageId>ami-6ea54007</imageId>
|
37
|
+
<instanceState>
|
38
|
+
<code>0</code>
|
39
|
+
<name>running</name>
|
40
|
+
</instanceState>
|
41
|
+
<privateDnsName>domU-12-31-35-00-1E-01.z-2.compute-1.internal</privateDnsName>
|
42
|
+
<dnsName>ec2-72-44-33-4.z-2.compute-1.amazonaws.com</dnsName>
|
43
|
+
<keyName>example-key-name</keyName>
|
44
|
+
<productCodesSet>
|
45
|
+
<item><productCode>774F4FF8</productCode></item>
|
46
|
+
</productCodesSet>
|
47
|
+
<instanceType>m1.small</instanceType>
|
48
|
+
<launchTime>2007-08-07T11:54:42.000Z</launchTime>
|
49
|
+
</item>
|
50
|
+
</instancesSet>
|
51
|
+
</item>
|
52
|
+
</reservationSet>
|
53
|
+
</DescribeInstancesResponse>
|
54
|
+
RESPONSE
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "should be able to be described and return the correct Ruby response class" do
|
59
|
+
@ec2.stubs(:make_request).with('DescribeInstances', {}).
|
60
|
+
returns stub(:body => @describe_instances_response_body, :is_a? => true)
|
61
|
+
@ec2.describe_instances.should.be.an.instance_of Hash
|
62
|
+
response = @ec2.describe_instances
|
63
|
+
response.reservationSet.item[0].reservationId.should.equal "r-44a5402d"
|
64
|
+
end
|
65
|
+
|
66
|
+
specify "should be able to be described and return the correct Ruby response class when the aws/s3 lib is required" do
|
67
|
+
begin
|
68
|
+
require 'aws/s3s'
|
69
|
+
@ec2.stubs(:make_request).with('DescribeInstances', {}).
|
70
|
+
returns stub(:body => @describe_instances_response_body, :is_a? => true)
|
71
|
+
@ec2.describe_instances.should.be.an.instance_of Hash
|
72
|
+
response = @ec2.describe_instances
|
73
|
+
response.reservationSet.item[0].reservationId.should.equal "r-44a5402d"
|
74
|
+
rescue LoadError
|
75
|
+
# do nothing. no aws/s3 gem installed to test against
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amazon-ec2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Glenn Rempe
|
@@ -9,7 +9,7 @@ autorequire: EC2
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-01-31 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -113,6 +113,7 @@ test_files:
|
|
113
113
|
- test/test_EC2_keypairs.rb
|
114
114
|
- test/test_EC2_products.rb
|
115
115
|
- test/test_EC2_responses.rb
|
116
|
+
- test/test_EC2_s3_xmlsimple.rb
|
116
117
|
- test/test_EC2_security_groups.rb
|
117
118
|
- test/test_EC2_snapshots.rb
|
118
119
|
- test/test_EC2_volumes.rb
|