auser-poolparty 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/Manifest +115 -0
- data/README.txt +140 -0
- data/Rakefile +27 -0
- data/bin/instance +61 -0
- data/bin/pool +62 -0
- data/config/cloud_master_takeover +17 -0
- data/config/create_proxy_ami.sh +582 -0
- data/config/haproxy.conf +29 -0
- data/config/heartbeat.conf +8 -0
- data/config/heartbeat_authkeys.conf +2 -0
- data/config/installers/ubuntu_install.sh +77 -0
- data/config/monit/haproxy.monit.conf +7 -0
- data/config/monit/nginx.monit.conf +0 -0
- data/config/monit.conf +9 -0
- data/config/nginx.conf +24 -0
- data/config/reconfigure_instances_script.sh +18 -0
- data/config/sample-config.yml +23 -0
- data/config/scp_instances_script.sh +12 -0
- data/lib/core/array.rb +13 -0
- data/lib/core/exception.rb +9 -0
- data/lib/core/float.rb +13 -0
- data/lib/core/hash.rb +11 -0
- data/lib/core/kernel.rb +12 -0
- data/lib/core/module.rb +22 -0
- data/lib/core/object.rb +18 -0
- data/lib/core/proc.rb +15 -0
- data/lib/core/string.rb +49 -0
- data/lib/core/time.rb +41 -0
- data/lib/modules/callback.rb +133 -0
- data/lib/modules/ec2_wrapper.rb +82 -0
- data/lib/modules/safe_instance.rb +31 -0
- data/lib/modules/vlad_override.rb +82 -0
- data/lib/poolparty/application.rb +170 -0
- data/lib/poolparty/init.rb +6 -0
- data/lib/poolparty/master.rb +329 -0
- data/lib/poolparty/monitors/cpu.rb +19 -0
- data/lib/poolparty/monitors/memory.rb +26 -0
- data/lib/poolparty/monitors/web.rb +23 -0
- data/lib/poolparty/monitors.rb +13 -0
- data/lib/poolparty/optioner.rb +16 -0
- data/lib/poolparty/plugin.rb +43 -0
- data/lib/poolparty/plugin_manager.rb +67 -0
- data/lib/poolparty/provider/packages/essential.rb +6 -0
- data/lib/poolparty/provider/packages/git.rb +4 -0
- data/lib/poolparty/provider/packages/haproxy.rb +20 -0
- data/lib/poolparty/provider/packages/heartbeat.rb +4 -0
- data/lib/poolparty/provider/packages/monit.rb +6 -0
- data/lib/poolparty/provider/packages/rsync.rb +4 -0
- data/lib/poolparty/provider/packages/ruby.rb +37 -0
- data/lib/poolparty/provider/packages/s3fuse.rb +11 -0
- data/lib/poolparty/provider/provider.rb +60 -0
- data/lib/poolparty/provider.rb +2 -0
- data/lib/poolparty/remote_instance.rb +216 -0
- data/lib/poolparty/remoter.rb +106 -0
- data/lib/poolparty/remoting.rb +112 -0
- data/lib/poolparty/scheduler.rb +103 -0
- data/lib/poolparty/tasks/cloud.rake +57 -0
- data/lib/poolparty/tasks/development.rake +38 -0
- data/lib/poolparty/tasks/ec2.rake +20 -0
- data/lib/poolparty/tasks/instance.rake +63 -0
- data/lib/poolparty/tasks/plugins.rake +30 -0
- data/lib/poolparty/tasks/server.rake +42 -0
- data/lib/poolparty/tasks.rb +29 -0
- data/lib/poolparty/tmp.rb +46 -0
- data/lib/poolparty.rb +105 -0
- data/lib/s3/s3_object_store_folders.rb +44 -0
- data/misc/basics_tutorial.txt +142 -0
- data/poolparty.gemspec +72 -0
- data/spec/application_spec.rb +39 -0
- data/spec/callback_spec.rb +194 -0
- data/spec/core_spec.rb +15 -0
- data/spec/helpers/ec2_mock.rb +44 -0
- data/spec/kernel_spec.rb +11 -0
- data/spec/master_spec.rb +203 -0
- data/spec/monitors/cpu_monitor_spec.rb +38 -0
- data/spec/monitors/memory_spec.rb +50 -0
- data/spec/monitors/misc_monitor_spec.rb +50 -0
- data/spec/monitors/web_spec.rb +39 -0
- data/spec/optioner_spec.rb +22 -0
- data/spec/plugin_manager_spec.rb +31 -0
- data/spec/plugin_spec.rb +101 -0
- data/spec/pool_binary_spec.rb +10 -0
- data/spec/poolparty_spec.rb +15 -0
- data/spec/provider_spec.rb +17 -0
- data/spec/remote_instance_spec.rb +149 -0
- data/spec/remoter_spec.rb +65 -0
- data/spec/remoting_spec.rb +84 -0
- data/spec/scheduler_spec.rb +75 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/string_spec.rb +28 -0
- data/web/static/conf/nginx.conf +22 -0
- data/web/static/site/images/balloon.png +0 -0
- data/web/static/site/images/cb.png +0 -0
- data/web/static/site/images/clouds.png +0 -0
- data/web/static/site/images/railsconf_preso_img.png +0 -0
- data/web/static/site/index.html +71 -0
- data/web/static/site/javascripts/application.js +3 -0
- data/web/static/site/javascripts/corner.js +178 -0
- data/web/static/site/javascripts/jquery-1.2.6.pack.js +11 -0
- data/web/static/site/misc.html +42 -0
- data/web/static/site/storage/pool_party_presentation.pdf +0 -0
- data/web/static/site/stylesheets/application.css +100 -0
- data/web/static/site/stylesheets/reset.css +17 -0
- data/web/static/src/layouts/application.haml +25 -0
- data/web/static/src/pages/index.haml +25 -0
- data/web/static/src/pages/misc.haml +5 -0
- data/web/static/src/stylesheets/application.sass +100 -0
- metadata +260 -0
data/spec/master_spec.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Master" do
|
4
|
+
before(:each) do
|
5
|
+
Kernel.stub!(:system).and_return true
|
6
|
+
Kernel.stub!(:exec).and_return true
|
7
|
+
Kernel.stub!(:sleep).and_return true # WHy wait?
|
8
|
+
|
9
|
+
Application.options.stub!(:contract_when).and_return("web > 30.0\n cpu < 0.10")
|
10
|
+
Application.options.stub!(:expand_when).and_return("web < 3.0\n cpu > 0.80")
|
11
|
+
@master = Master.new
|
12
|
+
end
|
13
|
+
it "should launch the first instances and set the first as the master and the rest as slaves" do
|
14
|
+
Application.stub!(:minimum_instances).and_return(1)
|
15
|
+
Application.stub!(:verbose).and_return(false) # Hide messages
|
16
|
+
Master.stub!(:new).and_return(@master)
|
17
|
+
|
18
|
+
@master.stub!(:number_of_running_instances).and_return(0);
|
19
|
+
@master.stub!(:number_of_pending_instances).and_return(0);
|
20
|
+
@master.stub!(:wait).and_return true
|
21
|
+
|
22
|
+
@master.should_receive(:launch_new_instance!).and_return(
|
23
|
+
{:instance_id => "i-5849ba", :ip => "ip-127-0-0-1.aws.amazon.com", :status => "running"})
|
24
|
+
@master.stub!(:list_of_nonterminated_instances).and_return(
|
25
|
+
[{:instance_id => "i-5849ba", :ip => "ip-127-0-0-1.aws.amazon.com", :status => "running"}])
|
26
|
+
|
27
|
+
node = RemoteInstance.new({:instance_id => "i-5849ba", :ip => "ip-127-0-0-1.aws.amazon.com", :status => "running"})
|
28
|
+
node.stub!(:scp).and_return "true"
|
29
|
+
node.stub!(:ssh).and_return "true"
|
30
|
+
|
31
|
+
@master.stub!(:number_of_pending_instances).and_return(0)
|
32
|
+
@master.stub!(:get_node).with(0).and_return node
|
33
|
+
@master.start_cloud!
|
34
|
+
|
35
|
+
@master.nodes.first.instance_id.should == "i-5849ba"
|
36
|
+
end
|
37
|
+
describe "with stubbed instances" do
|
38
|
+
before(:each) do
|
39
|
+
@master.stub!(:list_of_nonterminated_instances).and_return([
|
40
|
+
{:instance_id => "i-5849ba", :ip => "ip-127-0-0-1.aws.amazon.com", :status => "running"},
|
41
|
+
{:instance_id => "i-5849bb", :ip => "ip-127-0-0-2.aws.amazon.com", :status => "running"},
|
42
|
+
{:instance_id => "i-5849bc", :ip => "ip-127-0-0-3.aws.amazon.com", :status => "pending"}
|
43
|
+
])
|
44
|
+
Kernel.stub!(:exec).and_return true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be able to go through the instances and assign them numbers" do
|
48
|
+
i = 0
|
49
|
+
@master.nodes.each do |node|
|
50
|
+
node.number.should == i
|
51
|
+
i += 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
it "should be able to say that the master is the master" do
|
55
|
+
@master.nodes.first.master?.should == true
|
56
|
+
end
|
57
|
+
it "should be able to say that the slave is not a master" do
|
58
|
+
@master.nodes[1].master?.should == false
|
59
|
+
end
|
60
|
+
it "should be able to get a specific node in the nodes from the master" do
|
61
|
+
@master.get_node(2).instance_id.should == "i-5849bc"
|
62
|
+
end
|
63
|
+
it "should be able to build a hosts file" do
|
64
|
+
open(@master.build_hosts_file.path).read.should == "ip-127-0-0-1.aws.amazon.com node0\nip-127-0-0-2.aws.amazon.com node1\nip-127-0-0-3.aws.amazon.com node2"
|
65
|
+
end
|
66
|
+
it "should be able to build a hosts file for a specific instance" do
|
67
|
+
@master.build_hosts_file_for(@master.nodes.first).should =~ "127.0.0.1 node0"
|
68
|
+
end
|
69
|
+
it "should be able to build a haproxy file" do
|
70
|
+
@master.build_haproxy_file.should =~ "server node0 ip-127-0-0-1.aws.amazon.com:#{Application.client_port}"
|
71
|
+
end
|
72
|
+
it "should be able to reconfigure the instances (working on two files a piece)" do
|
73
|
+
@master.nodes[0].should_receive(:configure).and_return true if @master.nodes[0].status =~ /running/
|
74
|
+
@master.stub!(:number_of_unconfigured_nodes).and_return 1
|
75
|
+
@master.reconfigure_running_instances
|
76
|
+
end
|
77
|
+
it "should be able to restart the running instances' services" do
|
78
|
+
@master.nodes.each {|a| a.should_receive(:restart_with_monit).and_return true }
|
79
|
+
@master.restart_running_instances_services
|
80
|
+
end
|
81
|
+
it "should be able to build a heartbeat auth file" do
|
82
|
+
open(@master.build_heartbeat_authkeys_file).read.should =~ /1 md5/
|
83
|
+
end
|
84
|
+
describe "configuring" do
|
85
|
+
before(:each) do
|
86
|
+
Master.stub!(:new).and_return(@master)
|
87
|
+
end
|
88
|
+
it "should be able to build a heartbeat resources file for the specific node" do
|
89
|
+
Master.build_heartbeat_resources_file_for(@master.nodes.first).should =~ /node0 ip-127/
|
90
|
+
end
|
91
|
+
it "should be able to build a heartbeat config file" do
|
92
|
+
Master.build_heartbeat_config_file_for(@master.nodes.first).should =~ /\nnode node0\nnode node1/
|
93
|
+
end
|
94
|
+
it "should be able to say if heartbeat is necessary with more than 1 server or not" do
|
95
|
+
Master.requires_heartbeat?.should == true
|
96
|
+
end
|
97
|
+
it "should be able to say that heartbeat is not necessary if there is 1 server" do
|
98
|
+
@master.stub!(:list_of_nonterminated_instances).and_return([
|
99
|
+
{:instance_id => "i-5849ba", :ip => "ip-127-0-0-1.aws.amazon.com", :status => "running"}
|
100
|
+
])
|
101
|
+
Master.requires_heartbeat?.should == false
|
102
|
+
end
|
103
|
+
it "should only install the stack on nodes that don't have it marked locally as installed" do
|
104
|
+
@master.nodes.each {|i| i.should_receive(:stack_installed?).and_return(true)}
|
105
|
+
@master.should_not_receive(:reconfigure_running_instances)
|
106
|
+
@master.reconfigure_cloud_when_necessary
|
107
|
+
end
|
108
|
+
it "should install the stack on all the nodes (because it needs reconfiguring) if there is any node that needs the stack" do
|
109
|
+
@master.nodes.first.should_receive(:stack_installed?).and_return(false)
|
110
|
+
@master.should_receive(:reconfigure_running_instances).once.and_return(true)
|
111
|
+
@master.reconfigure_cloud_when_necessary
|
112
|
+
end
|
113
|
+
describe "with new configuration and installation (build scripts)" do
|
114
|
+
before(:each) do
|
115
|
+
@node = @master.nodes.first
|
116
|
+
end
|
117
|
+
it "should be able to build_scp_instances_script_for" do
|
118
|
+
@node.should_receive(:scp_string).exactly(10).times.and_return("true")
|
119
|
+
Master.build_scp_instances_script_for(@node)
|
120
|
+
end
|
121
|
+
it "should be able to build_scp_instances_script_for and contain scp 10 times" do
|
122
|
+
open(Master.build_scp_instances_script_for(@node)).read.scan(/scp/).size.should == 10
|
123
|
+
end
|
124
|
+
it "should be able to build_reconfigure_instances_script_for" do
|
125
|
+
str = open(Master.build_reconfigure_instances_script_for(@node)).read
|
126
|
+
str.should =~ /hostname -v node0/
|
127
|
+
str.should =~ /mkdir \/etc\/ha\.d\/resource\.d/
|
128
|
+
str.should =~ /pool\ maintain\ \-c \~\/\.config/
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
describe "displaying" do
|
133
|
+
it "should be able to list the cloud instances" do
|
134
|
+
@master.list.should =~ /CLOUD \(/
|
135
|
+
end
|
136
|
+
end
|
137
|
+
describe "monitoring" do
|
138
|
+
it "should start the monitor when calling start_monitor!" do
|
139
|
+
@master.should_receive(:run_thread_loop).and_return(Proc.new {})
|
140
|
+
@master.start_monitor!
|
141
|
+
end
|
142
|
+
it "should request to launch a new instance" do
|
143
|
+
@master.should_receive(:add_instance_if_load_is_high).and_return(true)
|
144
|
+
@master.add_instance_if_load_is_high
|
145
|
+
end
|
146
|
+
it "should request to terminate a non-master instance if the load" do
|
147
|
+
@master.should_receive(:contract?).and_return(true)
|
148
|
+
@master.should_receive(:request_termination_of_instance).and_return(true)
|
149
|
+
@master.terminate_instance_if_load_is_low
|
150
|
+
end
|
151
|
+
end
|
152
|
+
describe "expanding and contracting" do
|
153
|
+
it "should be able to say that it should not contract" do
|
154
|
+
@master.stub!(:web).and_return(10.2)
|
155
|
+
@master.stub!(:cpu).and_return(0.32)
|
156
|
+
|
157
|
+
@master.contract?.should == false
|
158
|
+
end
|
159
|
+
it "should be able to say that it should contract" do
|
160
|
+
@master.stub!(:web).and_return(30.2)
|
161
|
+
@master.stub!(:cpu).and_return(0.05)
|
162
|
+
|
163
|
+
@master.contract?.should == true
|
164
|
+
end
|
165
|
+
it "should be able to say that it should not expand if it shouldn't expand" do
|
166
|
+
@master.stub!(:web).and_return(30.2)
|
167
|
+
@master.stub!(:cpu).and_return(0.92)
|
168
|
+
|
169
|
+
@master.expand?.should == false
|
170
|
+
end
|
171
|
+
it "should be able to say that it should expand if it should expand" do
|
172
|
+
@master.stub!(:web).and_return(1.2)
|
173
|
+
@master.stub!(:cpu).and_return(0.92)
|
174
|
+
|
175
|
+
@master.expand?.should == true
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
describe "Configuration" do
|
180
|
+
it "should be able to build the haproxy file" do
|
181
|
+
@master.build_haproxy_file
|
182
|
+
end
|
183
|
+
end
|
184
|
+
describe "Singleton methods" do
|
185
|
+
before(:each) do
|
186
|
+
@master = Master.new
|
187
|
+
@instance = RemoteInstance.new
|
188
|
+
@blk = Proc.new {puts "new"}
|
189
|
+
Master.stub!(:new).once.and_return @master
|
190
|
+
end
|
191
|
+
it "should be able to run with_nodes" do
|
192
|
+
Master.should_receive(:new).once.and_return @master
|
193
|
+
@master.should_receive(:nodes).once.and_return []
|
194
|
+
Master.with_nodes &@blk
|
195
|
+
end
|
196
|
+
it "should run the block on each node" do
|
197
|
+
collection = [@instance]
|
198
|
+
@master.should_receive(:nodes).once.and_return collection
|
199
|
+
collection.should_receive(:each).once
|
200
|
+
Master.with_nodes &@blk
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require "lib/poolparty/monitors/cpu"
|
3
|
+
|
4
|
+
describe "monitors" do
|
5
|
+
describe "when included" do
|
6
|
+
before(:each) do
|
7
|
+
@master = Master.new
|
8
|
+
@instance = RemoteInstance.new
|
9
|
+
end
|
10
|
+
it "should include them in the Monitors module" do
|
11
|
+
@master.methods.include?("cpu").should == true
|
12
|
+
end
|
13
|
+
it "should also include the new methods in the remote model" do
|
14
|
+
RemoteInstance.new.methods.include?("cpu").should == true
|
15
|
+
end
|
16
|
+
describe "master" do
|
17
|
+
before(:each) do
|
18
|
+
@master.stub!(:list_of_nonterminated_instances).and_return(
|
19
|
+
[{:instance_id => "i-abcdde1"}]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
it "should try to collect the cpu for the entire set of remote instances when calling cpu" do
|
23
|
+
@master.nodes.should_receive(:inject).once.and_return 0.0
|
24
|
+
@master.cpu
|
25
|
+
end
|
26
|
+
end
|
27
|
+
describe "remote instance" do
|
28
|
+
it "should try to ssh into the remote instance" do
|
29
|
+
@instance.should_receive(:ssh).once.with("uptime")
|
30
|
+
@instance.cpu
|
31
|
+
end
|
32
|
+
it "should be able to find the exact amount of time the processor has been up" do
|
33
|
+
@instance.stub!(:ssh).once.with("uptime").and_return("18:55:31 up 5 min, 1 user, load average: 0.32, 0.03, 0.00")
|
34
|
+
@instance.cpu.should == 0.32
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require "lib/poolparty/monitors/memory"
|
3
|
+
|
4
|
+
describe "monitors" do
|
5
|
+
describe "when included" do
|
6
|
+
before(:each) do
|
7
|
+
@master = Master.new
|
8
|
+
@instance = RemoteInstance.new
|
9
|
+
end
|
10
|
+
it "should include them in the Monitors module" do
|
11
|
+
@master.methods.include?("memory").should == true
|
12
|
+
end
|
13
|
+
it "should also include the new methods in the remote model" do
|
14
|
+
@instance.methods.include?("memory").should == true
|
15
|
+
end
|
16
|
+
describe "master" do
|
17
|
+
before(:each) do
|
18
|
+
@master.stub!(:list_of_nonterminated_instances).and_return(
|
19
|
+
[{:instance_id => "i-abcdde1"}]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
it "should try to collect the cpu for the entire set of remote instances when calling cpu" do
|
23
|
+
@master.nodes.should_receive(:inject).once.and_return 0.0
|
24
|
+
@master.memory
|
25
|
+
end
|
26
|
+
end
|
27
|
+
describe "remote instance" do
|
28
|
+
it "should try to ssh into the remote instance" do
|
29
|
+
@instance.should_receive(:ssh).once.with("free -m | grep -i mem")
|
30
|
+
@instance.memory
|
31
|
+
end
|
32
|
+
it "should be able to find the exact amount of time the processor has been up" do
|
33
|
+
@instance.stub!(:ssh).once.with("free -m | grep -i mem").and_return("Mem: 1700 546 1644 0 2 18")
|
34
|
+
@instance.memory.round_to(2).should == 0.32
|
35
|
+
end
|
36
|
+
end
|
37
|
+
# it "should web monitor should be able to extract the amount of the requests it can handle" do
|
38
|
+
# str = "Request rate: 1.5 req/s (649.9 ms/req)"
|
39
|
+
# # Monitors::Web.monitor_from_string(str).should == 1.5
|
40
|
+
# end
|
41
|
+
# it "should be able to monitor the percentage of memory available on the server" do
|
42
|
+
# str = "Mem: 1700 56 1644 0 2 18"
|
43
|
+
# # Monitors::Memory.monitor_from_string(str).to_s.should =~ /0.032/
|
44
|
+
# end
|
45
|
+
# it "should be able to show the load on the cpu available on the server" do
|
46
|
+
# str = "18:55:31 up 5 min, 1 user, load average: 0.32, 0.03, 0.00"
|
47
|
+
# # Monitors::Cpu.monitor_from_string(str).should == 0.32
|
48
|
+
# end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
module Database
|
4
|
+
module Master
|
5
|
+
def db
|
6
|
+
nodes.inject(0) {|i,inst| i * inst.db} / nodes.size
|
7
|
+
end
|
8
|
+
end
|
9
|
+
module Remote
|
10
|
+
def db
|
11
|
+
5.0
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
PoolParty.register_monitor Database
|
17
|
+
|
18
|
+
describe "monitors (random, to spec the inclusion)" do
|
19
|
+
describe "when included" do
|
20
|
+
before(:each) do
|
21
|
+
@master = Master.new
|
22
|
+
@instance = RemoteInstance.new
|
23
|
+
end
|
24
|
+
it "should include them in the Monitors module" do
|
25
|
+
@master.methods.include?("db").should == true
|
26
|
+
end
|
27
|
+
it "should also include the new methods in the remote model" do
|
28
|
+
@instance.methods.include?("db").should == true
|
29
|
+
end
|
30
|
+
describe "master" do
|
31
|
+
before(:each) do
|
32
|
+
@master.stub!(:list_of_nonterminated_instances).and_return(
|
33
|
+
[{:instance_id => "i-abcdde1"}]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
it "should try to collect the cpu for the entire set of remote instances when calling cpu" do
|
37
|
+
@master.nodes.should_receive(:inject).once.and_return 5.0
|
38
|
+
@master.db.should == 5.0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
describe "remote instance" do
|
42
|
+
it "should try to ssh into the remote instance" do
|
43
|
+
@instance.db.should == 5.0
|
44
|
+
end
|
45
|
+
it "should be able to find the exact amount of time the processor has been up" do
|
46
|
+
@instance.db.round_to(2).should == 5.0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require "lib/poolparty/monitors/web"
|
3
|
+
|
4
|
+
describe "monitors" do
|
5
|
+
describe "when included" do
|
6
|
+
before(:each) do
|
7
|
+
Application.stub!(:client_port).and_return 8001
|
8
|
+
@master = Master.new
|
9
|
+
@instance = RemoteInstance.new
|
10
|
+
end
|
11
|
+
it "should include them in the Monitors module" do
|
12
|
+
@master.methods.include?("web").should == true
|
13
|
+
end
|
14
|
+
it "should also include the new methods in the remote model" do
|
15
|
+
@instance.methods.include?("web").should == true
|
16
|
+
end
|
17
|
+
describe "master" do
|
18
|
+
before(:each) do
|
19
|
+
@master.stub!(:list_of_nonterminated_instances).and_return(
|
20
|
+
[{:instance_id => "i-abcdde1"}]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
it "should try to collect the cpu for the entire set of remote instances when calling cpu" do
|
24
|
+
@master.nodes.should_receive(:inject).once.and_return 0.0
|
25
|
+
@master.web
|
26
|
+
end
|
27
|
+
end
|
28
|
+
describe "remote instance" do
|
29
|
+
it "should try to ssh into the remote instance" do
|
30
|
+
@instance.should_receive(:ssh).once.with("httperf --server localhost --port #{Application.client_port} --num-conn 3 --timeout 5 | grep 'Request rate'")
|
31
|
+
@instance.web
|
32
|
+
end
|
33
|
+
it "should be able to find the exact amount of time the processor has been up" do
|
34
|
+
@instance.stub!(:ssh).once.and_return("Request rate: 1.5 req/s (649.9 ms/req)")
|
35
|
+
@instance.web.round_to(2).should == 1.5
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Optioner with options" do
|
4
|
+
it "should be able to pull out the lonely arguments without any switches" do
|
5
|
+
Optioner.parse("hello".split(" ")).should == ["hello"]
|
6
|
+
end
|
7
|
+
it "should be able to pull out the lonely arguments with switches" do
|
8
|
+
Optioner.parse("-s 30.seconds -m hello world".split(" ")).should == ["world"]
|
9
|
+
end
|
10
|
+
it "should be able to pull out start from the the string" do
|
11
|
+
Optioner.parse("-c 'config/config.yml' -A 'Who' -S 'DarkwingDuck' list".split(" ")).should == ["list"]
|
12
|
+
end
|
13
|
+
it "should be able to pull out the lonely arguments with optional argument switches" do
|
14
|
+
Optioner.parse("-s 30 -q -n start".split(" "), %w(-q -n)).should == ["start"]
|
15
|
+
end
|
16
|
+
it "should pull out the lonely arguments if none are there" do
|
17
|
+
Optioner.parse("-s 30 -q".split(" ")).should == []
|
18
|
+
end
|
19
|
+
it "should pull out empty array if there are no lonely arguments" do
|
20
|
+
Optioner.parse("-s 30".split(" ")).should == []
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Plugin manager" do
|
4
|
+
before(:each) do
|
5
|
+
FileUtils.stub!(:mkdir_p).and_return true
|
6
|
+
Dir["./spec/../lib/../vendor/*"].each {|a| FileUtils.rm_rf a}
|
7
|
+
end
|
8
|
+
it "should git clone the directory when it is installing a plugin" do
|
9
|
+
File.stub!(:directory?).and_return false
|
10
|
+
Git.should_receive(:clone).with("git@github.com:auser/pool-party.git", "/Users/auser/Sites/work/citrusbyte/internal/gems/pool-party/pool/vendor/pool-party").and_return true
|
11
|
+
PluginManager.install_plugin "git@github.com:auser/pool-party.git"
|
12
|
+
end
|
13
|
+
it "should keep a list of the installed plugin locations" do
|
14
|
+
PluginManager.install_plugin "git@github.com:auser/pool-party-plugins.git"
|
15
|
+
PoolParty.installed_plugins.should == ["git@github.com:auser/pool-party-plugins.git"]
|
16
|
+
end
|
17
|
+
it "should be able to rescan the plugin directory and tell which plugins are installed" do
|
18
|
+
PluginManager.install_plugin "git@github.com:auser/pool-party-plugins.git"
|
19
|
+
PluginManager.scan.should == %w(pool-party-plugins)
|
20
|
+
end
|
21
|
+
it "should be able to remove a plugin based on the name" do
|
22
|
+
PluginManager.install_plugin "git@github.com:auser/pool-party-plugins.git"
|
23
|
+
PluginManager.remove_plugin "pool-party-plugins"
|
24
|
+
PluginManager.scan.should == %w()
|
25
|
+
end
|
26
|
+
it "should be able to extract the git repos from the .git/config file" do
|
27
|
+
PluginManager.install_plugin "git@github.com:auser/pool-party-plugins.git"
|
28
|
+
PoolParty.reset!
|
29
|
+
PoolParty.installed_plugins.should == ["git@github.com:auser/pool-party-plugins.git"]
|
30
|
+
end
|
31
|
+
end
|
data/spec/plugin_spec.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
class TestPlugin < PoolParty::Plugin
|
4
|
+
after_define_tasks :takss
|
5
|
+
after_install :echo_hosts, :email_updates
|
6
|
+
before_configure :echo_hosts
|
7
|
+
after_start :echo_start
|
8
|
+
|
9
|
+
def echo_start(master)
|
10
|
+
"start"
|
11
|
+
end
|
12
|
+
def echo_hosts(caller)
|
13
|
+
"hosts"
|
14
|
+
end
|
15
|
+
def email_updates(caller)
|
16
|
+
"email"
|
17
|
+
end
|
18
|
+
def takss(tasks)
|
19
|
+
"tasks"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "Plugin" do
|
24
|
+
it "should define run_before method" do
|
25
|
+
TestPlugin.methods.include?("before_install").should == true
|
26
|
+
end
|
27
|
+
it "should define run_after method" do
|
28
|
+
TestPlugin.methods.include?("after_install").should == true
|
29
|
+
end
|
30
|
+
it "should define a singleton method on the plugin'ed class" do
|
31
|
+
Master.new.methods.include?("testplugin").should == true
|
32
|
+
end
|
33
|
+
describe "usage" do
|
34
|
+
before(:each) do
|
35
|
+
@instance = RemoteInstance.new
|
36
|
+
@master = Master.new
|
37
|
+
|
38
|
+
@test = TestPlugin.new
|
39
|
+
@test.stub!(:echo_hosts).and_return("true")
|
40
|
+
@test.stub!(:email_updates).and_return("true")
|
41
|
+
@test.stub!(:echo_start).and_return("true")
|
42
|
+
TestPlugin.stub!(:new).and_return(@test)
|
43
|
+
Kernel.stub!(:wait).and_return true
|
44
|
+
|
45
|
+
@master.stub!(:launch_minimum_instances).and_return true
|
46
|
+
@master.stub!(:number_of_pending_instances).and_return 0
|
47
|
+
@master.stub!(:get_node).with(0).and_return @instance
|
48
|
+
|
49
|
+
@instance.stub!(:ssh).and_return "true"
|
50
|
+
@instance.stub!(:scp).and_return "true"
|
51
|
+
Kernel.stub!(:system).and_return "true"
|
52
|
+
end
|
53
|
+
it "should should call echo_hosts after calling configure" do
|
54
|
+
@test.should_receive(:echo_hosts).at_least(1)
|
55
|
+
@instance.install
|
56
|
+
end
|
57
|
+
it "should call email_updates after calling install" do
|
58
|
+
@test.should_receive(:email_updates).at_least(1)
|
59
|
+
@instance.install
|
60
|
+
end
|
61
|
+
it "should call echo_hosts before it calls configure" do
|
62
|
+
@test.should_receive(:echo_hosts).at_least(1).and_return "hi"
|
63
|
+
@instance.configure
|
64
|
+
end
|
65
|
+
it "should not call echo_hosts after if configures" do
|
66
|
+
@test.should_not_receive(:email_updates)
|
67
|
+
@instance.configure
|
68
|
+
end
|
69
|
+
it "should say that it started on the master" do
|
70
|
+
@test.should_receive(:echo_start).at_least(1).and_return "hi"
|
71
|
+
@master.start
|
72
|
+
end
|
73
|
+
describe "instance methods" do
|
74
|
+
before(:each) do
|
75
|
+
@str = "filename"
|
76
|
+
@str.stub!(:read).and_return "filename"
|
77
|
+
@test.stub!(:open).and_return @str
|
78
|
+
end
|
79
|
+
it "should try to open the file with the given filename" do
|
80
|
+
@test.should_receive(:open).with("filename").and_return @str
|
81
|
+
@test.read_config_file("filename")
|
82
|
+
end
|
83
|
+
it "should open a yaml file" do
|
84
|
+
YAML.should_receive(:load).with("filename").and_return ""
|
85
|
+
@test.read_config_file("filename")
|
86
|
+
end
|
87
|
+
describe "when reading the yaml file" do
|
88
|
+
before(:each) do
|
89
|
+
@str.stub!(:read).and_return ":username: eddie\n:password: eddie"
|
90
|
+
end
|
91
|
+
it "should parse the yaml file to a Hash" do
|
92
|
+
@str.should_receive(:read).and_return ":username: eddie\n:password: eddie"
|
93
|
+
@test.read_config_file("filename").class.should == Hash
|
94
|
+
end
|
95
|
+
it "should parse the yaml file into the proper hash" do
|
96
|
+
@test.read_config_file("filename").should == {:username => "eddie", :password => "eddie"}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Pool binary" do
|
4
|
+
describe "running" do
|
5
|
+
it "should call PoolParty.options" do
|
6
|
+
options = PoolParty.options(:optsparse => {:banner => "Usage: pool [OPTIONS] {start | stop | list | maintain | restart}" })
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Application options" do
|
4
|
+
it "should parse and use a config file if it is given for the options" do
|
5
|
+
YAML.should_receive(:load).and_return({:config_file => "config/sample-config.yml"})
|
6
|
+
Application.make_options(:config_file => "config/sample-config.yml")
|
7
|
+
end
|
8
|
+
it "should require all the plugin's init files in the plugin directory" do
|
9
|
+
PoolParty.should_receive(:load_plugins).once
|
10
|
+
Application.options
|
11
|
+
end
|
12
|
+
it "should be able to say that the plugin directory is the current directory" do
|
13
|
+
File.basename(PoolParty.plugin_dir).should == "vendor"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "Provider" do
|
4
|
+
before(:each) do
|
5
|
+
@ips = ["127.0.0.1"]
|
6
|
+
end
|
7
|
+
it "should be able to make a roles from the ips" do
|
8
|
+
Provider.string_roles_from_ips(@ips).should == "role :app, '127.0.0.1'"
|
9
|
+
end
|
10
|
+
describe "running" do
|
11
|
+
it "should be able to run with the provided packages" do
|
12
|
+
Sprinkle::Script.should_receive(:sprinkle).once.and_return true
|
13
|
+
Provider.should_receive(:string_roles_from_ips).with(@ips).and_return ""
|
14
|
+
Provider.install_poolparty(@ips)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|