Skip to content

Commit

Permalink
expanding on bootstrap and adding to aws
Browse files Browse the repository at this point in the history
  • Loading branch information
geemus committed Sep 16, 2010
1 parent f0e2cfd commit 22af45e
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 45 deletions.
8 changes: 4 additions & 4 deletions Gemfile.lock
Expand Up @@ -7,8 +7,8 @@ PATH
formatador (>= 0.0.15)
json
mime-types
net-ssh
nokogiri (>= 1.4.3.1)
net-ssh (~> 2.0.23)
nokogiri (~> 1.4.3.1)
ruby-hmac

GEM
Expand Down Expand Up @@ -40,8 +40,8 @@ DEPENDENCIES
formatador (>= 0.0.15)
json
mime-types
net-ssh
nokogiri (>= 1.4.3.1)
net-ssh (~> 2.0.23)
nokogiri (~> 1.4.3.1)
rake
rspec
ruby-hmac
Expand Down
4 changes: 2 additions & 2 deletions fog.gemspec
Expand Up @@ -47,8 +47,8 @@ Gem::Specification.new do |s|
s.add_dependency('formatador', '>=0.0.15')
s.add_dependency('json')
s.add_dependency('mime-types')
s.add_dependency('net-ssh')
s.add_dependency('nokogiri', '>=1.4.3.1')
s.add_dependency('net-ssh', '~>2.0.23')
s.add_dependency('nokogiri', '~>1.4.3.1')
s.add_dependency('ruby-hmac')

## List your development dependencies here. Development dependencies are
Expand Down
1 change: 1 addition & 0 deletions lib/fog.rb
Expand Up @@ -8,6 +8,7 @@
require 'mime/types'
require 'net/ssh'
require 'nokogiri'
require 'tempfile'
require 'time'

__DIR__ = File.dirname(__FILE__)
Expand Down
24 changes: 23 additions & 1 deletion lib/fog/aws/models/compute/security_group.rb
Expand Up @@ -30,7 +30,7 @@ def authorize_port_range(range, options = {})
'FromPort' => range.min,
'GroupName' => @name,
'ToPort' => range.max,
'IpProtocol' => options[:ip_protocol] || 'tcp'
'IpProtocol' => options[:ip_protocol] || 'tcp'
)
end

Expand All @@ -41,6 +41,28 @@ def destroy
true
end

def revoke_group_and_owner(group, owner)
requires :name

connection.revoke_security_group_ingress(
'GroupName' => @name,
'SourceSecurityGroupName' => group,
'SourceSecurityGroupOwnerId' => owner
)
end

def revoke_port_range(range, options = {})
requires :name

connection.revoke_security_group_ingress(
'CidrIp' => options[:cidr_ip] || '0.0.0.0/0',
'FromPort' => range.min,
'GroupName' => @name,
'ToPort' => range.max,
'IpProtocol' => options[:ip_protocol] || 'tcp'
)
end

def save
requires :description, :name

Expand Down
62 changes: 44 additions & 18 deletions lib/fog/aws/models/compute/server.rb
Expand Up @@ -32,6 +32,8 @@ class Server < Fog::Model
attribute :subnet_id, :aliases => 'subnetId'
attribute :user_data

attr_accessor :password, :private_key_path, :public_key_path, :username

def initialize(attributes={})
@groups ||= ["default"] unless attributes[:subnet_id]
@flavor_id ||= 'm1.small'
Expand All @@ -57,14 +59,6 @@ def destroy
true
end

# def security_group
# connection.security_groups.all(@group_id)
# end
#
# def security_group=(new_security_group)
# @group_id = new_security_group.name
# end

def flavor_id
@flavor && @flavor.id || @flavor_id
end
Expand Down Expand Up @@ -103,6 +97,14 @@ def placement=(new_placement)
end
end

def private_key_path
@private_key_path ||= Fog.credentials[:private_key_path]
end

def public_key_path
@public_key_path ||= Fog.credentials[:public_key_path]
end

def ready?
@state == 'running'
end
Expand All @@ -117,18 +119,18 @@ def save
requires :image_id

options = {
'BlockDeviceMapping' => @block_device_mapping,
'BlockDeviceMapping' => block_device_mapping,
'InstanceType' => flavor_id,
'KernelId' => @kernel_id,
'KeyName' => @key_name,
'Monitoring.Enabled' => @monitoring,
'Placement.AvailabilityZone' => @availability_zone,
'RamdiskId' => @ramdisk_id,
'SecurityGroup' => @groups,
'KernelId' => kernel_id,
'KeyName' => key_name,
'Monitoring.Enabled' => monitoring,
'Placement.AvailabilityZone' => availability_zone,
'RamdiskId' => ramdisk_id,
'SecurityGroup' => groups,
'SubnetId' => subnet_id,
'UserData' => @user_data
'UserData' => user_data
}

# If subnet is defined we are working on a virtual private cloud.
# subnet & security group cannot co-exist. I wish VPC just ignored
# the security group parameter instead, it would be much easier!
Expand All @@ -138,11 +140,31 @@ def save
options.delete('SubnetId')
end

data = connection.run_instances(@image_id, 1, 1, options)
data = connection.run_instances(image_id, 1, 1, options)
merge_attributes(data.body['instancesSet'].first)
true
end

def setup(credentials = {})
requires :ip_address, :identity, :public_key_path, :username
sleep(10) # takes a bit before EC2 instances will play nice
Fog::SSH.new(ip_address, username, credentials).run([
%{mkdir .ssh},
%{echo "#{File.read(File.expand_path(public_key_path))}" >> ~/.ssh/authorized_keys},
%{passwd -l root},
%{echo "#{attributes.to_json}" >> ~/attributes.json}
])
rescue Errno::ECONNREFUSED => e
sleep(1)
retry
end

def ssh(commands)
requires :identity, :ip_address, :private_key_path, :username
@ssh ||= Fog::SSH.new(ip_address, username, :keys => [private_key_path])
@ssh.run(commands)
end

def start
requires :id
connection.start_instances(@id)
Expand All @@ -155,6 +177,10 @@ def stop
true
end

def username
@username ||= 'root'
end

def volumes
requires :id

Expand Down
27 changes: 27 additions & 0 deletions lib/fog/aws/models/compute/servers.rb
Expand Up @@ -28,6 +28,33 @@ def all(server_id = @server_id)
)
end

def bootstrap(new_attributes = {})
begin
tmp_key_pair = connection.key_pairs.create(:name => "tmp_#{Time.now.to_f.to_s.gsub('.','')}")
server = create(new_attributes.merge(:key_pair => tmp_key_pair))

# make sure port 22 is open in the first security group
security_group = connection.security_groups.get(server.groups.first)
ip_permission = security_group.ip_permissions.detect do |ip_permission|
ip_permission['ipRanges'].first && ip_permission['ipRanges'].first['cidrIp'] == '0.0.0.0/0' &&
ip_permission['fromPort'] == 22 &&
ip_permission['ipProtocol'] == 'tcp' &&
ip_permission['toPort'] == 22
end
unless ip_permission
security_group.authorize_port_range(22..22)
end

server.wait_for { ready? }
server.setup(:key_data => [tmp_key_pair.material])
ensure
if tmp_key_pair
tmp_key_pair.destroy
end
end
server
end

def get(server_id)
if server_id
all(server_id).first
Expand Down
28 changes: 16 additions & 12 deletions lib/fog/rackspace/models/compute/server.rb
Expand Up @@ -18,7 +18,7 @@ class Server < Fog::Model
attribute :progress
attribute :status

attr_accessor :password, :private_key_path, :public_key_path
attr_accessor :password, :private_key_path, :public_key_path, :username

def initialize(attributes={})
@flavor_id ||= 1
Expand Down Expand Up @@ -57,11 +57,11 @@ def reboot(type = 'SOFT')
end

def private_key_path
@private_key_path || Fog.credentials[:private_key_path]
@private_key_path ||= Fog.credentials[:private_key_path]
end

def public_key_path
@public_key_path || Fog.credentials[:public_key_path]
@public_key_path ||= Fog.credentials[:public_key_path]
end

def save
Expand All @@ -77,15 +77,9 @@ def save
true
end

def ssh(commands)
requires :addresses, :identity, :private_key_path
@ssh ||= Fog::SSH.new(@addresses['public'].first, 'root', :keys => [private_key_path])
@ssh.run(commands)
end

def setup
requires :addresses, :identity, :password, :public_key_path
Fog::SSH.new(@addresses['public'].first, 'root', :password => password).run([
def setup(credentials = {})
requires :addresses, :identity, :public_key_path, :username
Fog::SSH.new(addresses['public'].first, username, credentials).run([
%{mkdir .ssh},
%{echo "#{File.read(File.expand_path(public_key_path))}" >> ~/.ssh/authorized_keys},
%{passwd -l root},
Expand All @@ -97,6 +91,16 @@ def setup
retry
end

def ssh(commands)
requires :addresses, :identity, :private_key_path, :username
@ssh ||= Fog::SSH.new(addresses['public'].first, username, :keys => [private_key_path])
@ssh.run(commands)
end

def username
@username ||= root
end

private

def adminPass=(new_admin_pass)
Expand Down
2 changes: 1 addition & 1 deletion lib/fog/rackspace/models/compute/servers.rb
Expand Up @@ -17,7 +17,7 @@ def all
def bootstrap(new_attributes = {})
server = create(new_attributes)
server.wait_for { ready? }
server.setup
server.setup(:password => server.password)
server
end

Expand Down
23 changes: 16 additions & 7 deletions lib/fog/ssh.rb
Expand Up @@ -2,8 +2,8 @@ module Fog
module SSH

def self.new(address, username, options = {})
unless options[:keys] || options[:password]
raise ArgumentError.new(':keys or :password are required to initialize SSH')
unless options[:key_data] || options[:keys] || options[:password]
raise ArgumentError.new(':key_data, :keys or :password are required to initialize SSH')
end
if Fog.mocking?
Fog::SSH::Mock.new(address, username, options)
Expand Down Expand Up @@ -41,7 +41,8 @@ class Real
def initialize(address, username, options)
@address = address
@username = username
@options = options.merge!(:paranoid => false)
@options = options.merge(:paranoid => false)
@options.merge(:verbose => true)
end

def run(commands)
Expand All @@ -50,11 +51,11 @@ def run(commands)
begin
Net::SSH.start(@address, @username, @options) do |ssh|
commands.each do |command|
sudoable_command = command.sub(/^sudo/, %{sudo -p 'fog sudo password:'})
escaped_command = sudoable_command.sub(/'/, %{'"'"'})
result = Result.new(escaped_command)
ssh.open_channel do |channel|
sudoable_command = command.sub(/^sudo/, %{sudo -p 'fog sudo password:'})
escaped_command = sudoable_command.sub(/'/, %{'"'"'})
channel.request_pty
result = Result.new(escaped_command)
channel.exec(%{bash -lc '#{escaped_command}'}) do |channel, success|
unless success
raise "Could not execute command: #{command.inspect}"
Expand All @@ -77,9 +78,9 @@ def run(commands)
result.status = 255
end
end
results << result
end
ssh.loop
results << result
end
end
rescue Net::SSH::HostKeyMismatch => exception
Expand All @@ -96,6 +97,14 @@ class Result

attr_accessor :command, :stderr, :stdout, :status

def display_stdout
Formatador.display_line(stdout.split("\r\n"))
end

def display_stderr
Formatador.display_line(stderr.split("\r\n"))
end

def initialize(command)
@command = command
@stderr = ''
Expand Down

0 comments on commit 22af45e

Please sign in to comment.