kunley-amazon-ec2 0.3.4 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,17 @@
1
+ === 0.3.8 2009-04-16
2
+ * Applied patch, fixing an issue with EU Signature version 2 creation (delano).
3
+
4
+ === 0.3.7 2009-03-09
5
+ * Applied patch, with updated tests to fix issue with base64 encoded user data (rsanheim).
6
+
7
+ === 0.3.6 2009-03-02
8
+ * You can now specify any arbitrary SSL tcp port to connect to (kerryb)
9
+ * Added rake target to quickly install the gem without docs
10
+
11
+ === 0.3.5 2009-02-26
12
+ * Honor the EC2_URL env var if provided in the main lib
13
+ * Some minor modifications to the exceptions raised when unknown
14
+
1
15
  === 0.3.4 2009-01-31
2
16
  * Added support in the helper binaries for EC2_URL server url for Euro servers
3
17
  * AWS Signature v2 support
data/Rakefile CHANGED
@@ -16,6 +16,11 @@ task :install => [:package] do
16
16
  sh %{sudo gem install pkg/#{GEM}-#{VER}}
17
17
  end
18
18
 
19
+ desc "Package and then install the gem locally omitting documentation"
20
+ task :install_nodoc => [:package] do
21
+ sh %{sudo gem install --no-ri --no-rdoc pkg/#{GEM}-#{VER}}
22
+ end
23
+
19
24
  Rake::TestTask.new do |t|
20
25
  t.libs << "test"
21
26
  t.test_files = FileList['test/test*.rb']
@@ -28,3 +33,5 @@ Rake::RDocTask.new do |rd|
28
33
  rd.rdoc_dir = 'doc'
29
34
  rd.options = spec.rdoc_options
30
35
  end
36
+
37
+ task :default => :test
@@ -30,7 +30,16 @@ if ACCESS_KEY_ID.nil? || ACCESS_KEY_ID.empty?
30
30
  exit
31
31
  end
32
32
 
33
- ec2 = EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY )
33
+ # us-east-1.ec2.amazonaws.com == ec2.amazonaws.com
34
+ # eu-west-1.ec2.amazonaws.com for the european region
35
+ # test different servers by running something like:
36
+ # export EC2_URL='https://ec2.amazonaws.com';./bin/ec2-gem-example.rb
37
+ if ENV['EC2_URL']
38
+ ec2 = EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY, :server => URI.parse(ENV['EC2_URL']).host )
39
+ else
40
+ # default server is US ec2.amazonaws.com
41
+ ec2 = EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY )
42
+ end
34
43
 
35
44
  puts "----- ec2.methods.sort -----"
36
45
  p ec2.methods.sort
@@ -20,7 +20,6 @@ if ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY']
20
20
  @ec2 = EC2::Base.new(opts)
21
21
  end
22
22
 
23
- puts "Current Options:"
24
- pp opts
23
+ puts "EC2 Server: #{opts[:server]}"
25
24
 
26
25
  include EC2
data/lib/EC2.rb CHANGED
@@ -19,7 +19,19 @@ Dir[File.join(File.dirname(__FILE__), 'EC2/**/*.rb')].sort.each { |lib| require
19
19
  module EC2
20
20
 
21
21
  # Which host FQDN will we connect to for all API calls to AWS?
22
- DEFAULT_HOST = 'ec2.amazonaws.com'
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
23
35
 
24
36
  # This is the version of the API as defined by Amazon Web Services
25
37
  API_VERSION = '2008-12-01'
@@ -32,7 +44,7 @@ module EC2
32
44
  # Sort, and encode parameters into a canonical string.
33
45
  sorted_params = params.sort {|x,y| x[0] <=> y[0]}
34
46
  encoded_params = sorted_params.collect do |p|
35
- encoded = (CGI::escape(p[0].to_s) +
47
+ encoded = (CGI::escape(p[0].to_s) +
36
48
  "=" + CGI::escape(p[1].to_s))
37
49
  # Ensure spaces are encoded as '%20', not '+'
38
50
  encoded.gsub('+', '%20')
@@ -40,10 +52,10 @@ module EC2
40
52
  sigquery = encoded_params.join("&")
41
53
 
42
54
  # Generate the request description string
43
- req_desc =
44
- method + "\n" +
45
- host + "\n" +
46
- base + "\n" +
55
+ req_desc =
56
+ method + "\n" +
57
+ host + "\n" +
58
+ base + "\n" +
47
59
  sigquery
48
60
 
49
61
  end
@@ -106,14 +118,14 @@ module EC2
106
118
  raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil?
107
119
  raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false
108
120
  raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty?
109
-
110
-
111
- # based on the :use_ssl boolean, determine which port we should connect to
112
- case @use_ssl
113
- when true
121
+
122
+ if options[:port]
123
+ # user-specified port
124
+ @port = options[:port]
125
+ elsif @use_ssl
114
126
  # https
115
127
  @port = 443
116
- when false
128
+ else
117
129
  # http
118
130
  @port = 80
119
131
  end
@@ -170,7 +182,7 @@ module EC2
170
182
  "Version" => API_VERSION,
171
183
  "Timestamp"=>Time.now.getutc.iso8601} )
172
184
 
173
- sig = get_aws_auth_param(params, @secret_access_key)
185
+ sig = get_aws_auth_param(params, @secret_access_key, @server)
174
186
 
175
187
  query = params.sort.collect do |param|
176
188
  CGI::escape(param[0]) + "=" + CGI::escape(param[1])
@@ -193,8 +205,8 @@ module EC2
193
205
  end
194
206
 
195
207
  # Set the Authorization header using AWS signed header authentication
196
- def get_aws_auth_param(params, secret_access_key)
197
- canonical_string = EC2.canonical_string(params)
208
+ def get_aws_auth_param(params, secret_access_key, server)
209
+ canonical_string = EC2.canonical_string(params, server)
198
210
  encoded_canonical = EC2.encode(secret_access_key, canonical_string)
199
211
  end
200
212
 
@@ -248,7 +260,7 @@ module EC2
248
260
  if EC2.const_defined?(error_code)
249
261
  raise EC2.const_get(error_code), error_message
250
262
  else
251
- raise Error, "This is an undefined error code which needs to be added to exceptions.rb : error_code => #{error_code} : error_message => #{error_message}"
263
+ raise EC2::Error, error_message
252
264
  end
253
265
 
254
266
  end
@@ -32,6 +32,14 @@ module EC2
32
32
  class AuthFailure < Error #:nodoc:
33
33
  end
34
34
 
35
+ # Invalid AWS Account
36
+ class InvalidClientTokenId < Error #:nodoc:
37
+ end
38
+
39
+ # Invalid Parameters for Value
40
+ class InvalidParameterValue < Error #:nodoc:
41
+ end
42
+
35
43
  # Specified AMI has an unparsable manifest.
36
44
  class InvalidManifest < Error #:nodoc:
37
45
  end
@@ -133,4 +141,7 @@ module EC2
133
141
  class Unavailable < Error #:nodoc:
134
142
  end
135
143
 
144
+ class SignatureDoesNotMatch < Error #:nodoc:
145
+ end
146
+
136
147
  end
@@ -90,18 +90,7 @@ module EC2
90
90
  raise ArgumentError, ":instance_type must be 'm1.small', 'm1.large', 'm1.xlarge', 'c1.medium', or 'c1.xlarge'" unless options[:instance_type] == "m1.small" || options[:instance_type] == "m1.large" || options[:instance_type] == "m1.xlarge" || options[:instance_type] == "c1.medium" || options[:instance_type] == "c1.xlarge"
91
91
  raise ArgumentError, ":base64_encoded must be 'true' or 'false'" unless options[:base64_encoded] == true || options[:base64_encoded] == false
92
92
 
93
- # If :user_data is passed in then URL escape and Base64 encode it
94
- # as needed. Need for URL Escape + Base64 encoding is determined
95
- # by :base64_encoded param.
96
- if options[:user_data]
97
- if options[:base64_encoded]
98
- user_data = options[:user_data]
99
- else
100
- user_data = Base64.encode64(options[:user_data]).gsub(/\n/,"").strip()
101
- end
102
- else
103
- user_data = nil
104
- end
93
+ user_data = extract_user_data(options)
105
94
 
106
95
  params = {
107
96
  "ImageId" => options[:image_id],
@@ -119,6 +108,20 @@ module EC2
119
108
  return response_generator(:action => "RunInstances", :params => params)
120
109
 
121
110
  end
111
+
112
+ # If :user_data is passed in then URL escape and Base64 encode it
113
+ # as needed. Need for URL Escape + Base64 encoding is determined
114
+ # by :base64_encoded param.
115
+ def extract_user_data(options)
116
+ return unless options[:user_data]
117
+ if options[:user_data]
118
+ if options[:base64_encoded]
119
+ Base64.encode64(options[:user_data]).gsub(/\n/,"").strip()
120
+ else
121
+ options[:user_data]
122
+ end
123
+ end
124
+ end
122
125
 
123
126
 
124
127
  #Amazon Developer Guide Docs:
@@ -17,31 +17,47 @@ context "The EC2 method " do
17
17
 
18
18
  specify "EC2::Base attribute readers should be available" do
19
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" )
20
+ :secret_access_key => "not a secret",
21
+ :use_ssl => true,
22
+ :server => "foo.example.com" )
23
23
 
24
24
  @ec2.use_ssl.should.equal true
25
25
  @ec2.port.should.equal 443
26
26
  @ec2.server.should.equal "foo.example.com"
27
27
  end
28
28
 
29
-
30
29
  specify "EC2::Base should work with insecure connections as well" do
31
30
  @ec2 = EC2::Base.new( :access_key_id => "not a key",
32
- :secret_access_key => "not a secret",
33
- :use_ssl => false,
34
- :server => "foo.example.com" )
31
+ :secret_access_key => "not a secret",
32
+ :use_ssl => false,
33
+ :server => "foo.example.com" )
35
34
 
36
35
  @ec2.use_ssl.should.equal false
37
36
  @ec2.port.should.equal 80
38
37
  @ec2.server.should.equal "foo.example.com"
39
38
  end
40
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
41
51
 
42
52
  specify "EC2.canonical_string(path) should conform to Amazon's requirements " do
43
53
  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"
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
45
61
  end
46
62
 
47
63
  specify "EC2.encode should return the expected string" do
@@ -221,28 +221,40 @@ context "EC2 instances " do
221
221
 
222
222
 
223
223
  specify "should be able specify an availability_zone" do
224
- @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Placement.AvailabilityZone" => "zone123", "UserData" => "foo", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
224
+ @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Placement.AvailabilityZone" => "zone123", "UserData" => "Zm9v", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
225
225
  returns stub(:body => @run_instances_response_body, :is_a? => true)
226
226
  @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1, :availability_zone => "zone123", :group_id => [], :user_data => "foo", :base64_encoded => true ).should.be.an.instance_of Hash
227
227
  end
228
228
 
229
229
  specify "should be able to call run_instances with :user_data and :base64_encoded => true (default is false)" do
230
- @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "foo", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
230
+ @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "Zm9v", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
231
231
  returns stub(:body => @run_instances_response_body, :is_a? => true)
232
232
  @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1, :group_id => [], :user_data => "foo", :base64_encoded => true ).should.be.an.instance_of Hash
233
233
  end
234
234
 
235
235
  specify "should be able specify an kernel_id" do
236
- @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Placement.AvailabilityZone" => "zone123", "UserData" => "foo", "AddressingType" => 'public', 'InstanceType' => 'm1.small', 'KernelId' => 'kernfoo').
236
+ @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Placement.AvailabilityZone" => "zone123", "UserData" => "Zm9v", "AddressingType" => 'public', 'InstanceType' => 'm1.small', 'KernelId' => 'kernfoo').
237
237
  returns stub(:body => @run_instances_response_body, :is_a? => true)
238
238
  @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1, :availability_zone => "zone123", :group_id => [], :user_data => "foo", :base64_encoded => true, :kernel_id => 'kernfoo' ).should.be.an.instance_of Hash
239
239
  end
240
240
 
241
241
  specify "should be able to call run_instances with :user_data and :base64_encoded => false" do
242
- @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "Zm9v", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
242
+ @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "foo", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
243
243
  returns stub(:body => @run_instances_response_body, :is_a? => true)
244
244
  @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1, :group_id => [], :user_data => "foo", :base64_encoded => false ).should.be.an.instance_of Hash
245
245
  end
246
+
247
+ specify "should get no user data for when options has no user_data key" do
248
+ @ec2.extract_user_data({}).should == nil
249
+ end
250
+
251
+ specify "should get plain string user data when options has user_data and no base64 key" do
252
+ @ec2.extract_user_data({:user_data => "foo\nbar"}).should == "foo\nbar"
253
+ end
254
+
255
+ specify "should strip new lines and base64 encode when options has both user_data and base64" do
256
+ @ec2.extract_user_data({:user_data => "binary\ndata\nhere\n", :base64_encoded => true}).should == "YmluYXJ5CmRhdGEKaGVyZQo="
257
+ end
246
258
 
247
259
 
248
260
  specify "should be able to be described and return the correct Ruby response class" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kunley-amazon-ec2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glenn Rempe
@@ -9,11 +9,12 @@ autorequire: EC2
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-11 00:00:00 -08:00
12
+ date: 2009-04-08 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: xml-simple
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -22,7 +23,7 @@ dependencies:
22
23
  version: 1.0.11
23
24
  version:
24
25
  description: An interface library that allows Ruby applications to easily connect to the HTTP 'Query API' for the Amazon Web Services Elastic Compute Cloud (EC2) and manipulate cloud servers.
25
- email: glenn.rempe@gmail.com
26
+ email: glenn@rempe.us
26
27
  executables:
27
28
  - ec2-gem-example.rb
28
29
  - ec2sh