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 +7 -4
- data/lib/slushy/command_failed_error.rb +2 -0
- data/lib/slushy/error.rb +2 -0
- data/lib/slushy/instance.rb +17 -21
- data/lib/slushy/timeout_error.rb +2 -0
- data/lib/slushy/version.rb +1 -1
- data/lib/slushy.rb +3 -0
- data/spec/lib/instance_spec.rb +49 -7
- data/spec/spec_helper.rb +0 -1
- data/spec/support/output_streams.rb +4 -0
- metadata +8 -5
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
|
12
|
-
|
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
|
14
|
+
instance = Slushy::Instance.launch(connection, :flavor_id => 'm1.large', :more => :keys)
|
15
|
+
|
16
|
+
# Install ruby and Chef
|
15
17
|
instance.bootstrap
|
16
|
-
|
18
|
+
|
19
|
+
# Converge using your Chef cookbooks
|
17
20
|
instance.converge Rails.root.join('provision')
|
18
21
|
```
|
19
22
|
|
data/lib/slushy/error.rb
ADDED
data/lib/slushy/instance.rb
CHANGED
@@ -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 {
|
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], "
|
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
|
-
|
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, [
|
70
|
+
retry_block(5, [Slushy::CommandFailedError], Slushy::CommandFailedError.new("Command 'apt-get' failed")) do
|
77
71
|
puts "Updating apt cache..."
|
78
|
-
|
72
|
+
run_command!('sudo apt-get update')
|
79
73
|
puts "Installing ruby..."
|
80
|
-
|
74
|
+
run_command!('sudo apt-get -y install ruby')
|
81
75
|
puts "Installing rubygems..."
|
82
|
-
|
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
|
-
|
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,
|
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 *
|
107
|
+
rescue *retryable_exceptions => e
|
112
108
|
attempts +=1
|
113
|
-
puts "#{
|
109
|
+
puts "#{retries_failed_exception.message}. Attempting retry #{attempts}..."
|
114
110
|
last_error = e
|
115
111
|
end
|
116
112
|
end
|
117
|
-
|
113
|
+
raise retries_failed_exception unless succeeded
|
118
114
|
retval
|
119
115
|
end
|
120
116
|
|
data/lib/slushy/version.rb
CHANGED
data/lib/slushy.rb
CHANGED
data/spec/lib/instance_spec.rb
CHANGED
@@ -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(:
|
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(:
|
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
|
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
|
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
|
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
|
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
|
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
|
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.
|
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-
|
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:
|
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:
|
127
|
+
hash: -3387664004883499874
|
125
128
|
requirements: []
|
126
129
|
rubyforge_project:
|
127
|
-
rubygems_version: 1.8.
|
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
|