Skip to content
This repository has been archived by the owner on Jan 20, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:grempe/amazon-ec2
Browse files Browse the repository at this point in the history
  • Loading branch information
grempe committed Nov 29, 2011
2 parents 6a8ad98 + e091307 commit 324247c
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 105 deletions.
4 changes: 2 additions & 2 deletions README.rdoc
Expand Up @@ -65,8 +65,8 @@ Edit the file ~/.bash_login and add the following to the existing contents:
export RUBYOPT="rubygems"

# For amazon-ec2 and amazon s3 ruby gems
export AMAZON_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID"
export AMAZON_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY_ID"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY_ID"

If you are using EC2 in the EU region, make sure you also set:

Expand Down
98 changes: 51 additions & 47 deletions bin/awshell
@@ -1,5 +1,8 @@
#!/usr/bin/env ruby

require 'rubygems' if RUBY_VERSION < '1.9'
require 'irb'

# Amazon Web Services EC2 Query API Ruby library
#
# Ruby Gem Name:: amazon-ec2
Expand All @@ -12,70 +15,71 @@
# CREDITS : Credit for this bit of shameful ripoff coolness
# goes to Marcel Molina and his AWS::S3 gem. Thanks!

aws_lib = File.dirname(__FILE__) + '/../lib/AWS'
setup = File.dirname(__FILE__) + '/setup'
irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
require File.dirname(__FILE__) + '/../lib/AWS'

welcome_message = <<-MESSAGE
setup = File.dirname(__FILE__) + '/setup'

Usage :
def welcome!
puts <<-MESSAGE
This is an interactive Ruby 'irb' shell that allows you to use the
AWS commands available in the 'amazon-ec2' gem. This can be a
great tool to help you debug issues and run commands
against the live AWS servers. You can do anything in this
shell that you can in a normal irb shell.
Usage :
Config :
This is an interactive Ruby 'irb' shell that allows you to use the
AWS commands available in the 'amazon-ec2' gem. This can be a
great tool to help you debug issues and run commands
against the live AWS servers. You can do anything in this
shell that you can in a normal irb shell.
You must set the following environment variables that contain your
AWS credentials in your system shell for this to work.
Config :
AMAZON_ACCESS_KEY_ID
AMAZON_SECRET_ACCESS_KEY
You must set the following environment variables that contain your
AWS credentials in your system shell for this to work.
Each AWS service has its own default server endpoints. You can override
the endpoints with the following environment variables set in your
system shell:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
EC2 : EC2_URL
Elastic Load Balancing : ELB_URL
AutoScaling : AS_URL
RDS : RDS_URL
CloudWatch : AWS_CLOUDWATCH_URL
Each AWS service has its own default server endpoints. You can override
the endpoints with the following environment variables set in your
system shell:
For your convenience, the various AWS services are wired up in this shell
to the following class variables. You can execute methods on each of these:
EC2 : EC2_URL
Elastic Load Balancing : ELB_URL
AutoScaling : AS_URL
RDS : RDS_URL
CloudWatch : AWS_CLOUDWATCH_URL
@ec2 (Elastic Compute Cloud)
@elb (Elastic Load Balancing)
@as (AutoScaling)
@rds (Relational Database Service)
@cw (CloudWatch)
For your convenience, the various AWS services are wired up in this shell
to the following class variables. You can execute methods on each of these:
You can make method calls on these instances to execute commands against
the various services. Pre-pending a 'pp' should give you a pretty printed
version of the response which may be easier to read.
@ec2 (Elastic Compute Cloud)
@elb (Elastic Load Balancing)
@as (AutoScaling)
@rds (Relational Database Service)
@cw (CloudWatch)
Examples:
You can make method calls on these instances to execute commands against
the various services. Pre-pending a 'pp' should give you a pretty printed
version of the response which may be easier to read.
returns : Pretty Print all ec2 public methods
>> pp @ec2.methods.sort
Examples:
returns : Pretty Print a Hash describing your EC2 images
>> @ec2.describe_images(:owner_id => ['self'])
returns : Pretty Print all ec2 public methods
>> pp @ec2.methods.sort
returns : an Array of AWS::Response objects, each an EC2 image and its data
>> @ec2.describe_images(:owner_id => ['self']).imagesSet.item
>> @ec2.describe_images(:owner_id => ['self']).imagesSet.item[0]
returns : Pretty Print a Hash describing your EC2 images
>> @ec2.describe_images(:owner_id => ['self'])
returns : an Array of AWS::Response objects, each an EC2 image and its data
>> @ec2.describe_images(:owner_id => ['self']).imagesSet.item
>> @ec2.describe_images(:owner_id => ['self']).imagesSet.item[0]
MESSAGE
end

if ( ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY'] )
puts welcome_message
exec "#{irb_name} -rubygems -r #{aws_lib} -r #{setup} --simple-prompt"
if((ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY']) || (ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY']))
puts "Please type 'welcome!' for an introduction on amazon-ec2"
IRB.start
require setup
else
puts "You must define AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY as shell environment variables before running #{$0}!"
puts welcome_message
puts "You must define AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as shell environment variables before running #{$0}!"
puts welcome!
end

10 changes: 5 additions & 5 deletions bin/ec2-gem-example.rb
Expand Up @@ -18,14 +18,14 @@
# e.g. in ~/.bash_login
#
# # For amazon-ec2 and amazon s3 ruby gems
# export AMAZON_ACCESS_KEY_ID="FOO"
# export AMAZON_SECRET_ACCESS_KEY="BAR"
# export AWS_SECRET_ACCESS_KEY="FOO"
# export AWS_SECRET_ACCESS_KEY="BAR"

ACCESS_KEY_ID = ENV['AMAZON_ACCESS_KEY_ID']
SECRET_ACCESS_KEY = ENV['AMAZON_SECRET_ACCESS_KEY']
ACCESS_KEY_ID = ENV['AWS_ACCESS_KEY_ID'] || ENV['AMAZON_ACCESS_KEY_ID']
SECRET_ACCESS_KEY = ENV['AWS_SECRET_ACCESS_KEY'] || ENV['AMAZON_SECRET_ACCESS_KEY']

if ACCESS_KEY_ID.nil? || ACCESS_KEY_ID.empty?
puts "Error : You must add the shell environment variables AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY before calling #{$0}!"
puts "Error : You must add the shell environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before calling #{$0}!"
exit
end

Expand Down
7 changes: 4 additions & 3 deletions bin/ec2-gem-profile.rb
Expand Up @@ -3,8 +3,9 @@
# Basic single command application that we can call with perftools.rb to get consistent results.

require File.dirname(__FILE__) + '/../lib/AWS'
ACCESS_KEY_ID = ENV['AMAZON_ACCESS_KEY_ID']
SECRET_ACCESS_KEY = ENV['AMAZON_SECRET_ACCESS_KEY']
ACCESS_KEY_ID = ENV['AWS_ACCESS_KEY_ID'] || ENV['AMAZON_ACCESS_KEY_ID']
SECRET_ACCESS_KEY = ENV['AWS_SECRET_ACCESS_KEY'] || ENV['AMAZON_SECRET_ACCESS_KEY']

ec2 = AWS::EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY )
@images = ec2.describe_images

@images = ec2.describe_images
8 changes: 5 additions & 3 deletions bin/setup.rb
Expand Up @@ -9,11 +9,13 @@
# Home:: http://github.com/grempe/amazon-ec2/tree/master
#++

if ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY']


if(AWS::ACCESS_KEY_ID and AWS::SECRET_ACCESS_KEY)

opts = {
:access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
:secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
:access_key_id => AWS::ACCESS_KEY_ID,
:secret_access_key => AWS::SECRET_ACCESS_KEY
}

if ENV['EC2_URL']
Expand Down
7 changes: 4 additions & 3 deletions lib/AWS.rb
Expand Up @@ -50,6 +50,8 @@ def does_not_have?(key)


module AWS
ACCESS_KEY_ID = ENV['AWS_ACCESS_KEY_ID'] || ENV['AMAZON_ACCESS_KEY_ID'] || ""
SECRET_ACCESS_KEY = ENV['AWS_SECRET_ACCESS_KEY'] || ENV['AMAZON_SECRET_ACCESS_KEY'] || ""

# Builds the canonical string for signing requests. This strips out all '&', '?', and '='
# from the query string to be signed. The parameters in the path passed in must already
Expand Down Expand Up @@ -111,7 +113,6 @@ def AWS.encode(secret_access_key, str, urlencode=true)
# interface. You should not instantiate this directly, instead
# you should setup an instance of 'AWS::EC2::Base' or 'AWS::ELB::Base'.
class Base

attr_reader :use_ssl, :server, :proxy_server, :port

# @option options [String] :access_key_id ("") The user's AWS Access Key ID
Expand All @@ -122,8 +123,8 @@ class Base
# @return [Object] the object.
def initialize( options = {} )

options = { :access_key_id => "",
:secret_access_key => "",
options = { :access_key_id => ACCESS_KEY_ID,
:secret_access_key => SECRET_ACCESS_KEY,
:use_ssl => true,
:server => default_host,
:path => "/",
Expand Down
10 changes: 10 additions & 0 deletions lib/AWS/EC2/images.rb
Expand Up @@ -130,16 +130,26 @@ def register_image( options = {} )
#
# Deregistered images will be included in the returned results for an unspecified interval subsequent to
# deregistration.
#
# The results can be filtered using the filter argument. The EC2 API reference for a full description of
# filter types and arguments.
#
# @example
# @ec2.describe_images(:owner_id => ['self'], :filter => [{"tag:Role" => "App"}])
#
# @option options [Array] :image_id ([])
# @option options [Array] :owner_id ([])
# @option options [Array] :executable_by ([])
# @option options [Array] :filter ([])
#
def describe_images( options = {} )
options = { :image_id => [], :owner_id => [], :executable_by => [] }.merge(options)
params = pathlist( "ImageId", options[:image_id] )
params.merge!(pathlist( "Owner", options[:owner_id] ))
params.merge!(pathlist( "ExecutableBy", options[:executable_by] ))
if options[:filter]
params.merge!(pathkvlist('Filter', options[:filter], 'Name', 'Value', {}))
end
return response_generator(:action => "DescribeImages", :params => params)
end

Expand Down
38 changes: 20 additions & 18 deletions lib/AWS/EC2/security_groups.rb
Expand Up @@ -80,7 +80,7 @@ def delete_security_group( options = {} )
# @option options [optional, Integer] :to_port (nil) Required when authorizing CIDR IP permission
# @option options [optional, String] :cidr_ip (nil) Required when authorizing CIDR IP permission
# @option options [optional, String] :source_security_group_name (nil) Required when authorizing user group pair permissions
# @option options [optional, String] :source_security_group_owner_id (nil) Required when authorizing user group pair permissions
# @option options [optional, String] :source_security_group_user_id (nil) Required when authorizing user group pair permissions
#
def authorize_security_group_ingress( options = {} )
options = { :group_name => nil,
Expand All @@ -89,20 +89,21 @@ def authorize_security_group_ingress( options = {} )
:to_port => nil,
:cidr_ip => nil,
:source_security_group_name => nil,
:source_security_group_owner_id => nil }.merge(options)
:source_security_group_user_id => nil }.merge(options)

# lets not validate the rest of the possible permutations of required params and instead let
# EC2 sort it out on the server side. We'll only require :group_name as that is always needed.
raise ArgumentError, "No :group_name provided" if options[:group_name].nil? || options[:group_name].empty?

params = { "GroupName" => options[:group_name],
"IpProtocol" => options[:ip_protocol],
"FromPort" => options[:from_port].to_s,
"ToPort" => options[:to_port].to_s,
"CidrIp" => options[:cidr_ip],
"SourceSecurityGroupName" => options[:source_security_group_name],
"SourceSecurityGroupOwnerId" => options[:source_security_group_owner_id]
}
"IpPermissions.1.IpProtocol" => options[:ip_protocol],
"IpPermissions.1.FromPort" => options[:from_port].to_s,
"IpPermissions.1.ToPort" => options[:to_port].to_s,
"IpPermissions.1.IpRanges.1" => options[:cidr_ip],
"IpPermissions.1.Groups.1.GroupName" => options[:source_security_group_name],
"IpPermissions.1.Groups.1.UserId" => options[:source_security_group_user_id]
}

return response_generator(:action => "AuthorizeSecurityGroupIngress", :params => params)
end

Expand Down Expand Up @@ -131,7 +132,7 @@ def authorize_security_group_ingress( options = {} )
# @option options [optional, Integer] :to_port (nil) Required when revoking CIDR IP permission
# @option options [optional, String] :cidr_ip (nil) Required when revoking CIDR IP permission
# @option options [optional, String] :source_security_group_name (nil) Required when revoking user group pair permissions
# @option options [optional, String] :source_security_group_owner_id (nil) Required when revoking user group pair permissions
# @option options [optional, String] :source_security_group_user_id (nil) Required when revoking user group pair permissions
#
def revoke_security_group_ingress( options = {} )
options = { :group_name => nil,
Expand All @@ -140,20 +141,21 @@ def revoke_security_group_ingress( options = {} )
:to_port => nil,
:cidr_ip => nil,
:source_security_group_name => nil,
:source_security_group_owner_id => nil }.merge(options)
:source_security_group_user_id => nil }.merge(options)

# lets not validate the rest of the possible permutations of required params and instead let
# EC2 sort it out on the server side. We'll only require :group_name as that is always needed.
raise ArgumentError, "No :group_name provided" if options[:group_name].nil? || options[:group_name].empty?

params = { "GroupName" => options[:group_name],
"IpProtocol" => options[:ip_protocol],
"FromPort" => options[:from_port].to_s,
"ToPort" => options[:to_port].to_s,
"CidrIp" => options[:cidr_ip],
"SourceSecurityGroupName" => options[:source_security_group_name],
"SourceSecurityGroupOwnerId" => options[:source_security_group_owner_id]
}
"IpPermissions.1.IpProtocol" => options[:ip_protocol],
"IpPermissions.1.FromPort" => options[:from_port].to_s,
"IpPermissions.1.ToPort" => options[:to_port].to_s,
"IpPermissions.1.IpRanges.1" => options[:cidr_ip],
"IpPermissions.1.Groups.1.GroupName" => options[:source_security_group_name],
"IpPermissions.1.Groups.1.UserId" => options[:source_security_group_user_id]
}

return response_generator(:action => "RevokeSecurityGroupIngress", :params => params)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/AWS/EC2/spot_prices.rb
Expand Up @@ -16,7 +16,7 @@ class Base < AWS::Base
def describe_spot_price_history( options = {} )
raise ArgumentError, ":start_time must be a Time object" unless options[:start_time].nil? || options[:start_time].kind_of?(Time)
raise ArgumentError, ":end_time must be a Time object" unless options[:end_time].nil? || options[:end_time].kind_of?(Time)
raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].include?(options[:instance_type])
raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge", "cg1.4xlarge"].include?(options[:instance_type])
raise ArgumentError, ":product_description must be 'Linux/UNIX' or 'Windows'" unless options[:product_description].nil? || ["Linux/UNIX", "Windows"].include?(options[:product_description])

params = {}
Expand Down
46 changes: 24 additions & 22 deletions test/test_EC2_security_groups.rb
Expand Up @@ -162,13 +162,14 @@


specify "permissions should be able to be added to a security group with authorize_security_group_ingress." do
@ec2.stubs(:make_request).with('AuthorizeSecurityGroupIngress', { "GroupName"=>"WebServers",
"IpProtocol"=>"tcp",
"FromPort"=>"8000",
"ToPort"=>"80",
"CidrIp"=>"0.0.0.0/24",
"SourceSecurityGroupName"=>"Source SG Name",
"SourceSecurityGroupOwnerId"=>"123"}).
@ec2.stubs(:make_request).with('AuthorizeSecurityGroupIngress',
{ "GroupName" => "WebServers",
"IpPermissions.1.IpProtocol" => "tcp",
"IpPermissions.1.FromPort" => "8000",
"IpPermissions.1.ToPort" => "80",
"IpPermissions.1.IpRanges.1" => "0.0.0.0/24",
"IpPermissions.1.Groups.1.GroupName" => "Source SG Name",
"IpPermissions.1.Groups.1.UserId" => "123"}).
returns stub(:body => @authorize_security_group_ingress_response_body, :is_a? => true)

@ec2.authorize_security_group_ingress( :group_name => "WebServers",
Expand All @@ -177,29 +178,30 @@
:to_port => "80",
:cidr_ip => "0.0.0.0/24",
:source_security_group_name => "Source SG Name",
:source_security_group_owner_id => "123"
:source_security_group_user_id => "123"
).should.be.an.instance_of Hash
end


specify "permissions should be able to be revoked from a security group with revoke_security_group_ingress." do
@ec2.stubs(:make_request).with('RevokeSecurityGroupIngress', { "GroupName"=>"WebServers",
"IpProtocol"=>"tcp",
"FromPort"=>"8000",
"ToPort"=>"80",
"CidrIp"=>"0.0.0.0/24",
"SourceSecurityGroupName"=>"Source SG Name",
"SourceSecurityGroupOwnerId"=>"123"}).
@ec2.stubs(:make_request).with('RevokeSecurityGroupIngress',
{ "GroupName" => "WebServers",
"IpPermissions.1.IpProtocol" => "tcp",
"IpPermissions.1.FromPort" => "8000",
"IpPermissions.1.ToPort" => "80",
"IpPermissions.1.IpRanges.1" => "0.0.0.0/24",
"IpPermissions.1.Groups.1.GroupName" => "Source SG Name",
"IpPermissions.1.Groups.1.UserId" => "123"}).
returns stub(:body => @revoke_security_group_ingress_response_body, :is_a? => true)

@ec2.revoke_security_group_ingress( :group_name => "WebServers",
:ip_protocol => "tcp",
:from_port => "8000",
:to_port => "80",
:cidr_ip => "0.0.0.0/24",
:source_security_group_name => "Source SG Name",
:source_security_group_owner_id => "123"
).should.be.an.instance_of Hash
:ip_protocol => "tcp",
:from_port => "8000",
:to_port => "80",
:cidr_ip => "0.0.0.0/24",
:source_security_group_name => "Source SG Name",
:source_security_group_user_id => "123"
).should.be.an.instance_of Hash
end

end

0 comments on commit 324247c

Please sign in to comment.