Skip to content

Commit

Permalink
Split Error into TimeoutError and CommandFailedError
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Umbach and Larry Karnowski committed Apr 30, 2012
1 parent 3c2bcd8 commit 0209206
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 18 deletions.
2 changes: 2 additions & 0 deletions lib/slushy.rb
Expand Up @@ -2,4 +2,6 @@ module Slushy; end


require 'slushy/version' require 'slushy/version'
require 'slushy/error' require 'slushy/error'
require 'slushy/command_failed_error'
require 'slushy/timeout_error'
require 'slushy/instance' require 'slushy/instance'
2 changes: 2 additions & 0 deletions lib/slushy/command_failed_error.rb
@@ -0,0 +1,2 @@
class Slushy::CommandFailedError < Slushy::Error
end
22 changes: 11 additions & 11 deletions lib/slushy/instance.rb
Expand Up @@ -5,7 +5,7 @@ class Slushy::Instance


def self.launch(connection, config) def self.launch(connection, config)
server = connection.servers.create(config) server = connection.servers.create(config)
server.wait_for { ready? } or raise Slushy::Error.new("Timeout launching server #{server.id}") server.wait_for { ready? } or raise Slushy::TimeoutError.new("Timeout launching server #{server.id}")
new(connection, server.id) new(connection, server.id)
end end


Expand Down Expand Up @@ -34,23 +34,23 @@ def snapshot(name, description)
response = connection.create_image(instance_id, name, description) response = connection.create_image(instance_id, name, description)
image_id = response.body["imageId"] image_id = response.body["imageId"]
image = connection.images.get(image_id) image = connection.images.get(image_id)
image.wait_for(3600) { ready? } or raise Slushy::Error.new("Timeout creating snapshot #{image_id}") image.wait_for(3600) { ready? } or raise Slushy::TimeoutError.new("Timeout creating snapshot #{image_id}")
image_id image_id
end end


def terminate def terminate
server.destroy server.destroy
server.wait_for { state == "terminated" } or raise Slushy::Error.new("Timeout terminating server #{server.id}") server.wait_for { state == "terminated" } or raise Slushy::TimeoutError.new("Timeout terminating server #{server.id}")
end end


def stop def stop
server.stop server.stop
server.wait_for { state == "stopped" } or raise Slushy::Error.new("Timeout stopping server #{server.id}") server.wait_for { state == "stopped" } or raise Slushy::TimeoutError.new("Timeout stopping server #{server.id}")
end end


def wait_for_connectivity def wait_for_connectivity
puts "Waiting for ssh connectivity..." puts "Waiting for ssh connectivity..."
retry_block(5, [Errno::ECONNREFUSED, Timeout::Error], "Connecting to Amazon refused") do retry_block(5, [Errno::ECONNREFUSED, Timeout::Error], Slushy::TimeoutError.new("Timeout connecting to server #{server.id}")) do
sleep 10 sleep 10
Timeout.timeout(60) { ssh('ls') } Timeout.timeout(60) { ssh('ls') }
end end
Expand All @@ -63,11 +63,11 @@ def run_command(command)
end end


def run_command!(command) def run_command!(command)
raise Slushy::Error.new("Failed running '#{command}'") unless run_command(command) raise Slushy::CommandFailedError.new("Failed running '#{command}'") unless run_command(command)
end end


def apt_installs def apt_installs
retry_block(5, [Slushy::Error], "Command 'apt-get' failed") do retry_block(5, [Slushy::CommandFailedError], Slushy::CommandFailedError.new("Command 'apt-get' failed")) do
puts "Updating apt cache..." puts "Updating apt cache..."
run_command!('sudo apt-get update') run_command!('sudo apt-get update')
puts "Installing ruby..." puts "Installing ruby..."
Expand All @@ -94,21 +94,21 @@ def converge(cookbooks_path) # TODO: find the standard Chef term for this


protected protected


def retry_block(times, errors, failure) def retry_block(times, retryable_exceptions, retries_failed_exception)
succeeded = false succeeded = false
attempts = 0 attempts = 0
last_error = nil last_error = nil
until succeeded || attempts > times-1 until succeeded || attempts > times-1
begin begin
retval = yield retval = yield
succeeded = true succeeded = true
rescue *errors => e rescue *retryable_exceptions => e
attempts +=1 attempts +=1
puts "#{failure}. Attempting retry #{attempts}..." puts "#{retries_failed_exception.message}. Attempting retry #{attempts}..."
last_error = e last_error = e
end end
end end
raise Slushy::Error.new(failure) unless succeeded raise retries_failed_exception unless succeeded
retval retval
end end


Expand Down
2 changes: 2 additions & 0 deletions lib/slushy/timeout_error.rb
@@ -0,0 +1,2 @@
class Slushy::TimeoutError < Slushy::Error
end
16 changes: 9 additions & 7 deletions spec/lib/instance_spec.rb
Expand Up @@ -24,7 +24,7 @@ def mock_job(options={})
servers = stub(:create => server) servers = stub(:create => server)
connection.stub(:servers).and_return(servers) connection.stub(:servers).and_return(servers)
server.stub(:wait_for).and_return(false) server.stub(:wait_for).and_return(false)
lambda { described_class.launch(connection, config) }.should raise_error(Slushy::Error) lambda { described_class.launch(connection, config) }.should raise_error(Slushy::TimeoutError)
end end


it "returns the instance object" do it "returns the instance object" do
Expand Down Expand Up @@ -73,7 +73,7 @@ def mock_job(options={})
connection.stub(:create_image).and_return(response) connection.stub(:create_image).and_return(response)
images.should_receive(:get).with(:some_ami_id).and_return(image) images.should_receive(:get).with(:some_ami_id).and_return(image)
image.stub(:wait_for).and_return(false) image.stub(:wait_for).and_return(false)
lambda { instance.snapshot(:some_name, :some_description) }.should raise_error(Slushy::Error) lambda { instance.snapshot(:some_name, :some_description) }.should raise_error(Slushy::TimeoutError)
end end
end end


Expand All @@ -90,7 +90,7 @@ def mock_job(options={})
instance.stub(:server).and_return(server) instance.stub(:server).and_return(server)
server.stub(:destroy) server.stub(:destroy)
server.stub(:wait_for).and_return(false) server.stub(:wait_for).and_return(false)
lambda { instance.terminate }.should raise_error(Slushy::Error) lambda { instance.terminate }.should raise_error(Slushy::TimeoutError)
end end
end end


Expand All @@ -107,11 +107,13 @@ def mock_job(options={})
instance.stub(:server).and_return(server) instance.stub(:server).and_return(server)
server.stub(:stop) server.stub(:stop)
server.stub(:wait_for).and_return(false) server.stub(:wait_for).and_return(false)
lambda { instance.stop }.should raise_error(Slushy::Error) lambda { instance.stop }.should raise_error(Slushy::TimeoutError)
end end
end end


describe '#wait_for_connectivity' do describe '#wait_for_connectivity' do
before { instance.stub(:server).and_return(server) }

it 'retries if the first attempt fails' do it 'retries if the first attempt fails' do
instance.should_receive(:ssh).ordered.and_raise(Errno::ECONNREFUSED) instance.should_receive(:ssh).ordered.and_raise(Errno::ECONNREFUSED)
instance.should_receive(:ssh).ordered.and_return([mock_job]) instance.should_receive(:ssh).ordered.and_return([mock_job])
Expand All @@ -136,7 +138,7 @@ def mock_job(options={})
instance.stub(:sleep).and_return(10) instance.stub(:sleep).and_return(10)
expect do expect do
capture_stdout { instance.wait_for_connectivity } capture_stdout { instance.wait_for_connectivity }
end.to raise_error Slushy::Error end.to raise_error Slushy::TimeoutError
end end
end end


Expand All @@ -147,7 +149,7 @@ def mock_job(options={})
capture_stdout do capture_stdout do
expect do expect do
instance.run_command!("ls") instance.run_command!("ls")
end.to raise_error Slushy::Error end.to raise_error Slushy::CommandFailedError
end.should =~ /STDERR: FAIL WHALE/ end.should =~ /STDERR: FAIL WHALE/
end end
end end
Expand All @@ -168,7 +170,7 @@ def mock_job(options={})
instance.should_receive(:ssh).exactly(5).times.with('sudo apt-get update').and_return([mock_job(:status => 1)]) instance.should_receive(:ssh).exactly(5).times.with('sudo apt-get update').and_return([mock_job(:status => 1)])
expect do expect do
capture_stdout { instance.apt_installs } capture_stdout { instance.apt_installs }
end.to raise_error Slushy::Error end.to raise_error Slushy::CommandFailedError
end end
end end


Expand Down

0 comments on commit 0209206

Please sign in to comment.