auser-poolparty 0.0.8
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/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
|