auser-poolparty 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -2
- data/Rakefile +61 -4
- data/bin/instance +3 -1
- data/bin/pool +6 -2
- data/config/sample-config.yml +4 -4
- data/lib/core/object.rb +3 -0
- data/lib/helpers/plugin_spec_helper.rb +59 -0
- data/lib/modules/ec2_wrapper.rb +3 -1
- data/lib/modules/file_writer.rb +1 -1
- data/lib/modules/vlad_override.rb +83 -83
- data/lib/poolparty.rb +31 -13
- data/lib/poolparty/application.rb +22 -15
- data/lib/poolparty/init.rb +1 -1
- data/lib/poolparty/master.rb +41 -28
- data/lib/poolparty/monitors.rb +1 -3
- data/lib/poolparty/monitors/cpu.rb +7 -3
- data/lib/poolparty/monitors/memory.rb +14 -7
- data/lib/poolparty/monitors/web.rb +11 -5
- data/lib/poolparty/provider/packages/essential.rb +1 -1
- data/lib/poolparty/provider/packages/heartbeat.rb +1 -1
- data/lib/poolparty/provider/packages/ruby.rb +1 -10
- data/lib/poolparty/remote_instance.rb +5 -18
- data/lib/poolparty/remoter.rb +55 -4
- data/lib/poolparty/scheduler.rb +15 -25
- data/lib/poolparty/thread_pool.rb +94 -0
- data/poolparty.gemspec +9 -6
- data/spec/application_spec.rb +32 -13
- data/spec/callback_spec.rb +20 -1
- data/spec/file_writer_spec.rb +1 -0
- data/spec/kernel_spec.rb +13 -0
- data/spec/master_spec.rb +50 -20
- data/spec/monitors/cpu_monitor_spec.rb +1 -1
- data/spec/plugin_manager_spec.rb +9 -17
- data/spec/plugin_spec.rb +34 -34
- data/spec/poolparty_spec.rb +41 -1
- data/spec/remote_instance_spec.rb +5 -18
- data/spec/scheduler_spec.rb +7 -6
- data/spec/spec_helper.rb +8 -18
- metadata +19 -6
- data/lib/poolparty/tasks/package.rake +0 -53
data/lib/poolparty/remoter.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
=begin rdoc
|
2
2
|
Handle the remoting aspects of the remote_instances
|
3
3
|
=end
|
4
|
+
require 'open4'
|
4
5
|
module PoolParty
|
5
6
|
module Remoter
|
6
7
|
module ClassMethods
|
@@ -66,10 +67,8 @@ module PoolParty
|
|
66
67
|
run_array_of_tasks arr
|
67
68
|
end
|
68
69
|
|
69
|
-
def run_now command
|
70
|
-
unless command.empty?
|
71
|
-
Kernel.system "#{self.class.ssh_string} #{self.ip} #{command.runnable}"
|
72
|
-
end
|
70
|
+
def run_now command
|
71
|
+
run command unless command.empty?
|
73
72
|
end
|
74
73
|
|
75
74
|
def ssh_tasks;@ssh_tasks ||= [];end
|
@@ -107,6 +106,58 @@ module PoolParty
|
|
107
106
|
def set_hosts(c=nil)
|
108
107
|
end
|
109
108
|
|
109
|
+
# Nearly Directly from vlad
|
110
|
+
def run command, on=self
|
111
|
+
cmd = [self.class.ssh_string, on.ip].compact
|
112
|
+
result = []
|
113
|
+
|
114
|
+
commander = cmd.join(" ") << " \"#{command.runnable}\""
|
115
|
+
|
116
|
+
pid, inn, out, err = Open4::popen4(commander)
|
117
|
+
|
118
|
+
inn.sync = true
|
119
|
+
streams = [out, err]
|
120
|
+
out_stream = {
|
121
|
+
out => $stdout,
|
122
|
+
err => $stderr,
|
123
|
+
}
|
124
|
+
|
125
|
+
# Handle process termination ourselves
|
126
|
+
status = nil
|
127
|
+
Thread.start do
|
128
|
+
status = Process.waitpid2(pid).last
|
129
|
+
end
|
130
|
+
|
131
|
+
until streams.empty? do
|
132
|
+
# don't busy loop
|
133
|
+
selected, = select streams, nil, nil, 0.1
|
134
|
+
|
135
|
+
next if selected.nil? or selected.empty?
|
136
|
+
|
137
|
+
selected.each do |stream|
|
138
|
+
if stream.eof? then
|
139
|
+
streams.delete stream if status # we've quit, so no more writing
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
data = stream.readpartial(1024)
|
144
|
+
out_stream[stream].write data
|
145
|
+
|
146
|
+
if stream == err and data =~ /^Password:/ then
|
147
|
+
inn.puts sudo_password
|
148
|
+
data << "\n"
|
149
|
+
$stderr.write "\n"
|
150
|
+
end
|
151
|
+
|
152
|
+
result << data
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
PoolParty.message "execution failed with status #{status.exitstatus}: #{cmd.join ' '}" unless status.success?
|
157
|
+
|
158
|
+
result.join
|
159
|
+
end
|
160
|
+
|
110
161
|
end
|
111
162
|
|
112
163
|
def self.included(receiver)
|
data/lib/poolparty/scheduler.rb
CHANGED
@@ -9,28 +9,21 @@ module PoolParty
|
|
9
9
|
end
|
10
10
|
# Synchronize the running threaded tasks
|
11
11
|
def run
|
12
|
-
unless tasks.empty?
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
a.join
|
18
|
-
rescue Exception => e
|
19
|
-
puts "There was an error in the task: #{e} #{e.backtrace.join("\n")}"
|
20
|
-
end
|
21
|
-
true
|
22
|
-
}
|
12
|
+
unless tasks.empty? && !running?
|
13
|
+
running = true
|
14
|
+
pool = ThreadPool.new(10)
|
15
|
+
tasks.reject! do |task|
|
16
|
+
pool.process {task.call}
|
23
17
|
end
|
18
|
+
pool.join() # When all the tasks are done
|
19
|
+
running = false
|
24
20
|
end
|
25
21
|
end
|
22
|
+
def running?;@running == true;end
|
23
|
+
def running;@running ||= false;end
|
26
24
|
# Add a task in a new thread
|
27
25
|
def <<(a, *args)
|
28
|
-
|
29
|
-
Thread.stop rescue ""
|
30
|
-
Thread.current[:callee] = task
|
31
|
-
a.call args
|
32
|
-
end
|
33
|
-
tasks << thread
|
26
|
+
tasks << a
|
34
27
|
end
|
35
28
|
alias_method :push, :<<
|
36
29
|
# In the ThreadSafeInstance
|
@@ -45,7 +38,7 @@ module PoolParty
|
|
45
38
|
end
|
46
39
|
# Add a task to the new threaded block
|
47
40
|
def add_task(&blk)
|
48
|
-
_tasker.push
|
41
|
+
_tasker.push blk
|
49
42
|
end
|
50
43
|
# Grab the polling_time
|
51
44
|
def interval
|
@@ -74,16 +67,17 @@ module PoolParty
|
|
74
67
|
end
|
75
68
|
# Run the loop and wait the amount of time between running the tasks
|
76
69
|
# You can send it daemonize => true and it will daemonize
|
77
|
-
def run_thread_loop(opts={}, &
|
70
|
+
def run_thread_loop(opts={}, &blk)
|
78
71
|
block = lambda {
|
79
72
|
loop do
|
80
73
|
begin
|
81
74
|
yield if block_given?
|
75
|
+
add_task { Signal.trap("INT") { exit } }
|
82
76
|
run_thread_list
|
77
|
+
PoolParty.message "Waiting: #{interval}"
|
83
78
|
wait interval
|
84
|
-
reset!
|
85
79
|
rescue Exception => e
|
86
|
-
|
80
|
+
Process.kill("INT", Process.pid)
|
87
81
|
end
|
88
82
|
end
|
89
83
|
}
|
@@ -94,10 +88,6 @@ module PoolParty
|
|
94
88
|
def run_thread_list
|
95
89
|
run_threads
|
96
90
|
end
|
97
|
-
# Reset
|
98
|
-
def reset!
|
99
|
-
cached_variables.each {|cached| cached = nil }
|
100
|
-
end
|
101
91
|
|
102
92
|
end
|
103
93
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module PoolParty
|
2
|
+
class ThreadPool
|
3
|
+
class Worker
|
4
|
+
def initialize
|
5
|
+
@mutex = Mutex.new
|
6
|
+
@thread = Thread.new do
|
7
|
+
while true
|
8
|
+
sleep 0.001
|
9
|
+
block = get_block
|
10
|
+
if block
|
11
|
+
block.call
|
12
|
+
reset_block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_block
|
19
|
+
@mutex.synchronize {@block}
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_block(block)
|
23
|
+
@mutex.synchronize do
|
24
|
+
raise RuntimeError, "Thread already busy." if @block
|
25
|
+
@block = block
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def reset_block
|
30
|
+
@mutex.synchronize {@block = nil}
|
31
|
+
end
|
32
|
+
|
33
|
+
def busy?
|
34
|
+
@mutex.synchronize {!@block.nil?}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :max_size
|
39
|
+
attr_reader :workers
|
40
|
+
|
41
|
+
def initialize(max_size = 10)
|
42
|
+
@max_size = max_size
|
43
|
+
@workers = []
|
44
|
+
@mutex = Mutex.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def size
|
48
|
+
@mutex.synchronize {@workers.size}
|
49
|
+
end
|
50
|
+
|
51
|
+
def busy?
|
52
|
+
@mutex.synchronize {@workers.any? {|w| w.busy?}}
|
53
|
+
end
|
54
|
+
|
55
|
+
def join
|
56
|
+
sleep 0.01 while busy?
|
57
|
+
end
|
58
|
+
|
59
|
+
def process(&block)
|
60
|
+
while true
|
61
|
+
@mutex.synchronize do
|
62
|
+
worker = find_available_worker
|
63
|
+
if worker
|
64
|
+
return worker.set_block(block)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
sleep 0.01
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_available_worker
|
72
|
+
free_worker || create_worker
|
73
|
+
end
|
74
|
+
|
75
|
+
def wait_for_worker
|
76
|
+
while true
|
77
|
+
worker = find_available_worker
|
78
|
+
return worker if worker
|
79
|
+
sleep 0.01
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def free_worker
|
84
|
+
@workers.each {|w| return w unless w.busy?}; nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_worker
|
88
|
+
return nil if @workers.size >= @max_size
|
89
|
+
worker = Worker.new
|
90
|
+
@workers << worker
|
91
|
+
worker
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/poolparty.gemspec
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = %q{poolparty}
|
3
|
-
s.version = "0.0
|
3
|
+
s.version = "0.1.0"
|
4
4
|
|
5
5
|
s.required_rubygems_version = Gem::Requirement.new("= 1.2") if s.respond_to? :required_rubygems_version=
|
6
6
|
s.authors = ["Ari Lerner"]
|
7
7
|
s.cert_chain = nil
|
8
|
-
s.date = %q{2008-
|
8
|
+
s.date = %q{2008-07-02}
|
9
9
|
s.description = %q{Run your entire application off EC2, managed and auto-scaling}
|
10
10
|
s.email = %q{ari.lerner@citrusbyte.com}
|
11
11
|
s.executables = ["instance", "pool", "poolnotify"]
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "README.txt", "bin", "bin/instance", "bin/pool", "bin/poolnotify", "lib", "lib/core", "lib/core/array.rb", "lib/core/exception.rb", "lib/core/float.rb", "lib/core/hash.rb", "lib/core/kernel.rb", "lib/core/module.rb", "lib/core/object.rb", "lib/core/proc.rb", "lib/core/string.rb", "lib/core/time.rb", "lib/modules", "lib/modules/callback.rb", "lib/modules/ec2_wrapper.rb", "lib/modules/file_writer.rb", "lib/modules/safe_instance.rb", "lib/modules/sprinkle_overrides.rb", "lib/modules/vlad_override.rb", "lib/poolparty", "lib/poolparty.rb", "lib/poolparty/application.rb", "lib/poolparty/init.rb", "lib/poolparty/master.rb", "lib/poolparty/monitors", "lib/poolparty/monitors.rb", "lib/poolparty/monitors/cpu.rb", "lib/poolparty/monitors/memory.rb", "lib/poolparty/monitors/web.rb", "lib/poolparty/optioner.rb", "lib/poolparty/plugin.rb", "lib/poolparty/plugin_manager.rb", "lib/poolparty/provider", "lib/poolparty/provider.rb", "lib/poolparty/provider/packages", "lib/poolparty/provider/packages/essential.rb", "lib/poolparty/provider/packages/git.rb", "lib/poolparty/provider/packages/haproxy.rb", "lib/poolparty/provider/packages/heartbeat.rb", "lib/poolparty/provider/packages/monit.rb", "lib/poolparty/provider/packages/rsync.rb", "lib/poolparty/provider/packages/ruby.rb", "lib/poolparty/provider/packages/s3fuse.rb", "lib/poolparty/provider/provider.rb", "lib/poolparty/remote_instance.rb", "lib/poolparty/remoter.rb", "lib/poolparty/remoting.rb", "lib/poolparty/scheduler.rb", "lib/poolparty/tasks", "lib/poolparty/tasks.rb", "lib/poolparty/tasks/cloud.rake", "lib/poolparty/tasks/development.rake", "lib/poolparty/tasks/ec2.rake", "lib/poolparty/tasks/instance.rake", "lib/poolparty/tasks/
|
13
|
-
s.files = ["CHANGELOG", "README.txt", "Rakefile", "assets", "assets/clouds.png", "bin", "bin/instance", "bin/pool", "bin/poolnotify", "config", "config/cloud_master_takeover", "config/create_proxy_ami.sh", "config/haproxy.conf", "config/heartbeat.conf", "config/heartbeat_authkeys.conf", "config/installers", "config/installers/ubuntu_install.sh", "config/monit", "config/monit.conf", "config/monit/haproxy.monit.conf", "config/monit/nginx.monit.conf", "config/nginx.conf", "config/reconfigure_instances_script.sh", "config/sample-config.yml", "config/scp_instances_script.sh", "lib", "lib/core", "lib/core/array.rb", "lib/core/exception.rb", "lib/core/float.rb", "lib/core/hash.rb", "lib/core/kernel.rb", "lib/core/module.rb", "lib/core/object.rb", "lib/core/proc.rb", "lib/core/string.rb", "lib/core/time.rb", "lib/modules", "lib/modules/callback.rb", "lib/modules/ec2_wrapper.rb", "lib/modules/file_writer.rb", "lib/modules/safe_instance.rb", "lib/modules/sprinkle_overrides.rb", "lib/modules/vlad_override.rb", "lib/poolparty", "lib/poolparty.rb", "lib/poolparty/application.rb", "lib/poolparty/init.rb", "lib/poolparty/master.rb", "lib/poolparty/monitors", "lib/poolparty/monitors.rb", "lib/poolparty/monitors/cpu.rb", "lib/poolparty/monitors/memory.rb", "lib/poolparty/monitors/web.rb", "lib/poolparty/optioner.rb", "lib/poolparty/plugin.rb", "lib/poolparty/plugin_manager.rb", "lib/poolparty/provider", "lib/poolparty/provider.rb", "lib/poolparty/provider/packages", "lib/poolparty/provider/packages/essential.rb", "lib/poolparty/provider/packages/git.rb", "lib/poolparty/provider/packages/haproxy.rb", "lib/poolparty/provider/packages/heartbeat.rb", "lib/poolparty/provider/packages/monit.rb", "lib/poolparty/provider/packages/rsync.rb", "lib/poolparty/provider/packages/ruby.rb", "lib/poolparty/provider/packages/s3fuse.rb", "lib/poolparty/provider/provider.rb", "lib/poolparty/remote_instance.rb", "lib/poolparty/remoter.rb", "lib/poolparty/remoting.rb", "lib/poolparty/scheduler.rb", "lib/poolparty/tasks", "lib/poolparty/tasks.rb", "lib/poolparty/tasks/cloud.rake", "lib/poolparty/tasks/development.rake", "lib/poolparty/tasks/ec2.rake", "lib/poolparty/tasks/instance.rake", "lib/poolparty/tasks/
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.txt", "bin", "bin/instance", "bin/pool", "bin/poolnotify", "lib", "lib/core", "lib/core/array.rb", "lib/core/exception.rb", "lib/core/float.rb", "lib/core/hash.rb", "lib/core/kernel.rb", "lib/core/module.rb", "lib/core/object.rb", "lib/core/proc.rb", "lib/core/string.rb", "lib/core/time.rb", "lib/helpers", "lib/helpers/plugin_spec_helper.rb", "lib/modules", "lib/modules/callback.rb", "lib/modules/ec2_wrapper.rb", "lib/modules/file_writer.rb", "lib/modules/safe_instance.rb", "lib/modules/sprinkle_overrides.rb", "lib/modules/vlad_override.rb", "lib/poolparty", "lib/poolparty.rb", "lib/poolparty/application.rb", "lib/poolparty/init.rb", "lib/poolparty/master.rb", "lib/poolparty/monitors", "lib/poolparty/monitors.rb", "lib/poolparty/monitors/cpu.rb", "lib/poolparty/monitors/memory.rb", "lib/poolparty/monitors/web.rb", "lib/poolparty/optioner.rb", "lib/poolparty/plugin.rb", "lib/poolparty/plugin_manager.rb", "lib/poolparty/provider", "lib/poolparty/provider.rb", "lib/poolparty/provider/packages", "lib/poolparty/provider/packages/essential.rb", "lib/poolparty/provider/packages/git.rb", "lib/poolparty/provider/packages/haproxy.rb", "lib/poolparty/provider/packages/heartbeat.rb", "lib/poolparty/provider/packages/monit.rb", "lib/poolparty/provider/packages/rsync.rb", "lib/poolparty/provider/packages/ruby.rb", "lib/poolparty/provider/packages/s3fuse.rb", "lib/poolparty/provider/provider.rb", "lib/poolparty/remote_instance.rb", "lib/poolparty/remoter.rb", "lib/poolparty/remoting.rb", "lib/poolparty/scheduler.rb", "lib/poolparty/tasks", "lib/poolparty/tasks.rb", "lib/poolparty/tasks/cloud.rake", "lib/poolparty/tasks/development.rake", "lib/poolparty/tasks/ec2.rake", "lib/poolparty/tasks/instance.rake", "lib/poolparty/tasks/plugins.rake", "lib/poolparty/tasks/server.rake", "lib/poolparty/thread_pool.rb", "lib/s3", "lib/s3/s3_object_store_folders.rb"]
|
13
|
+
s.files = ["CHANGELOG", "README.txt", "Rakefile", "assets", "assets/clouds.png", "bin", "bin/instance", "bin/pool", "bin/poolnotify", "config", "config/cloud_master_takeover", "config/create_proxy_ami.sh", "config/haproxy.conf", "config/heartbeat.conf", "config/heartbeat_authkeys.conf", "config/installers", "config/installers/ubuntu_install.sh", "config/monit", "config/monit.conf", "config/monit/haproxy.monit.conf", "config/monit/nginx.monit.conf", "config/nginx.conf", "config/reconfigure_instances_script.sh", "config/sample-config.yml", "config/scp_instances_script.sh", "lib", "lib/core", "lib/core/array.rb", "lib/core/exception.rb", "lib/core/float.rb", "lib/core/hash.rb", "lib/core/kernel.rb", "lib/core/module.rb", "lib/core/object.rb", "lib/core/proc.rb", "lib/core/string.rb", "lib/core/time.rb", "lib/helpers", "lib/helpers/plugin_spec_helper.rb", "lib/modules", "lib/modules/callback.rb", "lib/modules/ec2_wrapper.rb", "lib/modules/file_writer.rb", "lib/modules/safe_instance.rb", "lib/modules/sprinkle_overrides.rb", "lib/modules/vlad_override.rb", "lib/poolparty", "lib/poolparty.rb", "lib/poolparty/application.rb", "lib/poolparty/init.rb", "lib/poolparty/master.rb", "lib/poolparty/monitors", "lib/poolparty/monitors.rb", "lib/poolparty/monitors/cpu.rb", "lib/poolparty/monitors/memory.rb", "lib/poolparty/monitors/web.rb", "lib/poolparty/optioner.rb", "lib/poolparty/plugin.rb", "lib/poolparty/plugin_manager.rb", "lib/poolparty/provider", "lib/poolparty/provider.rb", "lib/poolparty/provider/packages", "lib/poolparty/provider/packages/essential.rb", "lib/poolparty/provider/packages/git.rb", "lib/poolparty/provider/packages/haproxy.rb", "lib/poolparty/provider/packages/heartbeat.rb", "lib/poolparty/provider/packages/monit.rb", "lib/poolparty/provider/packages/rsync.rb", "lib/poolparty/provider/packages/ruby.rb", "lib/poolparty/provider/packages/s3fuse.rb", "lib/poolparty/provider/provider.rb", "lib/poolparty/remote_instance.rb", "lib/poolparty/remoter.rb", "lib/poolparty/remoting.rb", "lib/poolparty/scheduler.rb", "lib/poolparty/tasks", "lib/poolparty/tasks.rb", "lib/poolparty/tasks/cloud.rake", "lib/poolparty/tasks/development.rake", "lib/poolparty/tasks/ec2.rake", "lib/poolparty/tasks/instance.rake", "lib/poolparty/tasks/plugins.rake", "lib/poolparty/tasks/server.rake", "lib/poolparty/thread_pool.rb", "lib/s3", "lib/s3/s3_object_store_folders.rb", "spec", "spec/application_spec.rb", "spec/callback_spec.rb", "spec/core_spec.rb", "spec/ec2_wrapper_spec.rb", "spec/file_writer_spec.rb", "spec/files", "spec/files/describe_response", "spec/files/multi_describe_response", "spec/files/remote_desc_response", "spec/helpers", "spec/helpers/ec2_mock.rb", "spec/kernel_spec.rb", "spec/master_spec.rb", "spec/monitors", "spec/monitors/cpu_monitor_spec.rb", "spec/monitors/memory_spec.rb", "spec/monitors/misc_monitor_spec.rb", "spec/monitors/web_spec.rb", "spec/optioner_spec.rb", "spec/plugin_manager_spec.rb", "spec/plugin_spec.rb", "spec/pool_binary_spec.rb", "spec/poolparty_spec.rb", "spec/provider_spec.rb", "spec/remote_instance_spec.rb", "spec/remoter_spec.rb", "spec/remoting_spec.rb", "spec/scheduler_spec.rb", "spec/spec_helper.rb", "spec/string_spec.rb", "poolparty.gemspec"]
|
14
14
|
s.has_rdoc = true
|
15
|
-
s.homepage = %q{http://
|
15
|
+
s.homepage = %q{http://poolpartyrb.com}
|
16
16
|
s.post_install_message = %q{
|
17
17
|
|
18
|
-
Get ready to jump in the pool, you just installed PoolParty! (Updated at
|
18
|
+
Get ready to jump in the pool, you just installed PoolParty! (Updated at 02:12PM, 07/02/08)
|
19
19
|
|
20
20
|
Please check out the documentation for any questions or check out the google groups at
|
21
21
|
http://groups.google.com/group/poolpartyrb
|
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
|
|
45
45
|
s.add_runtime_dependency(%q<git>, [">= 0"])
|
46
46
|
s.add_runtime_dependency(%q<crafterm-sprinkle>, [">= 0"])
|
47
47
|
s.add_runtime_dependency(%q<SystemTimer>, [">= 0"])
|
48
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
48
49
|
else
|
49
50
|
s.add_dependency(%q<aws-s3>, [">= 0"])
|
50
51
|
s.add_dependency(%q<amazon-ec2>, [">= 0"])
|
@@ -52,6 +53,7 @@ Gem::Specification.new do |s|
|
|
52
53
|
s.add_dependency(%q<git>, [">= 0"])
|
53
54
|
s.add_dependency(%q<crafterm-sprinkle>, [">= 0"])
|
54
55
|
s.add_dependency(%q<SystemTimer>, [">= 0"])
|
56
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
55
57
|
end
|
56
58
|
else
|
57
59
|
s.add_dependency(%q<aws-s3>, [">= 0"])
|
@@ -60,5 +62,6 @@ Gem::Specification.new do |s|
|
|
60
62
|
s.add_dependency(%q<git>, [">= 0"])
|
61
63
|
s.add_dependency(%q<crafterm-sprinkle>, [">= 0"])
|
62
64
|
s.add_dependency(%q<SystemTimer>, [">= 0"])
|
65
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
63
66
|
end
|
64
67
|
end
|
data/spec/application_spec.rb
CHANGED
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/spec_helper'
|
|
3
3
|
describe "Application" do
|
4
4
|
before(:each) do
|
5
5
|
stub_option_load
|
6
|
+
Application.reset!
|
6
7
|
end
|
7
8
|
it "should be able to send options in the Application.options" do
|
8
9
|
options({:optparse => {:banner => "hi"}})
|
@@ -39,29 +40,47 @@ describe "Application" do
|
|
39
40
|
it "should show the version as a string" do
|
40
41
|
Application.version.class.should == String
|
41
42
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
describe "User data" do
|
44
|
+
before(:each) do
|
45
|
+
@str = ":access_key: 3.14159\n:secret_access_key: pi"
|
46
|
+
Application.options = nil
|
47
|
+
Application.stub!(:open).with("http://169.254.169.254/latest/user-data").and_return(@str)
|
48
|
+
@str.stub!(:read).and_return ":access_key: 3.14159\n:secret_access_key: pi"
|
49
|
+
Application.default_options.stub!(:merge!).with({})
|
50
|
+
Application.default_options.stub!(:merge!).with({:access_key => 3.14159, :secret_access_key => "pi"})
|
51
|
+
end
|
52
|
+
it "should try to load the user data into a yaml hash" do
|
53
|
+
YAML.should_receive(:load).with(":access_key: 3.14159\n:secret_access_key: pi")
|
54
|
+
Application.local_user_data
|
55
|
+
end
|
56
|
+
it "should be able to start instances with the the key access information on the user-data" do
|
57
|
+
Application.launching_user_data.should =~ /:access_key/
|
58
|
+
Application.launching_user_data.should =~ /:secret_access_key/
|
59
|
+
end
|
60
|
+
it "should be able to pull out the access_key from the user data" do
|
61
|
+
Application.local_user_data[:access_key].should == 3.14159
|
62
|
+
end
|
63
|
+
it "should be able tp pull out the secret_access_key from the user-data" do
|
64
|
+
Application.local_user_data[:secret_access_key].should == "pi"
|
65
|
+
end
|
66
|
+
it "should overwrite the default_options when passing in to the instance data" do
|
67
|
+
Application.stub!(:default_options).and_return({:access_key => 42})
|
68
|
+
Application.local_user_data
|
69
|
+
Application.options.access_key.should == 3.14159
|
70
|
+
end
|
52
71
|
end
|
53
72
|
it "should parse and use a config file if it is given for the options" do
|
54
|
-
YAML.should_receive(:load).and_return({:config_file => "config/sample-config.yml"})
|
73
|
+
YAML.should_receive(:load).at_least(1).and_return({:config_file => "config/sample-config.yml"})
|
55
74
|
Application.make_options(:config_file => "config/sample-config.yml")
|
56
75
|
end
|
57
76
|
it "should not read the config file if it is not passed and doesn't exist" do
|
58
77
|
File.stub!(:file?).and_return false
|
59
|
-
YAML.should_not_receive(:load)
|
78
|
+
YAML.should_not_receive(:load).with("config/config.yml")
|
60
79
|
Application.make_options
|
61
80
|
end
|
62
81
|
it "should not read the config file if it is passed and doesn't exist" do
|
63
82
|
File.stub!(:file?).and_return false
|
64
|
-
YAML.should_not_receive(:load)
|
83
|
+
YAML.should_not_receive(:load).with("config/config.yml")
|
65
84
|
Application.make_options(:config_file => "ted")
|
66
85
|
end
|
67
86
|
end
|
data/spec/callback_spec.rb
CHANGED
@@ -68,7 +68,7 @@ describe "Multiple callbacks" do
|
|
68
68
|
end
|
69
69
|
class OutsideClass
|
70
70
|
def self.hello(caller)
|
71
|
-
|
71
|
+
"hello"
|
72
72
|
end
|
73
73
|
end
|
74
74
|
class TestOutsideClass
|
@@ -191,4 +191,23 @@ describe "Variables on the plugin callbacker class" do
|
|
191
191
|
BindingClass.new.print
|
192
192
|
BindingClass.new.methods.include?("eviloutsideclass").should == true
|
193
193
|
end
|
194
|
+
end
|
195
|
+
class DoubleClass
|
196
|
+
include Callbacks
|
197
|
+
before :print, :hello => "OutsideBindingClass"
|
198
|
+
after :print, :hello => "OutsideBindingClass"
|
199
|
+
|
200
|
+
def print
|
201
|
+
string
|
202
|
+
end
|
203
|
+
def string
|
204
|
+
@string ||= ""
|
205
|
+
end
|
206
|
+
end
|
207
|
+
describe "Chaining" do
|
208
|
+
it "should be able to call both a before and an after spec" do
|
209
|
+
@d = DoubleClass.new
|
210
|
+
@d.print
|
211
|
+
@d.string.should == "hellohello"
|
212
|
+
end
|
194
213
|
end
|
data/spec/file_writer_spec.rb
CHANGED
data/spec/kernel_spec.rb
CHANGED
@@ -8,4 +8,17 @@ describe "Kernel extensions" do
|
|
8
8
|
@host.should_receive(:sleep).once.and_return true
|
9
9
|
@host.wait "10.seconds"
|
10
10
|
end
|
11
|
+
end
|
12
|
+
describe "Object extensions" do
|
13
|
+
before(:each) do
|
14
|
+
@klass = Object.new
|
15
|
+
@klass.instance_eval <<-EOE
|
16
|
+
def hello
|
17
|
+
puts "hello"
|
18
|
+
end
|
19
|
+
EOE
|
20
|
+
end
|
21
|
+
it "should be able to get a list of the defined methods on the object" do
|
22
|
+
@klass.my_methods.should == ["hello"]
|
23
|
+
end
|
11
24
|
end
|
data/spec/master_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/helpers/ec2_mock'
|
2
3
|
|
3
4
|
describe "Master" do
|
4
5
|
before(:each) do
|
@@ -86,22 +87,25 @@ describe "Master" do
|
|
86
87
|
it "should be able to get a specific node in the nodes from the master" do
|
87
88
|
@master.get_node(2).instance_id.should == "i-5849bc"
|
88
89
|
end
|
90
|
+
it "should be able to get the next node" do
|
91
|
+
@master.get_next_node(@instance).instance_id.should == "i-5849bb"
|
92
|
+
end
|
89
93
|
it "should be able to build a hosts file" do
|
90
94
|
open(@master.build_hosts_file_for(@instance).path).read.should == "127.0.0.1 node0\n127.0.0.1 localhost.localdomain localhost ubuntu\n127.0.0.2 node1\n127.0.0.3 node2"
|
91
95
|
end
|
92
96
|
it "should be able to build a hosts file for a specific instance" do
|
93
|
-
open(@master.build_hosts_file_for(@instance).path).read.should =~
|
97
|
+
open(@master.build_hosts_file_for(@instance).path).read.should =~ /127\.0\.0\.1 node0/
|
94
98
|
end
|
95
99
|
it "should be able to build a haproxy file" do
|
96
|
-
open(@master.build_haproxy_file.path).read.should =~
|
100
|
+
open(@master.build_haproxy_file.path).read.should =~ /server node0 127\.0\.0\.1:#{Application.client_port}/
|
97
101
|
end
|
98
102
|
it "should be able to reconfigure the instances (working on two files a piece)" do
|
99
103
|
@master.should_receive(:remote_configure_instances).and_return true
|
100
104
|
@master.stub!(:number_of_unconfigured_nodes).and_return 1
|
101
105
|
@master.reconfigure_cloud_when_necessary
|
102
106
|
end
|
103
|
-
it "should return the number of unconfigured nodes when asked" do
|
104
|
-
@master.nodes.each {|node| node.stub!(:stack_installed?).and_return(
|
107
|
+
it "should return the number of unconfigured nodes when asked" do
|
108
|
+
@master.nodes.each {|node| node.stub!(:stack_installed?).and_return(node.master? ? false : true) }
|
105
109
|
@master.number_of_unconfigured_nodes.should == 1
|
106
110
|
end
|
107
111
|
it "should be able to return the size of the cloud" do
|
@@ -118,39 +122,50 @@ describe "Master" do
|
|
118
122
|
describe "sending configuration files" do
|
119
123
|
before(:each) do
|
120
124
|
Master.stub!(:new).and_return(@master)
|
125
|
+
@master.stub!(:ssh)
|
126
|
+
@master.stub!(:scp)
|
127
|
+
@master.nodes.each do |node|
|
128
|
+
node.stub!(:ssh)
|
129
|
+
node.stub!(:scp)
|
130
|
+
node.stub!(:stack_installed?).and_return true
|
131
|
+
end
|
121
132
|
end
|
122
133
|
it "should be able to build a heartbeat resources file for the specific node" do
|
123
|
-
open(
|
134
|
+
open(@master.build_heartbeat_resources_file_for(@master.nodes.first).path).read.should == "node0 127.0.0.1\nnode1 127.0.0.2"
|
124
135
|
end
|
125
136
|
it "should be able to build a heartbeat config file" do
|
126
|
-
open(
|
137
|
+
open(@master.build_heartbeat_config_file_for(@master.nodes.first).path).read.should =~ /\nnode node0\nnode node1/
|
127
138
|
end
|
128
139
|
it "should be able to say if heartbeat is necessary with more than 1 server or not" do
|
129
140
|
Master.requires_heartbeat?.should == true
|
130
141
|
end
|
131
142
|
it "should be able to say that heartbeat is not necessary if there is 1 server" do
|
132
|
-
@master.stub!(:
|
143
|
+
@master.stub!(:nodes).and_return([
|
133
144
|
{:instance_id => "i-5849ba", :ip => "127.0.0.1", :status => "running"}
|
134
145
|
])
|
135
146
|
Master.requires_heartbeat?.should == false
|
136
147
|
end
|
137
148
|
it "should only install the stack on nodes that don't have it marked locally as installed" do
|
138
|
-
@master.nodes.each {|i| i.should_receive(:stack_installed?).and_return(true)}
|
149
|
+
@master.nodes.each {|i| i.should_receive(:stack_installed?).at_least(1).and_return(true)}
|
139
150
|
@master.should_not_receive(:reconfigure_running_instances)
|
140
151
|
@master.reconfigure_cloud_when_necessary
|
141
152
|
end
|
142
153
|
it "should install the stack on all the nodes (because it needs reconfiguring) if there is any node that needs the stack" do
|
143
|
-
@master.nodes.first.should_receive(:stack_installed?).and_return(false)
|
154
|
+
@master.nodes.first.should_receive(:stack_installed?).at_least(1).and_return(false)
|
144
155
|
@master.should_receive(:configure_cloud).once.and_return(true)
|
145
156
|
@master.reconfigure_cloud_when_necessary
|
146
157
|
end
|
147
158
|
describe "rsync'ing the files to the instances" do
|
159
|
+
it "should cleanup the tmp directory before sending configuration to the nodes" do
|
160
|
+
@master.should_receive(:cleanup_tmp_directory).once
|
161
|
+
@master.build_and_send_config_files_in_temp_directory
|
162
|
+
end
|
148
163
|
it "should receive send_config_files_to_nodes after it builds the config files in the temp directory" do
|
149
|
-
@master.should_receive(:send_config_files_to_nodes).
|
164
|
+
@master.should_receive(:send_config_files_to_nodes).at_least(1)
|
150
165
|
@master.build_and_send_config_files_in_temp_directory
|
151
166
|
end
|
152
167
|
it "should run_array_of_tasks(scp_tasks)" do
|
153
|
-
@master.should_receive(:run_array_of_tasks).and_return true
|
168
|
+
@master.should_receive(:run_array_of_tasks).at_least(1).and_return true
|
154
169
|
@master.build_and_send_config_files_in_temp_directory
|
155
170
|
end
|
156
171
|
it "should compile a list of files to rsync" do
|
@@ -184,14 +199,18 @@ describe "Master" do
|
|
184
199
|
before(:each) do
|
185
200
|
Application.stub!(:install_on_load?).and_return true
|
186
201
|
Sprinkle::Script.stub!(:sprinkle).and_return true
|
187
|
-
@master.stub!(:
|
202
|
+
@master.stub!(:ssh).and_return true
|
203
|
+
@master.nodes.each do |node|
|
204
|
+
node.stub!(:run_now).and_return true
|
205
|
+
end
|
188
206
|
end
|
189
207
|
it "should install on the instances if the application says it should" do
|
208
|
+
Provider.stub!(:install_userpackages)
|
190
209
|
Provider.should_receive(:install_poolparty)
|
191
210
|
@master.install_cloud
|
192
211
|
end
|
193
212
|
it "should execute the remote tasks on all of the instances" do
|
194
|
-
@master.should_receive(:
|
213
|
+
@master.should_receive(:ssh).and_return true
|
195
214
|
@master.install_cloud
|
196
215
|
end
|
197
216
|
describe "stubbing installation" do
|
@@ -244,30 +263,35 @@ describe "Master" do
|
|
244
263
|
@master.should_receive(:request_termination_of_instance).and_return(true)
|
245
264
|
@master.terminate_instance_if_load_is_low
|
246
265
|
end
|
266
|
+
it "should launch the minimum_instances when the minimum aren't launched"
|
267
|
+
it "should reconfigure the cloud if it's necessary to do so"
|
268
|
+
it "should try to scale the cloud when monitoring"
|
269
|
+
it "should check the stats of the cloud"
|
247
270
|
end
|
248
|
-
describe "expanding and contracting" do
|
271
|
+
describe "expanding and contracting" do
|
249
272
|
it "should be able to say that it should not contract" do
|
250
273
|
@master.stub!(:web).and_return(10.2)
|
251
274
|
@master.stub!(:cpu).and_return(0.32)
|
252
275
|
|
253
276
|
@master.contract?.should == false
|
254
277
|
end
|
255
|
-
it "should be able to say that it should contract" do
|
256
|
-
@master.
|
257
|
-
@master.
|
258
|
-
|
278
|
+
it "should be able to say that it should contract" do
|
279
|
+
@master.should_receive(:cpu).once.and_return(0.05)
|
280
|
+
@master.should_receive(:web).once.and_return(35.2)
|
281
|
+
|
259
282
|
@master.contract?.should == true
|
260
283
|
end
|
261
284
|
it "should be able to say that it should not expand if it shouldn't expand" do
|
262
285
|
@master.stub!(:web).and_return(30.2)
|
263
286
|
@master.stub!(:cpu).and_return(0.92)
|
264
|
-
|
287
|
+
|
265
288
|
@master.expand?.should == false
|
266
289
|
end
|
267
290
|
it "should be able to say that it should expand if it should expand" do
|
268
291
|
@master.stub!(:web).and_return(1.2)
|
269
292
|
@master.stub!(:cpu).and_return(0.92)
|
270
|
-
|
293
|
+
|
294
|
+
@master.should_receive(:web).once.and_return(1.2)
|
271
295
|
@master.expand?.should == true
|
272
296
|
end
|
273
297
|
describe "scaling" do
|
@@ -313,6 +337,12 @@ describe "Master" do
|
|
313
337
|
File.should_receive(:copy).exactly(3).and_return true
|
314
338
|
@master.build_and_send_config_files_in_temp_directory
|
315
339
|
end
|
340
|
+
it "should tar the plugin_dir into the tmp directory" do
|
341
|
+
FileUtils.mkdir_p Application.plugin_dir rescue ""
|
342
|
+
|
343
|
+
Kernel.should_receive(:system).with("tar -czf #{@master.base_tmp_dir}/plugins.tar.gz #{File.basename(Application.plugin_dir)}").and_return true
|
344
|
+
@master.build_and_send_config_files_in_temp_directory
|
345
|
+
end
|
316
346
|
describe "get configs" do
|
317
347
|
before(:each) do
|
318
348
|
@master.stub!(:user_dir).and_return("user")
|