auser-poolparty 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CHANGELOG +12 -0
  2. data/Manifest +115 -0
  3. data/README.txt +140 -0
  4. data/Rakefile +27 -0
  5. data/bin/instance +61 -0
  6. data/bin/pool +62 -0
  7. data/config/cloud_master_takeover +17 -0
  8. data/config/create_proxy_ami.sh +582 -0
  9. data/config/haproxy.conf +29 -0
  10. data/config/heartbeat.conf +8 -0
  11. data/config/heartbeat_authkeys.conf +2 -0
  12. data/config/installers/ubuntu_install.sh +77 -0
  13. data/config/monit/haproxy.monit.conf +7 -0
  14. data/config/monit/nginx.monit.conf +0 -0
  15. data/config/monit.conf +9 -0
  16. data/config/nginx.conf +24 -0
  17. data/config/reconfigure_instances_script.sh +18 -0
  18. data/config/sample-config.yml +23 -0
  19. data/config/scp_instances_script.sh +12 -0
  20. data/lib/core/array.rb +13 -0
  21. data/lib/core/exception.rb +9 -0
  22. data/lib/core/float.rb +13 -0
  23. data/lib/core/hash.rb +11 -0
  24. data/lib/core/kernel.rb +12 -0
  25. data/lib/core/module.rb +22 -0
  26. data/lib/core/object.rb +18 -0
  27. data/lib/core/proc.rb +15 -0
  28. data/lib/core/string.rb +49 -0
  29. data/lib/core/time.rb +41 -0
  30. data/lib/modules/callback.rb +133 -0
  31. data/lib/modules/ec2_wrapper.rb +82 -0
  32. data/lib/modules/safe_instance.rb +31 -0
  33. data/lib/modules/vlad_override.rb +82 -0
  34. data/lib/poolparty/application.rb +170 -0
  35. data/lib/poolparty/init.rb +6 -0
  36. data/lib/poolparty/master.rb +329 -0
  37. data/lib/poolparty/monitors/cpu.rb +19 -0
  38. data/lib/poolparty/monitors/memory.rb +26 -0
  39. data/lib/poolparty/monitors/web.rb +23 -0
  40. data/lib/poolparty/monitors.rb +13 -0
  41. data/lib/poolparty/optioner.rb +16 -0
  42. data/lib/poolparty/plugin.rb +43 -0
  43. data/lib/poolparty/plugin_manager.rb +67 -0
  44. data/lib/poolparty/provider/packages/essential.rb +6 -0
  45. data/lib/poolparty/provider/packages/git.rb +4 -0
  46. data/lib/poolparty/provider/packages/haproxy.rb +20 -0
  47. data/lib/poolparty/provider/packages/heartbeat.rb +4 -0
  48. data/lib/poolparty/provider/packages/monit.rb +6 -0
  49. data/lib/poolparty/provider/packages/rsync.rb +4 -0
  50. data/lib/poolparty/provider/packages/ruby.rb +37 -0
  51. data/lib/poolparty/provider/packages/s3fuse.rb +11 -0
  52. data/lib/poolparty/provider/provider.rb +60 -0
  53. data/lib/poolparty/provider.rb +2 -0
  54. data/lib/poolparty/remote_instance.rb +216 -0
  55. data/lib/poolparty/remoter.rb +106 -0
  56. data/lib/poolparty/remoting.rb +112 -0
  57. data/lib/poolparty/scheduler.rb +103 -0
  58. data/lib/poolparty/tasks/cloud.rake +57 -0
  59. data/lib/poolparty/tasks/development.rake +38 -0
  60. data/lib/poolparty/tasks/ec2.rake +20 -0
  61. data/lib/poolparty/tasks/instance.rake +63 -0
  62. data/lib/poolparty/tasks/plugins.rake +30 -0
  63. data/lib/poolparty/tasks/server.rake +42 -0
  64. data/lib/poolparty/tasks.rb +29 -0
  65. data/lib/poolparty/tmp.rb +46 -0
  66. data/lib/poolparty.rb +105 -0
  67. data/lib/s3/s3_object_store_folders.rb +44 -0
  68. data/misc/basics_tutorial.txt +142 -0
  69. data/poolparty.gemspec +72 -0
  70. data/spec/application_spec.rb +39 -0
  71. data/spec/callback_spec.rb +194 -0
  72. data/spec/core_spec.rb +15 -0
  73. data/spec/helpers/ec2_mock.rb +44 -0
  74. data/spec/kernel_spec.rb +11 -0
  75. data/spec/master_spec.rb +203 -0
  76. data/spec/monitors/cpu_monitor_spec.rb +38 -0
  77. data/spec/monitors/memory_spec.rb +50 -0
  78. data/spec/monitors/misc_monitor_spec.rb +50 -0
  79. data/spec/monitors/web_spec.rb +39 -0
  80. data/spec/optioner_spec.rb +22 -0
  81. data/spec/plugin_manager_spec.rb +31 -0
  82. data/spec/plugin_spec.rb +101 -0
  83. data/spec/pool_binary_spec.rb +10 -0
  84. data/spec/poolparty_spec.rb +15 -0
  85. data/spec/provider_spec.rb +17 -0
  86. data/spec/remote_instance_spec.rb +149 -0
  87. data/spec/remoter_spec.rb +65 -0
  88. data/spec/remoting_spec.rb +84 -0
  89. data/spec/scheduler_spec.rb +75 -0
  90. data/spec/spec_helper.rb +39 -0
  91. data/spec/string_spec.rb +28 -0
  92. data/web/static/conf/nginx.conf +22 -0
  93. data/web/static/site/images/balloon.png +0 -0
  94. data/web/static/site/images/cb.png +0 -0
  95. data/web/static/site/images/clouds.png +0 -0
  96. data/web/static/site/images/railsconf_preso_img.png +0 -0
  97. data/web/static/site/index.html +71 -0
  98. data/web/static/site/javascripts/application.js +3 -0
  99. data/web/static/site/javascripts/corner.js +178 -0
  100. data/web/static/site/javascripts/jquery-1.2.6.pack.js +11 -0
  101. data/web/static/site/misc.html +42 -0
  102. data/web/static/site/storage/pool_party_presentation.pdf +0 -0
  103. data/web/static/site/stylesheets/application.css +100 -0
  104. data/web/static/site/stylesheets/reset.css +17 -0
  105. data/web/static/src/layouts/application.haml +25 -0
  106. data/web/static/src/pages/index.haml +25 -0
  107. data/web/static/src/pages/misc.haml +5 -0
  108. data/web/static/src/stylesheets/application.sass +100 -0
  109. metadata +260 -0
@@ -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
@@ -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