#--
# Amazon Web Services EC2 Query API Ruby library
#
# Ruby Gem Name:: amazon-ec2
# Author:: Glenn Rempe (mailto:glenn@rempe.us)
# Copyright:: Copyright (c) 2007-2008 Glenn Rempe
# License:: Distributes under the same terms as Ruby
# Home:: http://github.com/grempe/amazon-ec2/tree/master
#++
require File.dirname(__FILE__) + '/test_helper.rb'
context "EC2 instances " do
setup do
@ec2 = EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
@run_instances_response_body = <<-RESPONSE
r-47a5402e
495219933132
-
default
-
i-2ba64342
ami-60a54009
0
pending
example-key-name
0
m1.small
2007-08-07T11:51:50.000Z
-
i-2bc64242
ami-60a54009
0
pending
example-key-name
1
m1.small
2007-08-07T11:51:50.000Z
-
i-2be64332
ami-60a54009
0
pending
example-key-name
2
m1.small
2007-08-07T11:51:50.000Z
RESPONSE
@describe_instances_response_body = <<-RESPONSE
-
r-44a5402d
UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM
-
default
-
i-28a64341
ami-6ea54007
0
running
domU-12-31-35-00-1E-01.z-2.compute-1.internal
ec2-72-44-33-4.z-2.compute-1.amazonaws.com
example-key-name
- 774F4FF8
m1.small
2007-08-07T11:54:42.000Z
RESPONSE
@reboot_instances_response_body = <<-RESPONSE
true
RESPONSE
@terminate_instances_response_body = <<-RESPONSE
-
i-28a64341
32
shutting-down
0
pending
-
i-21a64348
32
shutting-down
0
pending
RESPONSE
end
specify "should be able to be run" do
@ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "AddressingType" => 'public', 'InstanceType' => 'm1.small').
returns stub(:body => @run_instances_response_body, :is_a? => true)
@ec2.run_instances( :image_id => "ami-60a54009" ).should.be.an.instance_of Hash
response = @ec2.run_instances( :image_id => "ami-60a54009" )
response.reservationId.should.equal "r-47a5402e"
response.ownerId.should.equal "495219933132"
response.groupSet.item[0].groupId.should.equal "default"
response.instancesSet.item.length.should.equal 3
response.instancesSet.item[0].instanceId.should.equal "i-2ba64342"
response.instancesSet.item[0].imageId.should.equal "ami-60a54009"
response.instancesSet.item[0].instanceState.code.should.equal "0"
response.instancesSet.item[0].instanceState.name.should.equal "pending"
response.instancesSet.item[0].privateDnsName
response.instancesSet.item[0].dnsName.should.be.nil
response.instancesSet.item[0].keyName.should.equal "example-key-name"
response.instancesSet.item[0].instanceType.should.equal "m1.small"
response.instancesSet.item[0].launchTime.should.equal "2007-08-07T11:51:50.000Z"
response.instancesSet.item[1].instanceId.should.equal "i-2bc64242"
response.instancesSet.item[1].imageId.should.equal "ami-60a54009"
response.instancesSet.item[1].instanceState.code.should.equal "0"
response.instancesSet.item[1].instanceState.name.should.equal "pending"
response.instancesSet.item[1].privateDnsName
response.instancesSet.item[1].dnsName.should.be.nil
response.instancesSet.item[1].keyName.should.equal "example-key-name"
response.instancesSet.item[1].instanceType.should.equal "m1.small"
response.instancesSet.item[1].launchTime.should.equal "2007-08-07T11:51:50.000Z"
response.instancesSet.item[2].instanceId.should.equal "i-2be64332"
response.instancesSet.item[2].imageId.should.equal "ami-60a54009"
response.instancesSet.item[2].instanceState.code.should.equal "0"
response.instancesSet.item[2].instanceState.name.should.equal "pending"
response.instancesSet.item[2].privateDnsName
response.instancesSet.item[2].dnsName.should.be.nil
response.instancesSet.item[2].keyName.should.equal "example-key-name"
response.instancesSet.item[2].instanceType.should.equal "m1.small"
response.instancesSet.item[2].launchTime.should.equal "2007-08-07T11:51:50.000Z"
end
specify "method 'run_instances' should reject invalid arguments" do
@ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "AddressingType" => 'public', 'InstanceType' => 'm1.small').
returns stub(:body => @run_instances_response_body, :is_a? => true)
lambda { @ec2.run_instances() }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "" ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1 ) }.should.not.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 0 ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => nil ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => "" ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => 1 ) }.should.not.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => 0 ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => nil ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => "" ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => "public" ) }.should.not.raise(EC2::ArgumentError)
#lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => "direct" ) }.should.not.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => nil ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => "" ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => "foo" ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => true ) }.should.not.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => false ) }.should.not.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => nil ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => "" ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => "foo" ) }.should.raise(EC2::ArgumentError)
end
specify "should be able specify an availability_zone" do
@ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Placement.AvailabilityZone" => "zone123", "UserData" => "Zm9v", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
returns stub(:body => @run_instances_response_body, :is_a? => true)
@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
end
specify "should be able to call run_instances with :user_data and :base64_encoded => true (default is false)" do
@ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "Zm9v", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
returns stub(:body => @run_instances_response_body, :is_a? => true)
@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
end
specify "should be able specify an kernel_id" do
@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').
returns stub(:body => @run_instances_response_body, :is_a? => true)
@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
end
specify "should be able to call run_instances with :user_data and :base64_encoded => false" do
@ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "foo", "AddressingType" => 'public', 'InstanceType' => 'm1.small').
returns stub(:body => @run_instances_response_body, :is_a? => true)
@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
end
specify "should get no user data for when options has no user_data key" do
@ec2.extract_user_data({}).should == nil
end
specify "should get plain string user data when options has user_data and no base64 key" do
@ec2.extract_user_data({:user_data => "foo\nbar"}).should == "foo\nbar"
end
specify "should strip new lines and base64 encode when options has both user_data and base64" do
@ec2.extract_user_data({:user_data => "binary\ndata\nhere\n", :base64_encoded => true}).should == "YmluYXJ5CmRhdGEKaGVyZQo="
end
specify "should be able to be described and return the correct Ruby response class" do
@ec2.stubs(:make_request).with('DescribeInstances', {}).
returns stub(:body => @describe_instances_response_body, :is_a? => true)
@ec2.describe_instances.should.be.an.instance_of Hash
response = @ec2.describe_instances
response.reservationSet.item[0].reservationId.should.equal "r-44a5402d"
end
specify "should be able to be described with no params and return an array of Items" do
@ec2.stubs(:make_request).with('DescribeInstances', {}).
returns stub(:body => @describe_instances_response_body, :is_a? => true)
@ec2.describe_instances.reservationSet.item.length.should.equal 1
response = @ec2.describe_instances
response.reservationSet.item[0].reservationId.should.equal "r-44a5402d"
response.reservationSet.item[0].ownerId.should.equal "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM"
response.reservationSet.item[0].groupSet.item[0].groupId.should.equal "default"
response.reservationSet.item[0].instancesSet.item[0].instanceId.should.equal "i-28a64341"
response.reservationSet.item[0].instancesSet.item[0].imageId.should.equal "ami-6ea54007"
response.reservationSet.item[0].instancesSet.item[0].instanceState.code.should.equal "0"
response.reservationSet.item[0].instancesSet.item[0].instanceState.name.should.equal "running"
response.reservationSet.item[0].instancesSet.item[0].privateDnsName.should.equal "domU-12-31-35-00-1E-01.z-2.compute-1.internal"
response.reservationSet.item[0].instancesSet.item[0].dnsName.should.equal "ec2-72-44-33-4.z-2.compute-1.amazonaws.com"
response.reservationSet.item[0].instancesSet.item[0].keyName.should.equal "example-key-name"
response.reservationSet.item[0].instancesSet.item[0].productCodesSet.item[0].productCode.should.equal "774F4FF8"
end
specify "should be able to be described with params of Array of :instance_id's and return an array of Items" do
@ec2.stubs(:make_request).with('DescribeInstances', {"InstanceId.1" => "i-28a64341"}).
returns stub(:body => @describe_instances_response_body, :is_a? => true)
@ec2.describe_instances( :instance_id => "i-28a64341" ).reservationSet.item.length.should.equal 1
response = @ec2.describe_instances( :instance_id => "i-28a64341" )
response.reservationSet.item[0].reservationId.should.equal "r-44a5402d"
response.reservationSet.item[0].ownerId.should.equal "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM"
response.reservationSet.item[0].groupSet.item[0].groupId.should.equal "default"
response.reservationSet.item[0].instancesSet.item[0].instanceId.should.equal "i-28a64341"
response.reservationSet.item[0].instancesSet.item[0].imageId.should.equal "ami-6ea54007"
response.reservationSet.item[0].instancesSet.item[0].instanceState.code.should.equal "0"
response.reservationSet.item[0].instancesSet.item[0].instanceState.name.should.equal "running"
response.reservationSet.item[0].instancesSet.item[0].privateDnsName.should.equal "domU-12-31-35-00-1E-01.z-2.compute-1.internal"
response.reservationSet.item[0].instancesSet.item[0].dnsName.should.equal "ec2-72-44-33-4.z-2.compute-1.amazonaws.com"
response.reservationSet.item[0].instancesSet.item[0].keyName.should.equal "example-key-name"
response.reservationSet.item[0].instancesSet.item[0].productCodesSet.item[0].productCode.should.equal "774F4FF8"
end
specify "method reboot_instances should raise an exception when called without nil/empty string arguments" do
lambda { @ec2.reboot_instances() }.should.raise(EC2::ArgumentError)
lambda { @ec2.reboot_instances( :instance_id => nil ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.reboot_instances( :instance_id => "" ) }.should.raise(EC2::ArgumentError)
end
specify "should be able to be rebooted when provided with an :instance_id" do
@ec2.expects(:make_request).with('RebootInstances', {"InstanceId.1"=>"i-2ea64347", "InstanceId.2"=>"i-21a64348"}).
returns stub(:body => @reboot_instances_response_body, :is_a? => true)
@ec2.reboot_instances( :instance_id => ["i-2ea64347", "i-21a64348"] ).class.should.equal Hash
end
specify "method terminate_instances should raise an exception when called without nil/empty string arguments" do
lambda { @ec2.terminate_instances() }.should.raise(EC2::ArgumentError)
lambda { @ec2.terminate_instances( :instance_id => nil ) }.should.raise(EC2::ArgumentError)
lambda { @ec2.terminate_instances( :instance_id => "" ) }.should.raise(EC2::ArgumentError)
end
specify "should be able to be terminated when provided with an :instance_id" do
@ec2.stubs(:make_request).with('TerminateInstances', {"InstanceId.1"=>"i-28a64341", "InstanceId.2"=>"i-21a64348"}).
returns stub(:body => @terminate_instances_response_body, :is_a? => true)
@ec2.terminate_instances( :instance_id => ["i-28a64341", "i-21a64348"] ).class.should.equal Hash
@response = @ec2.terminate_instances( :instance_id => ["i-28a64341", "i-21a64348"] )
@response.instancesSet.item[0].instanceId.should.equal "i-28a64341"
@response.instancesSet.item[0].shutdownState.code.should.equal "32"
@response.instancesSet.item[0].shutdownState.name.should.equal "shutting-down"
@response.instancesSet.item[0].previousState.code.should.equal "0"
@response.instancesSet.item[0].previousState.name.should.equal "pending"
@response.instancesSet.item[1].instanceId.should.equal "i-21a64348"
@response.instancesSet.item[1].shutdownState.code.should.equal "32"
@response.instancesSet.item[1].shutdownState.name.should.equal "shutting-down"
@response.instancesSet.item[1].previousState.code.should.equal "0"
@response.instancesSet.item[1].previousState.name.should.equal "pending"
end
end