slushy 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -8,12 +8,15 @@ Assumes Fog's API for connecting to and creating instances.
8
8
  Provision and converge an instance:
9
9
 
10
10
  ```ruby
11
- connection = Fog::Compute.new :provider => 'AWS', :aws_access_key => 'KEY',
12
- :aws_secret_access_key => 'SECRET'
11
+ connection = Fog::Compute.new(:provider => 'AWS', :aws_access_key_id => 'KEY', :aws_secret_access_key => 'SECRET')
12
+
13
13
  # Second arg is a hash passed to Fog::Compute::AWS::Servers.create
14
- instance = Slushy::Instance.launch connection, :flavor_id => 'm1.large', :more => :keys
14
+ instance = Slushy::Instance.launch(connection, :flavor_id => 'm1.large', :more => :keys)
15
+
16
+ # Install ruby and Chef
15
17
  instance.bootstrap
16
- # Point at directory containing Chef cookbooks
18
+
19
+ # Converge using your Chef cookbooks
17
20
  instance.converge Rails.root.join('provision')
18
21
  ```
19
22
 
@@ -0,0 +1,2 @@
1
+ class Slushy::CommandFailedError < Slushy::Error
2
+ end
@@ -0,0 +1,2 @@
1
+ class Slushy::Error < StandardError
2
+ end
@@ -1,13 +1,11 @@
1
1
  require 'timeout'
2
2
 
3
3
  class Slushy::Instance
4
- class AptInstallError < StandardError; end
5
-
6
4
  attr_reader :connection, :instance_id
7
5
 
8
6
  def self.launch(connection, config)
9
7
  server = connection.servers.create(config)
10
- server.wait_for { ready? }
8
+ server.wait_for { ready? } or raise Slushy::TimeoutError.new("Timeout launching server #{server.id}")
11
9
  new(connection, server.id)
12
10
  end
13
11
 
@@ -36,23 +34,23 @@ class Slushy::Instance
36
34
  response = connection.create_image(instance_id, name, description)
37
35
  image_id = response.body["imageId"]
38
36
  image = connection.images.get(image_id)
39
- image.wait_for { state == "available" }
37
+ image.wait_for(3600) { ready? } or raise Slushy::TimeoutError.new("Timeout creating snapshot #{image_id}")
40
38
  image_id
41
39
  end
42
40
 
43
41
  def terminate
44
42
  server.destroy
45
- server.wait_for { state == "terminated" }
43
+ server.wait_for { state == "terminated" } or raise Slushy::TimeoutError.new("Timeout terminating server #{server.id}")
46
44
  end
47
45
 
48
46
  def stop
49
47
  server.stop
50
- server.wait_for { state == "stopped" }
48
+ server.wait_for { state == "stopped" } or raise Slushy::TimeoutError.new("Timeout stopping server #{server.id}")
51
49
  end
52
50
 
53
51
  def wait_for_connectivity
54
52
  puts "Waiting for ssh connectivity..."
55
- retry_block(5, [Errno::ECONNREFUSED, Timeout::Error], "Connecting to Amazon refused") do
53
+ retry_block(5, [Errno::ECONNREFUSED, Timeout::Error], Slushy::TimeoutError.new("Timeout connecting to server #{server.id}")) do
56
54
  sleep 10
57
55
  Timeout.timeout(60) { ssh('ls') }
58
56
  end
@@ -65,21 +63,17 @@ class Slushy::Instance
65
63
  end
66
64
 
67
65
  def run_command!(command)
68
- exit 1 unless run_command(command)
69
- end
70
-
71
- def run_apt_command!(command)
72
- raise AptInstallError unless run_command(command)
66
+ raise Slushy::CommandFailedError.new("Failed running '#{command}'") unless run_command(command)
73
67
  end
74
68
 
75
69
  def apt_installs
76
- retry_block(5, [AptInstallError], "Command 'apt-get' failed") do
70
+ retry_block(5, [Slushy::CommandFailedError], Slushy::CommandFailedError.new("Command 'apt-get' failed")) do
77
71
  puts "Updating apt cache..."
78
- run_apt_command!('sudo apt-get update')
72
+ run_command!('sudo apt-get update')
79
73
  puts "Installing ruby..."
80
- run_apt_command!('sudo apt-get -y install ruby')
74
+ run_command!('sudo apt-get -y install ruby')
81
75
  puts "Installing rubygems..."
82
- run_apt_command!('sudo apt-get -y install rubygems1.8')
76
+ run_command!('sudo apt-get -y install rubygems1.8')
83
77
  end
84
78
  end
85
79
 
@@ -95,12 +89,14 @@ class Slushy::Instance
95
89
  cookbooks_path = "#{cookbooks_path}/" unless cookbooks_path.to_s.end_with?('/')
96
90
  scp(cookbooks_path, '/tmp/chef-solo', :recursive => true)
97
91
  puts "Converging server, this may take a while (10-20 minutes)"
98
- run_command!('cd /tmp/chef-solo && sudo /var/lib/gems/1.8/bin/chef-solo -c solo.rb -j dna.json')
92
+ path_part = 'PATH=/var/lib/gems/1.8/bin:/usr/local/bin:$PATH'
93
+ cmd = "cd /tmp/chef-solo && #{path_part} sudo chef-solo -c solo.rb -j dna.json"
94
+ run_command!(cmd)
99
95
  end
100
96
 
101
97
  protected
102
98
 
103
- def retry_block(times, errors, failure)
99
+ def retry_block(times, retryable_exceptions, retries_failed_exception)
104
100
  succeeded = false
105
101
  attempts = 0
106
102
  last_error = nil
@@ -108,13 +104,13 @@ class Slushy::Instance
108
104
  begin
109
105
  retval = yield
110
106
  succeeded = true
111
- rescue *errors => e
107
+ rescue *retryable_exceptions => e
112
108
  attempts +=1
113
- puts "#{failure}. Attempting retry #{attempts}..."
109
+ puts "#{retries_failed_exception.message}. Attempting retry #{attempts}..."
114
110
  last_error = e
115
111
  end
116
112
  end
117
- exit 1 if !succeeded
113
+ raise retries_failed_exception unless succeeded
118
114
  retval
119
115
  end
120
116
 
@@ -0,0 +1,2 @@
1
+ class Slushy::TimeoutError < Slushy::Error
2
+ end
@@ -1,3 +1,3 @@
1
1
  module Slushy
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/slushy.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  module Slushy; end
2
2
 
3
3
  require 'slushy/version'
4
+ require 'slushy/error'
5
+ require 'slushy/command_failed_error'
6
+ require 'slushy/timeout_error'
4
7
  require 'slushy/instance'
@@ -20,6 +20,13 @@ describe Slushy::Instance do
20
20
  lambda { described_class.launch(connection, config) }.should change { connection.servers.size }.by(1)
21
21
  end
22
22
 
23
+ it "raises if wait_for fails" do
24
+ servers = stub(:create => server)
25
+ connection.stub(:servers).and_return(servers)
26
+ server.stub(:wait_for).and_return(false)
27
+ lambda { described_class.launch(connection, config) }.should raise_error(Slushy::TimeoutError)
28
+ end
29
+
23
30
  it "returns the instance object" do
24
31
  described_class.launch(connection, config).should be_a Slushy::Instance
25
32
  end
@@ -57,21 +64,56 @@ describe Slushy::Instance do
57
64
  it "does NOT return until image creation is complete" do
58
65
  connection.stub(:create_image).and_return(response)
59
66
  images.should_receive(:get).with(:some_ami_id).and_return(image)
60
- image.should_receive(:wait_for)
67
+ image.should_receive(:ready?).ordered.and_return(false)
68
+ image.should_receive(:ready?).ordered.and_return(true)
61
69
  instance.snapshot(:some_name, :some_description)
62
70
  end
71
+
72
+ it "raises if wait_for fails" do
73
+ connection.stub(:create_image).and_return(response)
74
+ images.should_receive(:get).with(:some_ami_id).and_return(image)
75
+ image.stub(:wait_for).and_return(false)
76
+ lambda { instance.snapshot(:some_name, :some_description) }.should raise_error(Slushy::TimeoutError)
77
+ end
63
78
  end
64
79
 
65
80
  describe "#terminate" do
66
81
  it "terminates the given instance" do
67
82
  instance.stub(:server).and_return(server)
68
83
  server.should_receive(:destroy)
69
- server.should_receive(:wait_for)
84
+ server.should_receive(:state).ordered.and_return("running")
85
+ server.should_receive(:state).ordered.and_return("terminated")
70
86
  instance.terminate
71
87
  end
88
+
89
+ it "raises if wait_for fails" do
90
+ instance.stub(:server).and_return(server)
91
+ server.stub(:destroy)
92
+ server.stub(:wait_for).and_return(false)
93
+ lambda { instance.terminate }.should raise_error(Slushy::TimeoutError)
94
+ end
95
+ end
96
+
97
+ describe "#stop" do
98
+ it "stops the given instance" do
99
+ instance.stub(:server).and_return(server)
100
+ server.should_receive(:stop)
101
+ server.should_receive(:state).ordered.and_return("running")
102
+ server.should_receive(:state).ordered.and_return("stopped")
103
+ instance.stop
104
+ end
105
+
106
+ it "raises if wait_for fails" do
107
+ instance.stub(:server).and_return(server)
108
+ server.stub(:stop)
109
+ server.stub(:wait_for).and_return(false)
110
+ lambda { instance.stop }.should raise_error(Slushy::TimeoutError)
111
+ end
72
112
  end
73
113
 
74
114
  describe '#wait_for_connectivity' do
115
+ before { instance.stub(:server).and_return(server) }
116
+
75
117
  it 'retries if the first attempt fails' do
76
118
  instance.should_receive(:ssh).ordered.and_raise(Errno::ECONNREFUSED)
77
119
  instance.should_receive(:ssh).ordered.and_return([mock_job])
@@ -91,12 +133,12 @@ describe Slushy::Instance do
91
133
  stdout.should include 'Attempting retry 3...'
92
134
  end
93
135
 
94
- it 'retries up to five times, then aborts' do
136
+ it 'retries up to five times, then fails' do
95
137
  instance.should_receive(:ssh).exactly(5).times.and_raise(Errno::ECONNREFUSED)
96
138
  instance.stub(:sleep).and_return(10)
97
139
  expect do
98
140
  capture_stdout { instance.wait_for_connectivity }
99
- end.to raise_error SystemExit
141
+ end.to raise_error Slushy::TimeoutError
100
142
  end
101
143
  end
102
144
 
@@ -107,7 +149,7 @@ describe Slushy::Instance do
107
149
  capture_stdout do
108
150
  expect do
109
151
  instance.run_command!("ls")
110
- end.to raise_error SystemExit
152
+ end.to raise_error Slushy::CommandFailedError
111
153
  end.should =~ /STDERR: FAIL WHALE/
112
154
  end
113
155
  end
@@ -124,11 +166,11 @@ describe Slushy::Instance do
124
166
  end.to_not raise_error
125
167
  end
126
168
 
127
- it 'retries up to five times, then aborts' do
169
+ it 'retries up to five times, then fails' do
128
170
  instance.should_receive(:ssh).exactly(5).times.with('sudo apt-get update').and_return([mock_job(:status => 1)])
129
171
  expect do
130
172
  capture_stdout { instance.apt_installs }
131
- end.to raise_error SystemExit
173
+ end.to raise_error Slushy::CommandFailedError
132
174
  end
133
175
  end
134
176
 
data/spec/spec_helper.rb CHANGED
@@ -6,7 +6,6 @@ require 'slushy'
6
6
  Dir[File.expand_path("support/*.rb", File.dirname(__FILE__))].each {|f| require f}
7
7
 
8
8
  RSpec.configure do |config|
9
- config.include OutputStreams
10
9
  config.filter_run :focused => true
11
10
  config.filter_run_excluding :disabled => true
12
11
  config.run_all_when_everything_filtered = true
@@ -10,3 +10,7 @@ module OutputStreams
10
10
  fake.string
11
11
  end
12
12
  end
13
+
14
+ RSpec.configure do |config|
15
+ config.include OutputStreams
16
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slushy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-04-28 00:00:00.000000000 Z
14
+ date: 2012-07-09 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: fog
@@ -92,7 +92,10 @@ files:
92
92
  - README.md
93
93
  - Rakefile
94
94
  - lib/slushy.rb
95
+ - lib/slushy/command_failed_error.rb
96
+ - lib/slushy/error.rb
95
97
  - lib/slushy/instance.rb
98
+ - lib/slushy/timeout_error.rb
96
99
  - lib/slushy/version.rb
97
100
  - slushy.gemspec
98
101
  - spec/lib/instance_spec.rb
@@ -112,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
112
115
  version: '0'
113
116
  segments:
114
117
  - 0
115
- hash: 663044203149620506
118
+ hash: -3387664004883499874
116
119
  required_rubygems_version: !ruby/object:Gem::Requirement
117
120
  none: false
118
121
  requirements:
@@ -121,10 +124,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
124
  version: '0'
122
125
  segments:
123
126
  - 0
124
- hash: 663044203149620506
127
+ hash: -3387664004883499874
125
128
  requirements: []
126
129
  rubyforge_project:
127
- rubygems_version: 1.8.21
130
+ rubygems_version: 1.8.24
128
131
  signing_key:
129
132
  specification_version: 3
130
133
  summary: An Aussie kitchen hand helping out Chef