god 0.7.7 → 0.7.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.
@@ -1,4 +1,22 @@
1
- == 0.7.7 / TBD
1
+ == 0.7.8 / 2008-07-09
2
+ * Bug Fixes
3
+ * Catch all Exceptions from HttpResponseCode condition [github.com/rliebling]
4
+ * Don't error out if the process went away in SlashProcPoller [Kevin Clark]
5
+ * Correction of Task#handle_poll to prevent crash under event registration failure conditions. [github.com/raggi]
6
+ * Cleaned up logging of failed e-mail sends. [github.com/raggi]
7
+ * Listen on 127.0.0.1 when using God as a client. [github.com/halorgium]
8
+ * New Behaviors
9
+ * clean_unix_socket [github.com/gma]
10
+ * New Contacts
11
+ * jabber [github.com/jwulff]
12
+ * email via sendmail [github.com/monde]
13
+ * Minor Enhancements
14
+ * chroot support [github.com/eric]
15
+ * Added God.log_file for the main god log, overridden by command line option. [github.com/raggi]
16
+ * Print groups from `god status` command if present [github.com/pdlug]
17
+ * Allow headers to be specified for http_response_code condition [github.com/pdlug]
18
+
19
+ == 0.7.7 / 2008-06-17
2
20
  * Bug Fixes
3
21
  * Fix detection of proc file system [raggi]
4
22
 
@@ -13,6 +13,7 @@ init/god
13
13
  lib/god.rb
14
14
  lib/god/behavior.rb
15
15
  lib/god/behaviors/clean_pid_file.rb
16
+ lib/god/behaviors/clean_unix_socket.rb
16
17
  lib/god/behaviors/notify_when_flapping.rb
17
18
  lib/god/cli/command.rb
18
19
  lib/god/cli/run.rb
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'hoe'
3
3
 
4
- Hoe.new('god', '0.7.7') do |p|
4
+ Hoe.new('god', '0.7.8') do |p|
5
5
  p.rubyforge_name = 'god'
6
6
  p.author = 'Tom Preston-Werner'
7
7
  p.email = 'tom@rubyisawesome.com'
data/lib/god.rb CHANGED
@@ -33,6 +33,7 @@ require 'god/task'
33
33
 
34
34
  require 'god/behavior'
35
35
  require 'god/behaviors/clean_pid_file'
36
+ require 'god/behaviors/clean_unix_socket'
36
37
  require 'god/behaviors/notify_when_flapping'
37
38
 
38
39
  require 'god/condition'
@@ -51,6 +52,10 @@ require 'god/conditions/complex'
51
52
 
52
53
  require 'god/contact'
53
54
  require 'god/contacts/email'
55
+ begin
56
+ require 'god/contacts/jabber'
57
+ rescue LoadError
58
+ end
54
59
 
55
60
  require 'god/socket'
56
61
  require 'god/driver'
@@ -133,7 +138,7 @@ class Module
133
138
  end
134
139
 
135
140
  module God
136
- VERSION = '0.7.7'
141
+ VERSION = '0.7.8'
137
142
 
138
143
  LOG_BUFFER_SIZE_DEFAULT = 100
139
144
  PID_FILE_DIRECTORY_DEFAULTS = ['/var/run/god', '~/.god/pids']
@@ -149,6 +154,7 @@ module God
149
154
  :allow,
150
155
  :log_buffer_size,
151
156
  :pid_file_directory,
157
+ :log_file,
152
158
  :log_level,
153
159
  :use_events
154
160
 
@@ -460,7 +466,7 @@ module God
460
466
  def self.status
461
467
  info = {}
462
468
  self.watches.map do |name, w|
463
- info[name] = {:state => w.state}
469
+ info[name] = {:state => w.state, :group => w.group}
464
470
  end
465
471
  info
466
472
  end
@@ -635,4 +641,4 @@ end
635
641
  # Returns nothing
636
642
  at_exit do
637
643
  God.at_exit if $run
638
- end
644
+ end
@@ -0,0 +1,21 @@
1
+ module God
2
+ module Behaviors
3
+
4
+ class CleanUnixSocket < Behavior
5
+ def valid?
6
+ valid = true
7
+ valid &= complain("Attribute 'unix_socket' must be specified", self) if self.watch.unix_socket.nil?
8
+ valid
9
+ end
10
+
11
+ def before_start
12
+ File.delete(self.watch.unix_socket)
13
+
14
+ "deleted unix socket"
15
+ rescue
16
+ "no unix socket to delete"
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -12,7 +12,7 @@ module God
12
12
 
13
13
  def setup
14
14
  # connect to drb unix socket
15
- DRb.start_service
15
+ DRb.start_service("druby://127.0.0.1:0")
16
16
  @server = DRbObject.new(nil, God::Socket.socket(@options[:port]))
17
17
 
18
18
  # ping server to ensure that it is responsive
@@ -66,10 +66,21 @@ module God
66
66
  end
67
67
 
68
68
  def status_command
69
- watches = @server.status
70
- watches.keys.sort.each do |name|
71
- state = watches[name][:state]
72
- puts "#{name}: #{state}"
69
+ watches = {}
70
+ @server.status.each do |name, status|
71
+ g = status[:group] || ''
72
+ unless watches.has_key?(g)
73
+ watches[g] = {}
74
+ end
75
+ watches[g][name] = status
76
+ end
77
+ watches.keys.sort.each do |group|
78
+ puts "#{group}:" unless group.empty?
79
+ watches[group].keys.sort.each do |name|
80
+ state = watches[group][name][:state]
81
+ print " " unless group.empty?
82
+ puts "#{name}: #{state}"
83
+ end
73
84
  end
74
85
  end
75
86
 
@@ -192,4 +203,4 @@ module God
192
203
  end # Command
193
204
 
194
205
  end
195
- end
206
+ end
@@ -75,8 +75,9 @@ module God
75
75
 
76
76
  default_run
77
77
 
78
- if @options[:log]
79
- log_file = File.expand_path(@options[:log])
78
+ log_file = God.log_file
79
+ log_file = File.expand_path(@options[:log]) if @options[:log]
80
+ if log_file
80
81
  puts "Sending output to log file: #{log_file}"
81
82
 
82
83
  # reset file descriptors
@@ -95,7 +96,7 @@ module God
95
96
  begin
96
97
  require 'god'
97
98
 
98
- log_file = @options[:log] || "/dev/null"
99
+ log_file = @options[:log] || God.log_file || "/dev/null"
99
100
 
100
101
  # reset file descriptors
101
102
  STDIN.reopen "/dev/null"
@@ -19,6 +19,7 @@ module God
19
19
  # Optional
20
20
  # +port+ is the port to connect (default 80)
21
21
  # +path+ is the path to connect (default '/')
22
+ # +headers+ is the hash of HTTP headers to send (default none)
22
23
  # +times+ is the number of times after which to trigger (default 1)
23
24
  # e.g. 3 (times in a row) or [3, 5] (three out of fives times)
24
25
  # +timeout+ is the time to wait for a connection (default 60.seconds)
@@ -68,12 +69,14 @@ module God
68
69
  :host, # e.g. www.example.com
69
70
  :port, # e.g. 8080
70
71
  :timeout, # e.g. 60.seconds
71
- :path # e.g. '/'
72
+ :path, # e.g. '/'
73
+ :headers # e.g. {'Host' => 'myvirtual.mydomain.com'}
72
74
 
73
75
  def initialize
74
76
  super
75
77
  self.port = 80
76
78
  self.path = '/'
79
+ self.headers = {}
77
80
  self.times = [1, 1]
78
81
  self.timeout = 60.seconds
79
82
  end
@@ -108,7 +111,7 @@ module God
108
111
 
109
112
  Net::HTTP.start(self.host, self.port) do |http|
110
113
  http.read_timeout = self.timeout
111
- response = http.get(self.path)
114
+ response = http.get(self.path, self.headers)
112
115
  end
113
116
 
114
117
  actual_response_code = response.code.to_i
@@ -127,6 +130,10 @@ module God
127
130
  self.code_is ? fail('EOF') : pass('EOF')
128
131
  rescue Timeout::Error
129
132
  self.code_is ? fail('Timeout') : pass('Timeout')
133
+ rescue Errno::ETIMEDOUT
134
+ self.code_is ? fail('Timedout') : pass('Timedout')
135
+ rescue Exception => failure
136
+ self.code_is ? fail(failure.class.name) : pass(failure.class.name)
130
137
  end
131
138
 
132
139
  private
@@ -6,12 +6,12 @@ module God
6
6
 
7
7
  class Email < Contact
8
8
  class << self
9
- attr_accessor :message_settings, :delivery_method, :server_settings, :format
9
+ attr_accessor :message_settings, :delivery_method, :server_settings, :sendmail_settings, :format
10
10
  end
11
11
 
12
12
  self.message_settings = {:from => 'god@example.com'}
13
13
 
14
- self.delivery_method = :smtp
14
+ self.delivery_method = :smtp # or :sendmail
15
15
 
16
16
  self.server_settings = {:address => 'localhost',
17
17
  :port => 25}
@@ -19,6 +19,10 @@ module God
19
19
  # :user_name
20
20
  # :password
21
21
  # :authentication
22
+
23
+ self.sendmail_settings = {:location => '/usr/sbin/sendmail',
24
+ :arguments => '-i -t'
25
+ }
22
26
 
23
27
  self.format = lambda do |name, email, message, time, priority, category, host|
24
28
  <<-EOF
@@ -46,28 +50,46 @@ Category: #{category}
46
50
  def notify(message, time, priority, category, host)
47
51
  begin
48
52
  body = Email.format.call(self.name, self.email, message, time, priority, category, host)
49
-
50
- args = [Email.server_settings[:address], Email.server_settings[:port]]
51
- if Email.server_settings[:authentication]
52
- args << Email.server_settings[:domain]
53
- args << Email.server_settings[:user_name]
54
- args << Email.server_settings[:password]
55
- args << Email.server_settings[:authentication]
56
- end
57
-
58
- Net::SMTP.start(*args) do |smtp|
59
- smtp.send_message body, Email.message_settings[:from], self.email
53
+
54
+ case Email.delivery_method
55
+ when :smtp
56
+ notify_smtp(body)
57
+ when :sendmail
58
+ notify_sendmail(body)
59
+ else
60
+ raise "unknown delivery method: #{Email.delivery_method}"
60
61
  end
61
62
 
62
63
  self.info = "sent email to #{self.email}"
63
64
  rescue => e
64
- puts e.message
65
- puts e.backtrace.join("\n")
66
-
67
- self.info = "failed to send email to #{self.email}: #{e.message}"
65
+ applog(nil, :info, "failed to send email to #{self.email}: #{e.message}")
66
+ applog(nil, :debug, e.backtrace.join("\n"))
67
+ end
68
+ end
69
+
70
+ # private
71
+
72
+ def notify_smtp(mail)
73
+ args = [Email.server_settings[:address], Email.server_settings[:port]]
74
+ if Email.server_settings[:authentication]
75
+ args << Email.server_settings[:domain]
76
+ args << Email.server_settings[:user_name]
77
+ args << Email.server_settings[:password]
78
+ args << Email.server_settings[:authentication]
79
+ end
80
+
81
+ Net::SMTP.start(*args) do |smtp|
82
+ smtp.send_message mail, Email.message_settings[:from], self.email
83
+ end
84
+ end
85
+
86
+ def notify_sendmail(mail)
87
+ IO.popen("#{Email.sendmail_settings[:location]} #{Email.sendmail_settings[:arguments]}","w+") do |sm|
88
+ sm.print(mail.gsub(/\r/, ''))
89
+ sm.flush
68
90
  end
69
91
  end
70
92
  end
71
-
93
+
72
94
  end
73
- end
95
+ end
@@ -2,7 +2,7 @@ module God
2
2
  class Process
3
3
  WRITES_PID = [:start, :restart]
4
4
 
5
- attr_accessor :name, :uid, :gid, :log, :start, :stop, :restart
5
+ attr_accessor :name, :uid, :gid, :log, :start, :stop, :restart, :unix_socket, :chroot, :env
6
6
 
7
7
  def initialize
8
8
  self.log = '/dev/null'
@@ -11,6 +11,7 @@ module God
11
11
  @tracking_pid = true
12
12
  @user_log = false
13
13
  @pid = nil
14
+ @unix_socket = nil
14
15
  end
15
16
 
16
17
  def alive?
@@ -23,9 +24,14 @@ module God
23
24
 
24
25
  def file_writable?(file)
25
26
  pid = fork do
26
- ::Process::Sys.setgid(Etc.getgrnam(self.gid).gid) if self.gid
27
- ::Process::Sys.setuid(Etc.getpwnam(self.uid).uid) if self.uid
28
-
27
+ uid_num = Etc.getpwnam(self.uid).uid if self.uid
28
+ gid_num = Etc.getgrnam(self.gid).gid if self.gid
29
+
30
+ ::Dir.chroot(self.chroot) if self.chroot
31
+ ::Process.groups = [gid_num] if self.gid
32
+ ::Process::Sys.setgid(gid_num) if self.gid
33
+ ::Process::Sys.setuid(uid_num) if self.uid
34
+
29
35
  File.writable?(file) ? exit(0) : exit(1)
30
36
  end
31
37
 
@@ -101,6 +107,19 @@ module God
101
107
  applog(self, :error, "Log directory '#{File.dirname(self.log)}' is not writable by #{self.uid || Etc.getlogin}")
102
108
  end
103
109
  end
110
+
111
+ # chroot directory must exist and have /dev/null in it
112
+ if self.chroot
113
+ if !File.directory?(self.chroot)
114
+ valid = false
115
+ LOG.log(self, :error, "CHROOT directory '#{self.chroot}' does not exist")
116
+ end
117
+
118
+ if !File.exist?(File.join(self.chroot, '/dev/null'))
119
+ valid = false
120
+ LOG.log(self, :error, "CHROOT directory '#{self.chroot}' does not contain '/dev/null'")
121
+ end
122
+ end
104
123
 
105
124
  valid
106
125
  end
@@ -244,18 +263,29 @@ module God
244
263
  # Returns nothing
245
264
  def spawn(command)
246
265
  fork do
266
+ uid_num = Etc.getpwnam(self.uid).uid if self.uid
267
+ gid_num = Etc.getgrnam(self.gid).gid if self.gid
268
+
269
+ ::Dir.chroot(self.chroot) if self.chroot
247
270
  ::Process.setsid
248
- ::Process::Sys.setgid(Etc.getgrnam(self.gid).gid) if self.gid
249
- ::Process::Sys.setuid(Etc.getpwnam(self.uid).uid) if self.uid
271
+ ::Process.groups = [gid_num] if self.gid
272
+ ::Process::Sys.setgid(gid_num) if self.gid
273
+ ::Process::Sys.setuid(uid_num) if self.uid
250
274
  Dir.chdir "/"
251
275
  $0 = command
252
276
  STDIN.reopen "/dev/null"
253
- STDOUT.reopen self.log, "a"
277
+ STDOUT.reopen file_in_chroot(self.log), "a"
254
278
  STDERR.reopen STDOUT
255
279
 
256
280
  # close any other file descriptors
257
281
  3.upto(256){|fd| IO::new(fd).close rescue nil}
258
-
282
+
283
+ if self.env && self.env.is_a?(Hash)
284
+ self.env.each do |(key, value)|
285
+ ENV[key] = value
286
+ end
287
+ end
288
+
259
289
  exec command unless command.empty?
260
290
  end
261
291
  end
@@ -286,6 +316,12 @@ module God
286
316
  ::Process.kill('KILL', self.pid) rescue nil
287
317
  applog(self, :warn, "#{self.name} process still running 10 seconds after stop command returned. Force killing.")
288
318
  end
289
-
319
+
320
+ private
321
+ def file_in_chroot(file)
322
+ return file unless self.chroot
323
+
324
+ file.gsub(/^#{Regexp.escape(File.expand_path(self.chroot))}/, '')
325
+ end
290
326
  end
291
327
  end
@@ -31,10 +31,14 @@ module God
31
31
 
32
32
  def memory
33
33
  stat[:rss].to_i * @@kb_per_page
34
+ rescue # This shouldn't fail is there's an error (or proc doesn't exist)
35
+ 0
34
36
  end
35
37
 
36
38
  def percent_memory
37
39
  (memory / @@total_mem.to_f) * 100
40
+ rescue # This shouldn't fail is there's an error (or proc doesn't exist)
41
+ 0
38
42
  end
39
43
 
40
44
  # TODO: Change this to calculate the wma instead
@@ -47,6 +51,8 @@ module God
47
51
  else
48
52
  ((total_time * 1000 / @@hertz) / seconds) / 10
49
53
  end
54
+ rescue # This shouldn't fail is there's an error (or proc doesn't exist)
55
+ 0
50
56
  end
51
57
 
52
58
  private
@@ -19,7 +19,7 @@ module God
19
19
  self.behaviors = []
20
20
 
21
21
  # the list of conditions for each action
22
- self.metrics = {nil => [], :unmonitored => []}
22
+ self.metrics = {nil => [], :unmonitored => [], :stop => []}
23
23
 
24
24
  # the condition -> metric lookup
25
25
  self.directory = {}
@@ -343,10 +343,10 @@ module God
343
343
  begin
344
344
  self.move(dest)
345
345
  rescue EventRegistrationFailedError
346
- msg = watch.name + ' Event registration failed, moving back to previous state'
347
- applog(watch, :info, msg)
346
+ msg = self.name + ' Event registration failed, moving back to previous state'
347
+ applog(self, :info, msg)
348
348
 
349
- dest = watch.state
349
+ dest = self.state
350
350
  retry
351
351
  end
352
352
  else
@@ -13,7 +13,8 @@ module God
13
13
  extend Forwardable
14
14
  def_delegators :@process, :name, :uid, :gid, :start, :stop, :restart,
15
15
  :name=, :uid=, :gid=, :start=, :stop=, :restart=,
16
- :pid_file, :pid_file=, :log, :log=, :alive?, :pid
16
+ :pid_file, :pid_file=, :log, :log=, :alive?, :pid,
17
+ :unix_socket, :unix_socket=, :chroot, :chroot=, :env, :env=
17
18
  #
18
19
  def initialize
19
20
  super
@@ -74,6 +75,12 @@ module God
74
75
  end
75
76
  end
76
77
 
78
+ def stop_if
79
+ self.transition(:up, :stop) do |on|
80
+ yield(on)
81
+ end
82
+ end
83
+
77
84
  ###########################################################################
78
85
  #
79
86
  # Lifecycle
@@ -173,4 +180,4 @@ module God
173
180
  end
174
181
  end
175
182
 
176
- end
183
+ end
@@ -6,11 +6,13 @@ require 'set'
6
6
 
7
7
  include God
8
8
 
9
- if RUBY_PLATFORM =~ /linux/i && Process.uid != 0
9
+ if Process.uid != 0
10
10
  abort <<-EOF
11
+ \n
11
12
  *********************************************************************
12
13
  * *
13
- * You need to run these tests as root (netlink requires it) *
14
+ * You need to run these tests as root *
15
+ * chroot and netlink (linux only) require it *
14
16
  * *
15
17
  *********************************************************************
16
18
  EOF
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestEmail < Test::Unit::TestCase
4
+ def test_exists
5
+ God::Contacts::Email
6
+ end
7
+
8
+ def test_unknown_delivery_method_for_notify
9
+ assert_nothing_raised do
10
+ God::Contacts::Email.any_instance.expects(:notify_smtp).never
11
+ God::Contacts::Email.any_instance.expects(:notify_sendmail).never
12
+ God::Contacts::Email.delivery_method = :foo_protocol
13
+ LOG.expects(:log).times(2)
14
+
15
+ g = God::Contacts::Email.new
16
+ g.notify(:a, :b, :c, :d, :e)
17
+ assert_nil g.info
18
+ end
19
+ end
20
+
21
+ def test_smtp_delivery_method_for_notify
22
+ assert_nothing_raised do
23
+ God::Contacts::Email.any_instance.expects(:notify_sendmail).never
24
+ God::Contacts::Email.any_instance.expects(:notify_smtp).once.returns(nil)
25
+ God::Contacts::Email.delivery_method = :smtp
26
+ g = God::Contacts::Email.new
27
+ g.email = 'joe@example.com'
28
+ g.notify(:a, :b, :c, :d, :e)
29
+ assert_equal "sent email to joe@example.com", g.info
30
+ end
31
+ end
32
+
33
+ def test_sendmail_delivery_method_for_notify
34
+ assert_nothing_raised do
35
+ God::Contacts::Email.any_instance.expects(:notify_smtp).never
36
+ God::Contacts::Email.any_instance.expects(:notify_sendmail).once.returns(nil)
37
+ God::Contacts::Email.delivery_method = :sendmail
38
+ g = God::Contacts::Email.new
39
+ g.email = 'joe@example.com'
40
+ g.notify(:a, :b, :c, :d, :e)
41
+ assert_equal "sent email to joe@example.com", g.info
42
+ end
43
+ end
44
+
45
+ end
@@ -378,14 +378,22 @@ class TestGod < Test::Unit::TestCase
378
378
 
379
379
  w = God.watches['foo']
380
380
  w.state = :up
381
- assert_equal({'foo' => {:state => :up}}, God.status)
381
+ assert_equal({'foo' => {:state => :up, :group => nil}}, God.status)
382
382
  end
383
383
 
384
+ def test_status_should_show_state_with_group
385
+ God.watch { |w| w.name = 'foo'; w.start = 'bar'; w.group = 'g' }
386
+
387
+ w = God.watches['foo']
388
+ w.state = :up
389
+ assert_equal({'foo' => {:state => :up, :group => 'g'}}, God.status)
390
+ end
391
+
384
392
  def test_status_should_show_unmonitored_for_nil_state
385
393
  God.watch { |w| w.name = 'foo'; w.start = 'bar' }
386
394
 
387
395
  w = God.watches['foo']
388
- assert_equal({'foo' => {:state => :unmonitored}}, God.status)
396
+ assert_equal({'foo' => {:state => :unmonitored, :group => nil}}, God.status)
389
397
  end
390
398
 
391
399
  # running_log
@@ -587,4 +595,4 @@ end
587
595
  # God.validater
588
596
  # end
589
597
  # end
590
- # end
598
+ # end
@@ -68,7 +68,7 @@ class TestProcessChild < Test::Unit::TestCase
68
68
  assert @p.valid?
69
69
  end
70
70
 
71
- def test_valid_should_return_true_if_gid_does_not_exists
71
+ def test_valid_should_return_false_if_gid_does_not_exists
72
72
  @p.start = 'qux'
73
73
  @p.log = '/tmp/foo.log'
74
74
  @p.gid = 'foobarbaz'
@@ -79,6 +79,28 @@ class TestProcessChild < Test::Unit::TestCase
79
79
  end
80
80
  end
81
81
  end
82
+
83
+ def test_valid_should_return_false_with_bogus_chroot
84
+ @p.chroot = '/bogusroot'
85
+
86
+ no_stdout do
87
+ no_stderr do
88
+ assert !@p.valid?
89
+ end
90
+ end
91
+ end
92
+
93
+ def test_valid_should_return_true_with_chroot_and_valid_log
94
+ @p.start = 'qux'
95
+ @p.chroot = '/tmp'
96
+ @p.log = '/tmp/foo.log'
97
+
98
+ File.expects(:exist?).with('/tmp').returns(true)
99
+ File.expects(:exist?).with('/tmp/foo.log').returns(true)
100
+ File.expects(:exist?).with('/tmp/dev/null').returns(true)
101
+
102
+ assert @p.valid?
103
+ end
82
104
 
83
105
  # call_action
84
106
 
@@ -172,12 +194,19 @@ class TestProcessDaemon < Test::Unit::TestCase
172
194
  assert_equal 246, @p.pid
173
195
  end
174
196
 
175
- # defaul_pid_file
197
+ # default_pid_file
176
198
 
177
199
  def test_default_pid_file
178
200
  assert_equal File.join(God.pid_file_directory, 'foo.pid'), @p.default_pid_file
179
201
  end
180
202
 
203
+ # unix socket
204
+
205
+ def test_unix_socket_should_return_path_specified
206
+ @p.unix_socket = '/path/to-socket'
207
+ assert_equal '/path/to-socket', @p.unix_socket
208
+ end
209
+
181
210
  # call_action
182
211
  # These actually excercise call_action in the back at this point - Kev
183
212
 
@@ -214,4 +243,4 @@ class TestProcessDaemon < Test::Unit::TestCase
214
243
  @p.send("#{x}!")
215
244
  end
216
245
  end
217
- end
246
+ end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.2
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: god
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.7.7
7
- date: 2008-06-17 00:00:00 -07:00
6
+ version: 0.7.8
7
+ date: 2008-07-09 00:00:00 -07:00
8
8
  summary: Like monit, only awesome
9
9
  require_paths:
10
10
  - lib
@@ -45,6 +45,7 @@ files:
45
45
  - lib/god.rb
46
46
  - lib/god/behavior.rb
47
47
  - lib/god/behaviors/clean_pid_file.rb
48
+ - lib/god/behaviors/clean_unix_socket.rb
48
49
  - lib/god/behaviors/notify_when_flapping.rb
49
50
  - lib/god/cli/command.rb
50
51
  - lib/god/cli/run.rb
@@ -146,6 +147,7 @@ test_files:
146
147
  - test/test_contact.rb
147
148
  - test/test_dependency_graph.rb
148
149
  - test/test_driver.rb
150
+ - test/test_email.rb
149
151
  - test/test_event_handler.rb
150
152
  - test/test_god.rb
151
153
  - test/test_handlers_kqueue_handler.rb