bluepill 0.0.51 → 0.0.52
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -4
- data/.rspec +1 -0
- data/Gemfile +6 -0
- data/README.md +46 -0
- data/Rakefile +29 -0
- data/bin/bluepill +17 -4
- data/bluepill.gemspec +8 -1
- data/lib/bluepill/application.rb +1 -1
- data/lib/bluepill/dsl/process_factory.rb +35 -0
- data/lib/bluepill/process.rb +41 -2
- data/lib/bluepill/process_statistics.rb +8 -4
- data/lib/bluepill/socket.rb +19 -8
- data/lib/bluepill/system.rb +11 -3
- data/lib/bluepill/version.rb +1 -1
- data/spec/lib/bluepill/logger_spec.rb +3 -0
- data/spec/lib/bluepill/process_statistics_spec.rb +24 -0
- data/spec/lib/bluepill/system_spec.rb +36 -0
- data/spec/spec_helper.rb +19 -0
- metadata +111 -12
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-r ./spec/spec_helper.rb -c -f progress
|
data/Gemfile
CHANGED
@@ -2,3 +2,9 @@ source :rubygems
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in bluepill.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
# YARD helper for ruby 1.8 (already embedded into ruby 1.9)
|
7
|
+
gem "ripper", :platforms => :ruby_18, :group => :development
|
8
|
+
|
9
|
+
# Code coverage tool that works on Ruby 1.9
|
10
|
+
gem "simplecov", ">= 0.4.0", :platforms => :ruby_19, :group => :test
|
data/README.md
CHANGED
@@ -119,6 +119,23 @@ If you want to run the process as someone other than root:
|
|
119
119
|
end
|
120
120
|
```
|
121
121
|
|
122
|
+
If you want to include one or more supplementary groups:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
Bluepill.application("app_name") do |app|
|
126
|
+
app.process("process_name") do |process|
|
127
|
+
process.start_command = "/usr/bin/some_start_command"
|
128
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
129
|
+
process.uid = "deploy"
|
130
|
+
process.gid = "deploy"
|
131
|
+
process.supplementary_groups = ['rvm']
|
132
|
+
|
133
|
+
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
134
|
+
process.checks :mem_usage, :every => 10.seconds, :below => 100.megabytes, :times => [3,5]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
122
139
|
You can also set an app-wide uid/gid:
|
123
140
|
|
124
141
|
```ruby
|
@@ -164,6 +181,35 @@ You can also have an app-wide working directory:
|
|
164
181
|
|
165
182
|
Note: We also set the PWD in the environment to the working dir you specify. This is useful for when the working dir is a symlink. Unicorn in particular will cd into the environment variable in PWD when it re-execs to deal with a change in the symlink.
|
166
183
|
|
184
|
+
By default, bluepill will send a SIGTERM to your process when stopping.
|
185
|
+
To change the stop command:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
Bluepill.application("app_name") do |app|
|
189
|
+
app.process("process_name") do |process|
|
190
|
+
process.start_command = "/usr/bin/some_start_command"
|
191
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
192
|
+
process.stop_command = "/user/bin/some_stop_command"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
If you'd like to send a signal or signals to your process to stop it:
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
Bluepill.application("app_name") do |app|
|
201
|
+
app.process("process_name") do |process|
|
202
|
+
process.start_command = "/usr/bin/some_start_command"
|
203
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
204
|
+
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
```
|
208
|
+
|
209
|
+
We added a line that will send a SIGQUIT, wait 30 seconds and check to
|
210
|
+
see if the process is still up, send a SIGTERM, wait 5 seconds and check
|
211
|
+
to see if the process is still up, and finally send a SIGKILL.
|
212
|
+
|
167
213
|
And lastly, to monitor child processes:
|
168
214
|
|
169
215
|
```ruby
|
data/Rakefile
CHANGED
@@ -7,3 +7,32 @@ rescue LoadError
|
|
7
7
|
$stderr.puts "Bundler not installed. You should install it with: gem install bundler"
|
8
8
|
end
|
9
9
|
|
10
|
+
$LOAD_PATH << File.expand_path('./lib', File.dirname(__FILE__))
|
11
|
+
require 'bluepill/version'
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'rspec/core/rake_task'
|
15
|
+
|
16
|
+
RSpec::Core::RakeTask.new
|
17
|
+
|
18
|
+
if RUBY_VERSION >= '1.9'
|
19
|
+
RSpec::Core::RakeTask.new(:cov) do |t|
|
20
|
+
ENV['ENABLE_SIMPLECOV'] = '1'
|
21
|
+
t.ruby_opts = '-w'
|
22
|
+
t.rcov_opts = %q[-Ilib --exclude "spec/*,gems/*"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
rescue LoadError
|
26
|
+
$stderr.puts "RSpec not available. Install it with: gem install rspec-core rspec-expectations rr faker"
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'yard'
|
31
|
+
YARD::Rake::YardocTask.new do |yard|
|
32
|
+
yard.options << "--title='bluepill #{Bluepill::VERSION}'"
|
33
|
+
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
$stderr.puts "Please install YARD with: gem install yard"
|
37
|
+
end
|
38
|
+
|
data/bin/bluepill
CHANGED
@@ -2,11 +2,20 @@
|
|
2
2
|
require 'optparse'
|
3
3
|
require 'bluepill'
|
4
4
|
|
5
|
+
begin
|
6
|
+
require 'rbconfig'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
10
|
+
RbConfig = Config unless Object.const_defined?(:RbConfig)
|
11
|
+
|
5
12
|
# Default options
|
6
13
|
options = {
|
7
14
|
:log_file => "/var/log/bluepill.log",
|
8
|
-
:base_dir => "/var/bluepill",
|
9
|
-
:privileged => true
|
15
|
+
:base_dir => "/var/run/bluepill",
|
16
|
+
:privileged => true,
|
17
|
+
:timeout => 10,
|
18
|
+
:attempts => 1
|
10
19
|
}
|
11
20
|
|
12
21
|
OptionParser.new do |opts|
|
@@ -32,6 +41,10 @@ OptionParser.new do |opts|
|
|
32
41
|
options[:timeout] = timeout
|
33
42
|
end
|
34
43
|
|
44
|
+
opts.on('--attempts Count', Integer, "Attempts for commands sent to the daemon, in seconds. Defaults to 1.") do |attempts|
|
45
|
+
options[:attempts] = attempts
|
46
|
+
end
|
47
|
+
|
35
48
|
help = proc do
|
36
49
|
puts opts
|
37
50
|
puts
|
@@ -95,8 +108,7 @@ if options[:command] == "load"
|
|
95
108
|
if File.exists?(file)
|
96
109
|
# Restart the ruby interpreter for the config file so that anything loaded here
|
97
110
|
# does not stay in memory for the daemon
|
98
|
-
|
99
|
-
ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
111
|
+
ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
100
112
|
load_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
101
113
|
file_path = File.expand_path(file)
|
102
114
|
|
@@ -109,3 +121,4 @@ else
|
|
109
121
|
target = ARGV.shift
|
110
122
|
controller.handle_command(options[:application], options[:command], target)
|
111
123
|
end
|
124
|
+
|
data/bluepill.gemspec
CHANGED
@@ -15,11 +15,17 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.description = %q{Bluepill keeps your daemons up while taking up as little resources as possible. After all you probably want the resources of your server to be used by whatever daemons you are running rather than the thing that's supposed to make sure they are brought back up, should they die or misbehave.}
|
16
16
|
|
17
17
|
s.add_dependency 'daemons', '~> 1.1.0'
|
18
|
-
s.add_dependency 'state_machine', '~>
|
18
|
+
s.add_dependency 'state_machine', '~> 1.1.0'
|
19
19
|
s.add_dependency 'activesupport', '>= 3.0.0'
|
20
20
|
s.add_dependency 'i18n', '>= 0.5.0'
|
21
21
|
|
22
22
|
s.add_development_dependency 'bundler', '>= 1.0.10'
|
23
|
+
s.add_development_dependency 'rake', '!= 0.9.0'
|
24
|
+
s.add_development_dependency 'rspec-core', '~> 2.0'
|
25
|
+
s.add_development_dependency 'rspec-expectations', '~> 2.0'
|
26
|
+
s.add_development_dependency 'rr', '~> 1.0'
|
27
|
+
s.add_development_dependency 'faker', '~> 0.9'
|
28
|
+
s.add_development_dependency 'yard', '~> 0.7'
|
23
29
|
|
24
30
|
s.files = `git ls-files`.split("\n")
|
25
31
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -27,3 +33,4 @@ Gem::Specification.new do |s|
|
|
27
33
|
s.require_paths = ["lib"]
|
28
34
|
s.extra_rdoc_files = ["LICENSE", "README.md"]
|
29
35
|
end
|
36
|
+
|
data/lib/bluepill/application.rb
CHANGED
@@ -14,7 +14,7 @@ module Bluepill
|
|
14
14
|
|
15
15
|
@foreground = options[:foreground]
|
16
16
|
self.log_file = options[:log_file]
|
17
|
-
self.base_dir = options[:base_dir] || '/var/bluepill'
|
17
|
+
self.base_dir = options[:base_dir] || '/var/run/bluepill'
|
18
18
|
self.pid_file = File.join(self.base_dir, 'pids', self.name + ".pid")
|
19
19
|
self.pids_dir = File.join(self.base_dir, 'pids', self.name)
|
20
20
|
|
@@ -74,6 +74,41 @@ module Bluepill
|
|
74
74
|
else
|
75
75
|
@@pid_files[pid_key] = 0
|
76
76
|
end
|
77
|
+
|
78
|
+
#validate stop_signals array
|
79
|
+
stop_grace_time = process.attributes[:stop_grace_time]
|
80
|
+
stop_signals = process.attributes[:stop_signals]
|
81
|
+
|
82
|
+
unless stop_signals.nil?
|
83
|
+
#Start with the more helpful error messages before the 'odd number' message.
|
84
|
+
delay_sum = 0
|
85
|
+
stop_signals.each_with_index do |s_or_d, i|
|
86
|
+
if i % 2 == 0
|
87
|
+
signal = s_or_d
|
88
|
+
unless signal.is_a? Symbol
|
89
|
+
$stderr.puts "Config Error: Invalid stop_signals! Expected a symbol (signal) at position #{i} instead of '#{signal}'."
|
90
|
+
exit(6)
|
91
|
+
end
|
92
|
+
else
|
93
|
+
delay = s_or_d
|
94
|
+
unless delay.is_a? Fixnum
|
95
|
+
$stderr.puts "Config Error: Invalid stop_signals! Expected a number (delay) at position #{i} instead of '#{delay}'."
|
96
|
+
exit(6)
|
97
|
+
end
|
98
|
+
delay_sum += delay
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
unless stop_signals.size % 2 == 1
|
103
|
+
$stderr.puts "Config Error: Invalid stop_signals! Expected an odd number of elements."
|
104
|
+
exit(6)
|
105
|
+
end
|
106
|
+
|
107
|
+
if stop_grace_time.nil? || stop_grace_time <= delay_sum
|
108
|
+
$stderr.puts "Config Error: Stop_grace_time should be greater than the sum of stop_signals delays!"
|
109
|
+
exit(6)
|
110
|
+
end
|
111
|
+
end
|
77
112
|
end
|
78
113
|
|
79
114
|
def validate_child_process!(child)
|
data/lib/bluepill/process.rb
CHANGED
@@ -35,7 +35,11 @@ module Bluepill
|
|
35
35
|
:child_process_factory,
|
36
36
|
|
37
37
|
:pid_command,
|
38
|
-
:auto_start
|
38
|
+
:auto_start,
|
39
|
+
|
40
|
+
:supplementary_groups,
|
41
|
+
|
42
|
+
:stop_signals
|
39
43
|
]
|
40
44
|
|
41
45
|
attr_accessor :name, :watches, :triggers, :logger, :skip_ticks_until, :process_running
|
@@ -87,6 +91,7 @@ module Bluepill
|
|
87
91
|
end
|
88
92
|
|
89
93
|
before_transition any => any, :do => :notify_triggers
|
94
|
+
before_transition :stopping => any, :do => :clean_threads
|
90
95
|
|
91
96
|
after_transition any => :starting, :do => :start_process
|
92
97
|
after_transition any => :stopping, :do => :stop_process
|
@@ -101,6 +106,7 @@ module Bluepill
|
|
101
106
|
@watches = []
|
102
107
|
@triggers = []
|
103
108
|
@children = []
|
109
|
+
@threads = []
|
104
110
|
@statistics = ProcessStatistics.new
|
105
111
|
@actual_pid = options[:actual_pid]
|
106
112
|
self.logger = options[:logger]
|
@@ -134,6 +140,9 @@ module Bluepill
|
|
134
140
|
# clear the memoization per tick
|
135
141
|
@process_running = nil
|
136
142
|
|
143
|
+
# Deal with thread cleanup here since the stopping state isn't used
|
144
|
+
clean_threads if self.unmonitored?
|
145
|
+
|
137
146
|
# run state machine transitions
|
138
147
|
super
|
139
148
|
|
@@ -288,6 +297,30 @@ module Bluepill
|
|
288
297
|
end
|
289
298
|
end
|
290
299
|
|
300
|
+
elsif stop_signals
|
301
|
+
# issue stop signals with configurable delay between each
|
302
|
+
logger.warning "Sending stop signals to #{actual_pid}"
|
303
|
+
@threads << Thread.new(self, stop_signals.clone) do |process, stop_signals|
|
304
|
+
signal = stop_signals.shift
|
305
|
+
logger.info "Sending signal #{signal} to #{process.actual_pid}"
|
306
|
+
process.signal_process(signal.upcase) # send first signal
|
307
|
+
|
308
|
+
until stop_signals.empty?
|
309
|
+
# we already checked to make sure stop_signals had an odd number of items
|
310
|
+
delay = stop_signals.shift
|
311
|
+
signal = stop_signals.shift
|
312
|
+
|
313
|
+
logger.debug "Sleeping for #{delay} seconds"
|
314
|
+
sleep delay
|
315
|
+
#break unless signal_process(0) #break unless the process can be reached
|
316
|
+
unless process.signal_process(0)
|
317
|
+
logger.debug "Process has terminated."
|
318
|
+
break
|
319
|
+
end
|
320
|
+
logger.info "Sending signal #{signal} to #{process.actual_pid}"
|
321
|
+
process.signal_process(signal.upcase)
|
322
|
+
end
|
323
|
+
end
|
291
324
|
else
|
292
325
|
logger.warning "Executing default stop command. Sending TERM signal to #{actual_pid}"
|
293
326
|
signal_process("TERM")
|
@@ -320,6 +353,11 @@ module Bluepill
|
|
320
353
|
end
|
321
354
|
end
|
322
355
|
|
356
|
+
def clean_threads
|
357
|
+
@threads.each { |t| t.kill }
|
358
|
+
@threads.clear
|
359
|
+
end
|
360
|
+
|
323
361
|
def daemonize?
|
324
362
|
!!self.daemonize
|
325
363
|
end
|
@@ -422,7 +460,8 @@ module Bluepill
|
|
422
460
|
:logger => self.logger,
|
423
461
|
:stdin => self.stdin,
|
424
462
|
:stdout => self.stdout,
|
425
|
-
:stderr => self.stderr
|
463
|
+
:stderr => self.stderr,
|
464
|
+
:supplementary_groups => self.supplementary_groups
|
426
465
|
}
|
427
466
|
end
|
428
467
|
|
@@ -1,19 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
module Bluepill
|
3
3
|
class ProcessStatistics
|
4
|
-
STRFTIME = "%m/%d/%Y %H:%I:%S"
|
4
|
+
STRFTIME = "%m/%d/%Y %H:%I:%S".freeze
|
5
|
+
EVENTS_TO_PERSIST = 10
|
6
|
+
|
7
|
+
attr_reader :events
|
5
8
|
|
6
9
|
# possibly persist this data.
|
7
10
|
def initialize
|
8
|
-
@events = Util::RotationalArray.new(
|
11
|
+
@events = Util::RotationalArray.new(EVENTS_TO_PERSIST)
|
9
12
|
end
|
10
13
|
|
11
14
|
def record_event(event, reason)
|
12
|
-
|
15
|
+
events.push([event, reason, Time.now])
|
13
16
|
end
|
14
17
|
|
15
18
|
def to_s
|
16
|
-
str =
|
19
|
+
str = events.reverse.map do |(event, reason, time)|
|
17
20
|
" #{event} at #{time.strftime(STRFTIME)} - #{reason || "unspecified"}"
|
18
21
|
end.join("\n")
|
19
22
|
|
@@ -21,3 +24,4 @@ module Bluepill
|
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
27
|
+
|
data/lib/bluepill/socket.rb
CHANGED
@@ -4,22 +4,33 @@ require 'socket'
|
|
4
4
|
module Bluepill
|
5
5
|
module Socket
|
6
6
|
TIMEOUT = 60 # Used for client commands
|
7
|
+
MAX_ATTEMPTS = 5
|
7
8
|
|
8
9
|
extend self
|
9
10
|
|
10
|
-
def client(base_dir, name, &
|
11
|
-
UNIXSocket.open(socket_path(base_dir, name), &
|
11
|
+
def client(base_dir, name, &block)
|
12
|
+
UNIXSocket.open(socket_path(base_dir, name), &block)
|
12
13
|
end
|
13
14
|
|
14
15
|
def client_command(base_dir, name, command)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
res = nil
|
17
|
+
MAX_ATTEMPTS.times do |current_attempt|
|
18
|
+
begin
|
19
|
+
client(base_dir, name) do |socket|
|
20
|
+
Timeout.timeout(TIMEOUT) do
|
21
|
+
socket.puts command
|
22
|
+
res = Marshal.load(socket.read)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
break
|
26
|
+
rescue EOFError, Timeout::Error
|
27
|
+
if current_attempt == MAX_ATTEMPTS - 1
|
28
|
+
abort("Socket Timeout: Server may not be responding")
|
29
|
+
end
|
30
|
+
puts "Retry #{current_attempt + 1} of #{MAX_ATTEMPTS}"
|
19
31
|
end
|
20
32
|
end
|
21
|
-
|
22
|
-
abort("Socket Timeout: Server may not be responding")
|
33
|
+
res
|
23
34
|
end
|
24
35
|
|
25
36
|
def server(base_dir, name)
|
data/lib/bluepill/system.rb
CHANGED
@@ -62,7 +62,7 @@ module Bluepill
|
|
62
62
|
# child
|
63
63
|
rd.close
|
64
64
|
|
65
|
-
drop_privileges(options[:uid], options[:gid])
|
65
|
+
drop_privileges(options[:uid], options[:gid], options[:supplementary_groups])
|
66
66
|
|
67
67
|
# if we cannot write the pid file as the provided user, err out
|
68
68
|
exit unless can_write_pid_file(options[:pid_file], options[:logger])
|
@@ -113,7 +113,7 @@ module Bluepill
|
|
113
113
|
|
114
114
|
pid = fork {
|
115
115
|
# grandchild
|
116
|
-
drop_privileges(options[:uid], options[:gid])
|
116
|
+
drop_privileges(options[:uid], options[:gid], options[:supplementary_groups])
|
117
117
|
|
118
118
|
Dir.chdir(ENV["PWD"] = options[:working_dir]) if options[:working_dir]
|
119
119
|
options[:environment].each { |key, value| ENV[key.to_s] = value.to_s } if options[:environment]
|
@@ -192,14 +192,22 @@ module Bluepill
|
|
192
192
|
|
193
193
|
# be sure to call this from a fork otherwise it will modify the attributes
|
194
194
|
# of the bluepill daemon
|
195
|
-
def drop_privileges(uid, gid)
|
195
|
+
def drop_privileges(uid, gid, supplementary_groups)
|
196
196
|
if ::Process::Sys.geteuid == 0
|
197
197
|
uid_num = Etc.getpwnam(uid).uid if uid
|
198
198
|
gid_num = Etc.getgrnam(gid).gid if gid
|
199
199
|
|
200
|
+
supplementary_groups ||= []
|
201
|
+
|
202
|
+
group_nums = supplementary_groups.map do |group|
|
203
|
+
Etc.getgrnam(group).gid
|
204
|
+
end
|
205
|
+
|
200
206
|
::Process.groups = [gid_num] if gid
|
207
|
+
::Process.groups |= group_nums unless group_nums.empty?
|
201
208
|
::Process::Sys.setgid(gid_num) if gid
|
202
209
|
::Process::Sys.setuid(uid_num) if uid
|
210
|
+
ENV['HOME'] = Etc.getpwuid(uid_num).try(:dir) || ENV['HOME'] if uid
|
203
211
|
end
|
204
212
|
end
|
205
213
|
|
data/lib/bluepill/version.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
describe Bluepill::ProcessStatistics do
|
2
|
+
before(:each) do
|
3
|
+
@stats = Bluepill::ProcessStatistics.new
|
4
|
+
end
|
5
|
+
|
6
|
+
it "should record events" do
|
7
|
+
@stats.record_event('some event', 'some reason')
|
8
|
+
@stats.record_event('another event', 'another reason')
|
9
|
+
@stats.events.should have(2).events
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should record #EVENTS_TO_PERSIST events" do
|
13
|
+
(2 * Bluepill::ProcessStatistics::EVENTS_TO_PERSIST).times do
|
14
|
+
@stats.record_event('some event', 'some reason')
|
15
|
+
end
|
16
|
+
@stats.events.should have(Bluepill::ProcessStatistics::EVENTS_TO_PERSIST).events
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return event history" do
|
20
|
+
@stats.record_event('some event', 'some reason')
|
21
|
+
@stats.to_s.should match(/some reason/)
|
22
|
+
@stats.to_s.should match(/event history/)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe Bluepill::System do
|
2
|
+
describe :pid_alive? do
|
3
|
+
it "should be true if process responds to zero signal" do
|
4
|
+
mock(::Process).kill(0, 555)
|
5
|
+
Bluepill::System.should be_pid_alive(555)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be false if process throws exception on zero signal" do
|
9
|
+
mock(::Process).kill(0, 555) { raise Errno::ESRCH.new }
|
10
|
+
Bluepill::System.should_not be_pid_alive(555)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe :store do
|
15
|
+
it "should be Hash" do
|
16
|
+
Bluepill::System.store.should be_kind_of(Hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return same Hash or every call" do
|
20
|
+
Bluepill::System.store.should be_equal(Bluepill::System.store)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should store assigned pairs" do
|
24
|
+
Bluepill::System.store[:somekey] = 10
|
25
|
+
Bluepill::System.store[:somekey].should be_eql(10)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe :reset_data do
|
30
|
+
it 'should clear the #store' do
|
31
|
+
Bluepill::System.store[:anotherkey] = Faker::Lorem.sentence
|
32
|
+
Bluepill::System.reset_data
|
33
|
+
Bluepill::System.store.should be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
if RUBY_VERSION >= '1.9'
|
2
|
+
if ENV['ENABLE_SIMPLECOV']
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start
|
5
|
+
end
|
6
|
+
else
|
7
|
+
require 'rubygems'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'faker'
|
11
|
+
require 'rspec/core'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
|
14
|
+
|
15
|
+
RSpec.configure do |conf|
|
16
|
+
conf.mock_with :rr
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'bluepill'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bluepill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 119
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 52
|
10
|
+
version: 0.0.52
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Arya Asemanfar
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-12-13 00:00:00 +04:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -44,12 +44,12 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
hash:
|
47
|
+
hash: 19
|
48
48
|
segments:
|
49
|
+
- 1
|
50
|
+
- 1
|
49
51
|
- 0
|
50
|
-
|
51
|
-
- 4
|
52
|
-
version: 0.9.4
|
52
|
+
version: 1.1.0
|
53
53
|
type: :runtime
|
54
54
|
version_requirements: *id002
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -100,6 +100,97 @@ dependencies:
|
|
100
100
|
version: 1.0.10
|
101
101
|
type: :development
|
102
102
|
version_requirements: *id005
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: rake
|
105
|
+
prerelease: false
|
106
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - "!="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 59
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
- 9
|
115
|
+
- 0
|
116
|
+
version: 0.9.0
|
117
|
+
type: :development
|
118
|
+
version_requirements: *id006
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: rspec-core
|
121
|
+
prerelease: false
|
122
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ~>
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 2
|
130
|
+
- 0
|
131
|
+
version: "2.0"
|
132
|
+
type: :development
|
133
|
+
version_requirements: *id007
|
134
|
+
- !ruby/object:Gem::Dependency
|
135
|
+
name: rspec-expectations
|
136
|
+
prerelease: false
|
137
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ~>
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
hash: 3
|
143
|
+
segments:
|
144
|
+
- 2
|
145
|
+
- 0
|
146
|
+
version: "2.0"
|
147
|
+
type: :development
|
148
|
+
version_requirements: *id008
|
149
|
+
- !ruby/object:Gem::Dependency
|
150
|
+
name: rr
|
151
|
+
prerelease: false
|
152
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 15
|
158
|
+
segments:
|
159
|
+
- 1
|
160
|
+
- 0
|
161
|
+
version: "1.0"
|
162
|
+
type: :development
|
163
|
+
version_requirements: *id009
|
164
|
+
- !ruby/object:Gem::Dependency
|
165
|
+
name: faker
|
166
|
+
prerelease: false
|
167
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
169
|
+
requirements:
|
170
|
+
- - ~>
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
hash: 25
|
173
|
+
segments:
|
174
|
+
- 0
|
175
|
+
- 9
|
176
|
+
version: "0.9"
|
177
|
+
type: :development
|
178
|
+
version_requirements: *id010
|
179
|
+
- !ruby/object:Gem::Dependency
|
180
|
+
name: yard
|
181
|
+
prerelease: false
|
182
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
183
|
+
none: false
|
184
|
+
requirements:
|
185
|
+
- - ~>
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
hash: 5
|
188
|
+
segments:
|
189
|
+
- 0
|
190
|
+
- 7
|
191
|
+
version: "0.7"
|
192
|
+
type: :development
|
193
|
+
version_requirements: *id011
|
103
194
|
description: Bluepill keeps your daemons up while taking up as little resources as possible. After all you probably want the resources of your server to be used by whatever daemons you are running rather than the thing that's supposed to make sure they are brought back up, should they die or misbehave.
|
104
195
|
email:
|
105
196
|
- entombedvirus@gmail.com
|
@@ -114,6 +205,7 @@ extra_rdoc_files:
|
|
114
205
|
- README.md
|
115
206
|
files:
|
116
207
|
- .gitignore
|
208
|
+
- .rspec
|
117
209
|
- DESIGN.md
|
118
210
|
- Gemfile
|
119
211
|
- LICENSE
|
@@ -153,6 +245,10 @@ files:
|
|
153
245
|
- lib/bluepill/triggers/flapping.rb
|
154
246
|
- lib/bluepill/util/rotational_array.rb
|
155
247
|
- lib/bluepill/version.rb
|
248
|
+
- spec/lib/bluepill/logger_spec.rb
|
249
|
+
- spec/lib/bluepill/process_statistics_spec.rb
|
250
|
+
- spec/lib/bluepill/system_spec.rb
|
251
|
+
- spec/spec_helper.rb
|
156
252
|
has_rdoc: true
|
157
253
|
homepage: http://github.com/arya/bluepill
|
158
254
|
licenses: []
|
@@ -183,9 +279,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
279
|
requirements: []
|
184
280
|
|
185
281
|
rubyforge_project:
|
186
|
-
rubygems_version: 1.
|
282
|
+
rubygems_version: 1.3.7
|
187
283
|
signing_key:
|
188
284
|
specification_version: 3
|
189
285
|
summary: A process monitor written in Ruby with stability and minimalism in mind.
|
190
|
-
test_files:
|
191
|
-
|
286
|
+
test_files:
|
287
|
+
- spec/lib/bluepill/logger_spec.rb
|
288
|
+
- spec/lib/bluepill/process_statistics_spec.rb
|
289
|
+
- spec/lib/bluepill/system_spec.rb
|
290
|
+
- spec/spec_helper.rb
|