slushy 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|