god 0.7.7 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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