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.
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