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
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
class RemoteInstance
|
|
4
|
+
def scp(src="", dest="", opts={})
|
|
5
|
+
"true"
|
|
6
|
+
end
|
|
7
|
+
# Ssh into the instance or run a command, if the cmd is set
|
|
8
|
+
def ssh(cmd="")
|
|
9
|
+
"true"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
describe "remote instance" do
|
|
13
|
+
before(:each) do
|
|
14
|
+
@instance = RemoteInstance.new({:ip => "127.0.0.1", :instance_id => "i-abcdef1"})
|
|
15
|
+
@instance.stub!(:ssh).and_return true
|
|
16
|
+
@instance.stub!(:scp).and_return true
|
|
17
|
+
Kernel.stub!(:system).and_return true
|
|
18
|
+
|
|
19
|
+
@master = Master.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "scping" do
|
|
23
|
+
end
|
|
24
|
+
describe "ssh'ing" do
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "in general" do
|
|
28
|
+
it "should set the ip upon creation" do
|
|
29
|
+
@instance.ip.should == "127.0.0.1"
|
|
30
|
+
end
|
|
31
|
+
it "should be able to tell if it is the master" do
|
|
32
|
+
@instance.master?.should == true
|
|
33
|
+
end
|
|
34
|
+
it "should be able to say that it isn't secondary?" do
|
|
35
|
+
@instance.secondary?.should_not be_true
|
|
36
|
+
end
|
|
37
|
+
it "should be able to build itself a haproxy_resources_entry" do
|
|
38
|
+
@instance.haproxy_resources_entry.should =~ /node0/
|
|
39
|
+
end
|
|
40
|
+
it "should be able to build a list of the heartbeat nodes" do
|
|
41
|
+
@instance.node_entry.should =~ /node0/
|
|
42
|
+
end
|
|
43
|
+
it "should be able to build a hosts_entry for self" do
|
|
44
|
+
@instance.hosts_entry.should =~ /node0/
|
|
45
|
+
end
|
|
46
|
+
it "should be able to have local_hosts_entry with 127.0.0.01" do
|
|
47
|
+
@instance.local_hosts_entry.should =~ /127\.0\.0\.1/
|
|
48
|
+
end
|
|
49
|
+
it "should have a heartbeat_entry" do
|
|
50
|
+
@instance.heartbeat_entry.should =~ /127\.0\.0\.1/
|
|
51
|
+
@instance.heartbeat_entry.should =~ /#{Application.managed_services}/
|
|
52
|
+
end
|
|
53
|
+
it "should be able to build a haproxy_entry" do
|
|
54
|
+
@instance.haproxy_entry.should =~ /server/
|
|
55
|
+
end
|
|
56
|
+
describe "callbacks" do
|
|
57
|
+
it "should call configure after it calls install"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
describe "new configuration style (build scripts)" do
|
|
61
|
+
before(:each) do
|
|
62
|
+
@tempfile = Tempfile.new("/tmp")
|
|
63
|
+
Kernel.stub!(:system).and_return true
|
|
64
|
+
end
|
|
65
|
+
# it "should try to run the scp build file" do
|
|
66
|
+
# Master.should_receive(:build_scp_instances_script_for).with(@instance).and_return @tempfile
|
|
67
|
+
# @instance.configure
|
|
68
|
+
# end
|
|
69
|
+
# it "should try to run and build the reconfigure script for the node" do
|
|
70
|
+
# Master.should_receive(:build_reconfigure_instances_script_for).with(@instance).and_return @tempfile
|
|
71
|
+
# @instance.configure
|
|
72
|
+
# end
|
|
73
|
+
# it "should scp the reconfigure file to the remote instance" do
|
|
74
|
+
# @instance.should_receive(:scp).once.and_return true
|
|
75
|
+
# @instance.configure
|
|
76
|
+
# end
|
|
77
|
+
# it "should ssh and execute the reconfigure file on the remote instance" do
|
|
78
|
+
# @instance.should_receive(:ssh).once.with("chmod +x /usr/local/src/reconfigure.sh && /bin/sh /usr/local/src/reconfigure.sh").and_return true
|
|
79
|
+
# @instance.configure
|
|
80
|
+
# end
|
|
81
|
+
describe "with a public ip" do
|
|
82
|
+
before(:each) do
|
|
83
|
+
Application.stub!(:public_ip).and_return "127.0.0.1"
|
|
84
|
+
end
|
|
85
|
+
it "should run associate_address if there is a public_ip set in the Application.options" do
|
|
86
|
+
@instance.should_receive(:associate_address_with).with(Application.public_ip, @instance.instance_id).and_return true
|
|
87
|
+
@instance.configure
|
|
88
|
+
end
|
|
89
|
+
it "should not run associate_address_with if the public_ip is empty" do
|
|
90
|
+
Application.stub!(:public_ip).and_return ""
|
|
91
|
+
@instance.should_not_receive(:associate_address_with)
|
|
92
|
+
@instance.configure
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
describe "in failover" do
|
|
98
|
+
it "should be able to become master " do
|
|
99
|
+
@instance.stub!(:configure).and_return true
|
|
100
|
+
@instance.number = 1
|
|
101
|
+
@instance.become_master
|
|
102
|
+
@instance.number.should == 0
|
|
103
|
+
end
|
|
104
|
+
it "should reconfigure after becoming master" do
|
|
105
|
+
@instance.should_receive(:configure).and_return true
|
|
106
|
+
@instance.become_master
|
|
107
|
+
end
|
|
108
|
+
it "should say that it is the master after becoming master" do
|
|
109
|
+
@instance.stub!(:configure).and_return true
|
|
110
|
+
@instance.become_master
|
|
111
|
+
@instance.master?.should == true
|
|
112
|
+
end
|
|
113
|
+
it "should be able to detect is_not_master_and_master_is_not_running? and return false when the server is the master" do
|
|
114
|
+
@instance.is_not_master_and_master_is_not_running?.should == false
|
|
115
|
+
end
|
|
116
|
+
it "should be able to detect is_not_master_and_master_is_not_running? and return false when the master server is responding" do
|
|
117
|
+
Master.stub!(:is_master_responding?).and_return true
|
|
118
|
+
@instance.is_not_master_and_master_is_not_running?.should == false
|
|
119
|
+
end
|
|
120
|
+
it "should be able to detect is_not_master_and_master_is_not_running? and return false when the master server is responding" do
|
|
121
|
+
@instance.stub!(:master?).and_return false
|
|
122
|
+
Master.stub!(:is_master_responding?).and_return false
|
|
123
|
+
@instance.is_not_master_and_master_is_not_running?.should == true
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
describe "when installing the poolparty software" do
|
|
127
|
+
it "should be able to detect if the stack_installed? == false" do
|
|
128
|
+
@instance.stack_installed?.should == false
|
|
129
|
+
end
|
|
130
|
+
it "should set the stack_installed? once installed" do
|
|
131
|
+
@instance.install
|
|
132
|
+
@instance.stack_installed?.should == true
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe "when installing plugins" do
|
|
137
|
+
it "should call update_plugins after become master" do
|
|
138
|
+
@instance.should_receive(:update_plugins).at_least(1)
|
|
139
|
+
@instance.configure
|
|
140
|
+
end
|
|
141
|
+
it "should try to install the plugins from the git repos of the installed plugins" do
|
|
142
|
+
PluginManager.remove_plugin "pool-party-plugins"
|
|
143
|
+
PluginManager.install_plugin "git@github.com:auser/pool-party-plugins.git"
|
|
144
|
+
@instance.update_plugin_string.should == ["git@github.com:auser/pool-party-plugins.git"]
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
class TestRemote
|
|
4
|
+
include Remoter
|
|
5
|
+
include Callbacks
|
|
6
|
+
attr_accessor :ip
|
|
7
|
+
end
|
|
8
|
+
describe "Remoter" do
|
|
9
|
+
before(:each) do
|
|
10
|
+
@instance = RemoteInstance.new
|
|
11
|
+
@master = Master.new
|
|
12
|
+
|
|
13
|
+
@remoter = TestRemote.new
|
|
14
|
+
@remoter.stub!(:put).and_return "true"
|
|
15
|
+
# @tempfile = Tempfile.new("/tmp") do |f|
|
|
16
|
+
# f << "hi"
|
|
17
|
+
# end
|
|
18
|
+
Application.stub!(:ec2_dir).and_return "/Users"
|
|
19
|
+
Application.stub!(:keypair).and_return "app"
|
|
20
|
+
Application.stub!(:username).and_return "root"
|
|
21
|
+
end
|
|
22
|
+
it "should have an ssh method that corresponds to ssm with the keypair" do
|
|
23
|
+
@remoter.ssh_string.should == "ssh -i /Users/id_rsa-app -o StrictHostKeyChecking=no"
|
|
24
|
+
end
|
|
25
|
+
it "should have a list of ssh_tasks" do
|
|
26
|
+
@remoter.ssh_tasks.should == []
|
|
27
|
+
end
|
|
28
|
+
it "should have a list of scp_tasks" do
|
|
29
|
+
@remoter.scp_tasks.should == []
|
|
30
|
+
end
|
|
31
|
+
it "should reset the values to nil when calling reset" do
|
|
32
|
+
@remoter.target_hosts.should_not be_nil
|
|
33
|
+
@remoter.reset!
|
|
34
|
+
@hosts.should be_nil
|
|
35
|
+
end
|
|
36
|
+
describe "executing" do
|
|
37
|
+
it "should call set_hosts before it executes the tasks" do
|
|
38
|
+
@remoter.should_receive(:set_hosts).once
|
|
39
|
+
@remoter.execute_tasks {}
|
|
40
|
+
end
|
|
41
|
+
it "should not call set_hosts before it executes the task if it explicitly doesn't want it to" do
|
|
42
|
+
@remoter.should_not_receive(:set_hosts)
|
|
43
|
+
@remoter.execute_tasks(:dont_set_hosts => true) {}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "ssh" do
|
|
47
|
+
before(:each) do
|
|
48
|
+
@arr = []
|
|
49
|
+
@arr << @a = proc{puts "hello"}
|
|
50
|
+
@arr << @b = proc{puts "world"}
|
|
51
|
+
@instance.stub!(:ip).and_return("127.0.0.1")
|
|
52
|
+
end
|
|
53
|
+
it "should run the tasks in an array with run_thread_list" do
|
|
54
|
+
@remoter.should_receive(:run_thread_list).once
|
|
55
|
+
@remoter.run_array_of_tasks(@arr)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should be able to collect the list of the target hosts's ips" do
|
|
59
|
+
Master.should_receive(:new).and_return(@master)
|
|
60
|
+
@master.stub!(:nodes).and_return([@instance])
|
|
61
|
+
@remoter.target_hosts.should == %w(127.0.0.1)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
require File.dirname(__FILE__) + "/helpers/ec2_mock"
|
|
3
|
+
|
|
4
|
+
describe "Master remoting: " do
|
|
5
|
+
before(:each) do
|
|
6
|
+
Kernel.stub!(:system).and_return true
|
|
7
|
+
Application.stub!(:environment).and_return("test") # So it doesn't daemonize
|
|
8
|
+
Application.stub!(:minimum_instances).and_return(2)
|
|
9
|
+
Application.stub!(:maximum_instances).and_return(10)
|
|
10
|
+
Application.stub!(:polling_time).and_return(0.1)
|
|
11
|
+
Application.stub!(:verbose).and_return(false) # Turn off messaging
|
|
12
|
+
|
|
13
|
+
@master = Master.new
|
|
14
|
+
@master.launch_new_instance!
|
|
15
|
+
end
|
|
16
|
+
describe "starting" do
|
|
17
|
+
before(:each) do
|
|
18
|
+
@master.start_cloud!
|
|
19
|
+
end
|
|
20
|
+
it "should start the cloud with instances" do
|
|
21
|
+
@master.list_of_instances.should_not be_empty
|
|
22
|
+
end
|
|
23
|
+
it "should start the cloud with running instances" do
|
|
24
|
+
@master.list_of_running_instances.should_not be_empty
|
|
25
|
+
end
|
|
26
|
+
it "should start with the minimum_instances running" do
|
|
27
|
+
wait 0.5 # Give the last one time to get to running
|
|
28
|
+
@master.list_of_running_instances.size.should == Application.minimum_instances
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
describe "maintaining" do
|
|
32
|
+
it "should maintain the minimum_instances if one goes down" do
|
|
33
|
+
@master.start_cloud!
|
|
34
|
+
wait 0.2 # Give the two instances time to boot up
|
|
35
|
+
(Application.minimum_instances - @master.number_of_pending_and_running_instances).should == 0
|
|
36
|
+
|
|
37
|
+
# Kill one off to test how it handles the response
|
|
38
|
+
@master.terminate_instance!(@master.list_of_running_instances[0][:instance_id])
|
|
39
|
+
(Application.minimum_instances - @master.number_of_pending_and_running_instances).should == 1
|
|
40
|
+
@master.launch_minimum_instances # Assume this runs in the bg process
|
|
41
|
+
|
|
42
|
+
(Application.minimum_instances - @master.number_of_pending_and_running_instances).should == 0
|
|
43
|
+
@master.number_of_pending_and_running_instances.should == Application.minimum_instances
|
|
44
|
+
end
|
|
45
|
+
it "should launch a new instance when the load gets too heavy set in the configs" do
|
|
46
|
+
@master.stub!(:expand?).and_return true
|
|
47
|
+
@master.start_cloud!
|
|
48
|
+
wait 0.2 # Give the two instances time to boot up
|
|
49
|
+
(Application.minimum_instances - @master.number_of_pending_and_running_instances).should == 0
|
|
50
|
+
@master.scale_cloud!
|
|
51
|
+
@master.nodes.size.should == Application.minimum_instances + 1
|
|
52
|
+
end
|
|
53
|
+
it "should terminate an instance when the load shows that it's too light" do
|
|
54
|
+
@master.stub!(:contract?).and_return true
|
|
55
|
+
@master.start_cloud!
|
|
56
|
+
@master.request_launch_new_instance
|
|
57
|
+
wait 0.5 # Give the two instances time to boot up
|
|
58
|
+
@master.number_of_pending_and_running_instances.should == Application.minimum_instances + 1
|
|
59
|
+
@master.scale_cloud!
|
|
60
|
+
@master.number_of_pending_and_running_instances.should == Application.minimum_instances
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
describe "configuring" do
|
|
64
|
+
it "should call configure on all of the nodes when calling reconfigure_running_instances" do
|
|
65
|
+
@master.nodes.each {|a|
|
|
66
|
+
a.stub!(:status).and_return("running")
|
|
67
|
+
a.should_receive(:configure).and_return true
|
|
68
|
+
}
|
|
69
|
+
@master.reconfigure_running_instances
|
|
70
|
+
end
|
|
71
|
+
it "should call restart_with_monit on all of the nodes when calling restart_running_instances_services" do
|
|
72
|
+
@master.nodes.each {|a| a.should_receive(:restart_with_monit).and_return true }
|
|
73
|
+
@master.restart_running_instances_services
|
|
74
|
+
end
|
|
75
|
+
it "should be able to say there are no number_of_unconfigured_nodes left when all the nodes are configured" do
|
|
76
|
+
@master.nodes.each {|a| a.should_receive(:stack_installed?).and_return true }
|
|
77
|
+
@master.number_of_unconfigured_nodes.should == 0
|
|
78
|
+
end
|
|
79
|
+
it "should be able to say that there is an unconfigured node" do
|
|
80
|
+
@master.nodes[-1].should_receive(:stack_installed?).and_return false
|
|
81
|
+
@master.number_of_unconfigured_nodes.should_not == 0
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
class TestSched
|
|
4
|
+
include Scheduler
|
|
5
|
+
end
|
|
6
|
+
describe "Scheduler" do
|
|
7
|
+
before(:each) do
|
|
8
|
+
@test = TestSched.new
|
|
9
|
+
end
|
|
10
|
+
it "should create a ScheduleTasks" do
|
|
11
|
+
@test._tasker.class.should == ScheduleTasks
|
|
12
|
+
end
|
|
13
|
+
describe "run_thread_loop" do
|
|
14
|
+
before(:each) do
|
|
15
|
+
@klass = Class.new
|
|
16
|
+
@klass.stub!(:pop).once.and_return true
|
|
17
|
+
@block = Proc.new {@klass.pop}
|
|
18
|
+
end
|
|
19
|
+
it "should yield the block that it is given" do
|
|
20
|
+
@test.run_thread_list &@block
|
|
21
|
+
end
|
|
22
|
+
it "should run run_threads" do
|
|
23
|
+
@test.should_receive(:run_threads).and_return true
|
|
24
|
+
@test.run_thread_list &@block
|
|
25
|
+
end
|
|
26
|
+
it "should call run on the _tasker" do
|
|
27
|
+
@test._tasker.should_receive(:run).once.and_return true
|
|
28
|
+
@test.run_thread_list &@block
|
|
29
|
+
end
|
|
30
|
+
describe "ScheduleTasks class" do
|
|
31
|
+
before(:each) do
|
|
32
|
+
@stasks = ScheduleTasks.new
|
|
33
|
+
@test.stub!(:_tasker).and_return(@stasks)
|
|
34
|
+
end
|
|
35
|
+
it "should have its tasks listed as an empty array if there are no tasks added" do
|
|
36
|
+
@stasks.tasks.should == []
|
|
37
|
+
end
|
|
38
|
+
it "should have one task listed if it is added" do
|
|
39
|
+
@test.add_task {@klass.pop}
|
|
40
|
+
@stasks.tasks.size.should == 1
|
|
41
|
+
end
|
|
42
|
+
it "should add each task as a thread" do
|
|
43
|
+
Thread.should_receive(:new).once
|
|
44
|
+
@stasks.push proc{puts "hi"}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
describe "when running" do
|
|
48
|
+
before(:each) do
|
|
49
|
+
@test.add_task {@klass.pop}
|
|
50
|
+
end
|
|
51
|
+
it "should not run the tasks after adding them" do
|
|
52
|
+
@klass.should_not_receive(:pop)
|
|
53
|
+
@test.add_task {@klass.pop}
|
|
54
|
+
end
|
|
55
|
+
it "should run the tasks when run_thread_list" do
|
|
56
|
+
@klass.should_receive(:pop)
|
|
57
|
+
@test.run_thread_list
|
|
58
|
+
end
|
|
59
|
+
it "should be able to add tasks and have the run_thread_list run" do
|
|
60
|
+
@test._tasker.class.should_receive(:synchronize).once
|
|
61
|
+
@test.run_thread_list
|
|
62
|
+
end
|
|
63
|
+
it "should empty all the tasks after running them in the loop" do
|
|
64
|
+
@test.run_thread_list
|
|
65
|
+
@test._tasker.tasks.size.should == 0
|
|
66
|
+
end
|
|
67
|
+
describe "daemonizing" do
|
|
68
|
+
it "should detached the process" do
|
|
69
|
+
Process.should_receive(:detach).once
|
|
70
|
+
@test.daemonize
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib poolparty])
|
|
2
|
+
|
|
3
|
+
%w(test/spec).each do |library|
|
|
4
|
+
begin
|
|
5
|
+
require library
|
|
6
|
+
rescue
|
|
7
|
+
STDERR.puts "== Cannot run test without #{library}"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Dir["#{File.dirname(__FILE__)}/helpers/**"].each {|a| require a}
|
|
12
|
+
|
|
13
|
+
include PoolParty
|
|
14
|
+
extend PoolParty
|
|
15
|
+
|
|
16
|
+
Application.environment = "test"
|
|
17
|
+
Application.verbose = false
|
|
18
|
+
|
|
19
|
+
def wait_launch(time=5)
|
|
20
|
+
pid = fork {yield}
|
|
21
|
+
wait time
|
|
22
|
+
Process.kill("INT", pid)
|
|
23
|
+
Process.wait(pid, 0)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module Test::Unit::AssertDifference
|
|
27
|
+
def assert_difference(object, method = nil, difference = 1)
|
|
28
|
+
initial_value = object.send(method)
|
|
29
|
+
yield
|
|
30
|
+
assert_equal initial_value + difference, object.send(method), "#{object}##{method}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def assert_no_difference(object, method, &block)
|
|
34
|
+
assert_difference object, method, 0, &block
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
Test::Spec::Should.send(:include, Test::Unit::AssertDifference)
|
|
39
|
+
Test::Spec::ShouldNot.send(:include, Test::Unit::AssertDifference)
|
data/spec/string_spec.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "String" do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@string = "string"
|
|
6
|
+
@string.stub!(:bucket_objects).and_return([])
|
|
7
|
+
end
|
|
8
|
+
# Dumb test
|
|
9
|
+
it "should be able to call bucket_objects on itself" do
|
|
10
|
+
@string.should_receive(:bucket_objects)
|
|
11
|
+
@string.bucket_objects
|
|
12
|
+
end
|
|
13
|
+
describe "with config replacements" do
|
|
14
|
+
it "should replace those syms in the string" do
|
|
15
|
+
("new :port" ^ {:port => 100}).should == "new 100"
|
|
16
|
+
end
|
|
17
|
+
it "should be able to detect vars" do
|
|
18
|
+
@string=<<-EOC
|
|
19
|
+
listen web_proxy 127.0.0.1::client_port
|
|
20
|
+
\tserver web1 127.0.0.1::port weight 1 minconn 3 maxconn 6 check inter 30000
|
|
21
|
+
EOC
|
|
22
|
+
(@string ^ {:client_port => 3000, :port => 3001}).should ==<<-EOO
|
|
23
|
+
listen web_proxy 127.0.0.1:3000
|
|
24
|
+
\tserver web1 127.0.0.1:3001 weight 1 minconn 3 maxconn 6 check inter 30000
|
|
25
|
+
EOO
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
server {
|
|
2
|
+
|
|
3
|
+
listen 80;
|
|
4
|
+
server_name www.poolpartyrb.com;
|
|
5
|
+
rewrite ^/(.*) http://poolpartyrb.com permanent;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
server {
|
|
10
|
+
|
|
11
|
+
listen 80;
|
|
12
|
+
server_name poolpartyrb.com;
|
|
13
|
+
|
|
14
|
+
access_log /apps/poolpartyrb/logs/access.log;
|
|
15
|
+
error_log /apps/poolpartyrb/logs/error.log;
|
|
16
|
+
|
|
17
|
+
location / {
|
|
18
|
+
root /apps/poolpartyrb;
|
|
19
|
+
index index.html;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>PoolParty - Cloud EC2 Computing Made Easy</title>
|
|
5
|
+
<link href="/stylesheets/reset.css" media="all" rel="stylesheet" type="text/css"/>
|
|
6
|
+
<link href="/stylesheets/application.css" media="all" rel="stylesheet" type="text/css"/>
|
|
7
|
+
<script type="text/javascript" src="/javascripts/jquery-1.2.6.pack.js"></script>
|
|
8
|
+
<script type="text/javascript" src="/javascripts/corner.js"></script>
|
|
9
|
+
<script type="text/javascript" src="/javascripts/application.js"></script>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div class='container'>
|
|
13
|
+
<div class='balloon'><img alt="Balloon" src="images/balloon.png"/></div>
|
|
14
|
+
<div class='header'>
|
|
15
|
+
<h1><a href="/">PoolParty</a></h1>
|
|
16
|
+
<div class='clouds'><img alt="Clouds" src="images/clouds.png"/></div>
|
|
17
|
+
<div class='links'>
|
|
18
|
+
<a href="#">api</a>
|
|
19
|
+
<a href="http://poolparty.rubyforge.org/">docs</a>
|
|
20
|
+
<a href="misc.html">misc</a>
|
|
21
|
+
<a href="#">group</a>
|
|
22
|
+
</div>
|
|
23
|
+
<div class='clear'>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div class='clear'>
|
|
27
|
+
</div>
|
|
28
|
+
<div class='content'>
|
|
29
|
+
<h2>
|
|
30
|
+
One Ruby <strong><a href="http://github.com/auser/pool-party/tree/master">Gem</a></strong> = easy EC2 computing cloud.
|
|
31
|
+
</h2>
|
|
32
|
+
<div class='tout'>
|
|
33
|
+
<p class='alt'>
|
|
34
|
+
Amazon's Elastic Compute Cloud provides pay-per-use scalability to the masses. However, clouds do not have innate load-balancing ability, and there is no native failover solution.
|
|
35
|
+
</p>
|
|
36
|
+
<p class='alt'>
|
|
37
|
+
PoolParty is an <strong>open source</strong> tool that <strong>automates</strong> deployment, monitoring, and load balancing of EC2 instances. Configure once, and relax by the poolside -- PoolParty will keep your site and its instances afloat.
|
|
38
|
+
</p>
|
|
39
|
+
</div>
|
|
40
|
+
<p>
|
|
41
|
+
"I'm convinced, how do I get started?"
|
|
42
|
+
<code>
|
|
43
|
+
sudo gem install auser-poolparty -s http://gems.github.com
|
|
44
|
+
</code>
|
|
45
|
+
</p>
|
|
46
|
+
<p>
|
|
47
|
+
"Okay, are there examples or documentation?"
|
|
48
|
+
<span class='alt'>
|
|
49
|
+
<a href="http://poolparty.rubyforge.org/">Docs</a>
|
|
50
|
+
&
|
|
51
|
+
<a href="#">Examples</a>
|
|
52
|
+
</span>
|
|
53
|
+
</p>
|
|
54
|
+
<p>
|
|
55
|
+
"How do I extend it?"
|
|
56
|
+
<p class='alt'>
|
|
57
|
+
More coming soon
|
|
58
|
+
<strong>
|
|
59
|
+
<a href='http://github.com/auser/pool-party-plugins/tree/master'>
|
|
60
|
+
http://github.com/auser/pool-party-plugins/tree/master
|
|
61
|
+
</a>
|
|
62
|
+
</strong>
|
|
63
|
+
</p>
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
<div class='cb'>
|
|
67
|
+
<a href="http://www.citrusbyte.com"><img alt="Cb" src="images/cb.png"/></a>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</body>
|
|
71
|
+
</html>
|