kennethkalmer-daemon-kit 0.1.6 → 0.1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/Configuration.txt +58 -0
  2. data/History.txt +16 -0
  3. data/Manifest.txt +29 -2
  4. data/PostInstall.txt +1 -1
  5. data/{README.textile → README.rdoc} +31 -19
  6. data/Rakefile +2 -4
  7. data/TODO.txt +6 -5
  8. data/app_generators/daemon_kit/daemon_kit_generator.rb +29 -0
  9. data/app_generators/daemon_kit/templates/Rakefile +3 -1
  10. data/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
  11. data/app_generators/daemon_kit/templates/config/boot.rb +2 -2
  12. data/app_generators/daemon_kit/templates/script/console +3 -0
  13. data/app_generators/daemon_kit/templates/script/destroy +14 -0
  14. data/app_generators/daemon_kit/templates/script/generate +14 -0
  15. data/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +35 -0
  16. data/daemon_generators/deploy_capistrano/templates/Capfile +10 -0
  17. data/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
  18. data/daemon_generators/deploy_capistrano/templates/config/deploy/production.rb +6 -0
  19. data/daemon_generators/deploy_capistrano/templates/config/deploy/staging.rb +6 -0
  20. data/daemon_generators/deploy_capistrano/templates/config/deploy.rb +51 -0
  21. data/daemon_generators/deploy_capistrano/templates/config/environments/staging.rb +0 -0
  22. data/lib/daemon_kit/application.rb +135 -11
  23. data/lib/daemon_kit/arguments.rb +151 -0
  24. data/lib/daemon_kit/commands/console.rb +38 -0
  25. data/lib/daemon_kit/config.rb +1 -0
  26. data/lib/daemon_kit/console_daemon.rb +2 -0
  27. data/lib/daemon_kit/core_ext/string.rb +22 -0
  28. data/lib/daemon_kit/core_ext.rb +1 -0
  29. data/lib/daemon_kit/deployment/capistrano.rb +485 -0
  30. data/lib/daemon_kit/initializer.rb +87 -25
  31. data/lib/daemon_kit/pid_file.rb +61 -0
  32. data/lib/daemon_kit/tasks/environment.rake +5 -4
  33. data/lib/daemon_kit/tasks/framework.rake +15 -1
  34. data/lib/daemon_kit/tasks/god.rake +62 -0
  35. data/lib/daemon_kit/tasks/monit.rake +29 -0
  36. data/lib/daemon_kit.rb +11 -5
  37. data/rubygems_generators/install_rspec/templates/spec/spec_helper.rb +1 -1
  38. data/spec/argument_spec.rb +51 -0
  39. data/spec/config_spec.rb +77 -0
  40. data/spec/daemon_kit_spec.rb +2 -2
  41. data/spec/fixtures/env.yml +15 -0
  42. data/spec/fixtures/noenv.yml +4 -0
  43. data/spec/initializer_spec.rb +4 -3
  44. data/spec/spec_helper.rb +8 -11
  45. data/templates/god/god.erb +69 -0
  46. data/templates/monit/monit.erb +14 -0
  47. data/test/test_daemon-kit_generator.rb +15 -1
  48. data/test/test_deploy_capistrano_generator.rb +48 -0
  49. metadata +41 -21
  50. data/lib/daemon_kit/patches/force_kill_wait.rb +0 -120
@@ -3,7 +3,15 @@ require 'pathname'
3
3
 
4
4
  DAEMON_ENV = (ENV['DAEMON_ENV'] || 'development').dup unless defined?(DAEMON_ENV)
5
5
 
6
- $:.unshift File.dirname(__FILE__) + '/..'
6
+ # Absolute paths to the daemon_kit libraries added to $:
7
+ incdir = ( File.dirname(__FILE__) + '/..' )
8
+ absincdir = if RUBY_PLATFORM =~ /(:?mswin|mingw)/
9
+ File.expand_path( incdir )
10
+ else
11
+ File.expand_path( Pathname.new( incdir ).realpath.to_s )
12
+ end
13
+ $:.unshift absincdir unless $:.include?( absincdir )
14
+
7
15
  require 'daemon_kit'
8
16
 
9
17
  module DaemonKit
@@ -26,17 +34,29 @@ module DaemonKit
26
34
  @configuration = configuration
27
35
  end
28
36
 
37
+ def arguments
38
+ @arguments
39
+ end
40
+
41
+ def arguments=( args )
42
+ @arguments = args
43
+ end
44
+
29
45
  def trap( *args, &block )
30
46
  self.configuration.trap( *args, &block )
31
47
  end
32
48
 
33
49
  def framework_root
34
- File.join( File.dirname(__FILE__), '..', '..' )
50
+ @framework_root ||= File.join( File.dirname(__FILE__), '..', '..' ).to_absolute_path
35
51
  end
36
52
 
37
53
  def root
38
54
  DAEMON_ROOT
39
55
  end
56
+
57
+ def env
58
+ DAEMON_ENV
59
+ end
40
60
  end
41
61
 
42
62
 
@@ -46,7 +66,9 @@ module DaemonKit
46
66
 
47
67
  attr_reader :configuration
48
68
 
49
- def self.run( configuration = Configuration.new )
69
+ def self.run
70
+ configuration = DaemonKit.configuration || Configuration.new
71
+
50
72
  yield configuration if block_given?
51
73
  initializer = new configuration
52
74
  initializer.before_daemonize
@@ -83,6 +105,8 @@ module DaemonKit
83
105
 
84
106
  include_core_lib
85
107
  load_postdaemonize_configs
108
+
109
+ set_process_name
86
110
  end
87
111
 
88
112
  def set_load_path
@@ -96,9 +120,7 @@ module DaemonKit
96
120
  end
97
121
 
98
122
  def load_patches
99
- if !!configuration.force_kill_wait
100
- require 'daemon_kit/patches/force_kill_wait'
101
- end
123
+
102
124
  end
103
125
 
104
126
  def load_environment
@@ -159,6 +181,10 @@ module DaemonKit
159
181
  require core_lib
160
182
  end
161
183
  end
184
+
185
+ def set_process_name
186
+ $0 = configuration.daemon_name
187
+ end
162
188
  end
163
189
 
164
190
  # Holds our various configuration values
@@ -175,21 +201,15 @@ module DaemonKit
175
201
  # Path to the log file, defaults to 'log/<environment>.log'
176
202
  attr_accessor :log_path
177
203
 
178
- # :system,
179
- attr_accessor :dir_mode
180
-
181
- # Path to the log file, defaults to 'log/<environment>.log'
182
- attr_accessor :dir
183
-
184
204
  # Provide a custom logger to use
185
205
  attr_accessor :logger
186
206
 
207
+ # Path to the pid file, defaults to 'log/<daemon_name>.pid'
208
+ attr_accessor :pid_file
209
+
187
210
  # The application name
188
211
  attr_accessor :daemon_name
189
212
 
190
- # Allow multiple copies to run?
191
- attr_accessor :multiple
192
-
193
213
  # Use the force kill patch? Give the number of seconds
194
214
  attr_accessor :force_kill_wait
195
215
 
@@ -200,6 +220,8 @@ module DaemonKit
200
220
  attr_accessor :safety_net
201
221
 
202
222
  def initialize
223
+ parse_arguments!
224
+
203
225
  set_root_path!
204
226
  set_daemon_defaults!
205
227
 
@@ -207,7 +229,6 @@ module DaemonKit
207
229
  self.log_level = default_log_level
208
230
  self.log_path = default_log_path
209
231
 
210
- self.multiple = false
211
232
  self.force_kill_wait = false
212
233
 
213
234
  self.safety_net = DaemonKit::Safety.instance
@@ -240,6 +261,10 @@ module DaemonKit
240
261
  @signal_traps[signal].unshift( proc || block )
241
262
  end
242
263
 
264
+ def pid_file
265
+ @pid_file ||= "#{File.dirname(self.log_path)}/#{self.daemon_name}.pid"
266
+ end
267
+
243
268
  protected
244
269
 
245
270
  def run_traps( signal )
@@ -255,28 +280,55 @@ module DaemonKit
255
280
  Signal.trap( signal, Proc.new { self.run_traps( signal ) } )
256
281
  end
257
282
 
283
+ def parse_arguments!
284
+ configs = Arguments.configuration( ARGV ).first
285
+ @unused_arguments = {}
286
+
287
+ configs.each do |c|
288
+ k,v = c.split('=')
289
+
290
+ if v.nil?
291
+ error( "#{k} has no value" )
292
+ next
293
+ end
294
+
295
+ begin
296
+ if self.respond_to?( k )
297
+ self.send( "#{k}=", v ) # pid_file = /var/run/foo.pid
298
+ else
299
+ @unused_arguments[ k ] = v
300
+ end
301
+ rescue => e
302
+ error( "Couldn't set `#{k}' to `#{v}': #{e.message}" )
303
+ end
304
+ end
305
+ end
306
+
307
+ # DANGEROUS: Change the value of DAEMON_ENV
308
+ def environment=( env )
309
+ ::DAEMON_ENV.replace( env )
310
+ end
311
+
258
312
  def set_root_path!
259
313
  raise "DAEMON_ROOT is not set" unless defined?(::DAEMON_ROOT)
260
- raise "DAEMON_ROOT is not a directory" unless defined?(::DAEMON_ROOT)
314
+ raise "DAEMON_ROOT is not a directory" unless File.directory?(::DAEMON_ROOT)
261
315
 
262
- @root_path =
316
+ @root_path = ::DAEMON_ROOT.to_absolute_path
263
317
  # Pathname is incompatible with Windows, but Windows doesn't have
264
318
  # real symlinks so File.expand_path is safe.
265
- if RUBY_PLATFORM =~ /(:?mswin|mingw)/
266
- File.expand_path(::DAEMON_ROOT)
319
+ #if RUBY_PLATFORM =~ /(:?mswin|mingw)/
320
+ # File.expand_path(::DAEMON_ROOT)
267
321
 
268
322
  # Otherwise use Pathname#realpath which respects symlinks.
269
- else
270
- Pathname.new(::DAEMON_ROOT).realpath.to_s
271
- end
323
+ #else
324
+ # File.expand_path( Pathname.new(::DAEMON_ROOT).realpath.to_s )
325
+ #end
272
326
 
273
327
  Object.const_set(:RELATIVE_DAEMON_ROOT, ::DAEMON_ROOT.dup) unless defined?(::RELATIVE_DAEMON_ROOT)
274
328
  ::DAEMON_ROOT.replace @root_path
275
329
  end
276
330
 
277
331
  def set_daemon_defaults!
278
- self.dir_mode = :normal
279
- self.dir = File.join( DAEMON_ROOT, 'log' )
280
332
  end
281
333
 
282
334
  def default_load_paths
@@ -290,6 +342,16 @@ module DaemonKit
290
342
  def default_log_level
291
343
  environment == 'production' ? Logger::INFO : Logger::DEBUG
292
344
  end
345
+
346
+ def error( msg )
347
+ msg = "[E] Configuration: #{msg}"
348
+
349
+ if DaemonKit.logger
350
+ DaemonKit.logger.error( msg )
351
+ else
352
+ STDERR.puts msg
353
+ end
354
+ end
293
355
  end
294
356
 
295
357
 
@@ -0,0 +1,61 @@
1
+ module DaemonKit
2
+
3
+ # Simple pidfile handling for daemon processes
4
+ class PidFile
5
+
6
+ def initialize( path )
7
+ @path = path.to_absolute_path
8
+ end
9
+
10
+ def exists?
11
+ File.exists?( @path )
12
+ end
13
+
14
+ # Returns true if the process is running
15
+ def running?
16
+ return false unless self.exists?
17
+
18
+ # Check if process is in existence
19
+ # The simplest way to do this is to send signal '0'
20
+ # (which is a single system call) that doesn't actually
21
+ # send a signal
22
+ begin
23
+ Process.kill(0, self.pid)
24
+ return true
25
+ rescue Errno::ESRCH
26
+ return false
27
+ rescue ::Exception # for example on EPERM (process exists but does not belong to us)
28
+ return true
29
+ #rescue Errno::EPERM
30
+ # return false
31
+ end
32
+ end
33
+
34
+ # Return the pid contained in the pidfile, or nil
35
+ def pid
36
+ return nil unless self.exists?
37
+
38
+ File.open( @path ) { |f|
39
+ return f.gets.to_i
40
+ }
41
+ end
42
+
43
+ def ensure_stopped!
44
+ if self.running?
45
+ puts "Process already running with id #{self.pid}"
46
+ exit 1
47
+ end
48
+ end
49
+
50
+ def cleanup
51
+ File.delete( @path ) rescue Errno::ENOENT
52
+ end
53
+ alias zap cleanup
54
+
55
+ def write!
56
+ File.open( @path, 'w' ) { |f|
57
+ f.puts Process.pid
58
+ }
59
+ end
60
+ end
61
+ end
@@ -1,9 +1,10 @@
1
1
  task :environment do
2
- # This relies on the fact that rake changes the currect working
3
- # directory to the directory where the Rakefile is located, thus
4
- # implying DAEMON_ROOT.
5
- DAEMON_ROOT = '.'
6
2
  $daemon_kit_rake_task = true
7
3
 
8
4
  require 'config/environment'
9
5
  end
6
+
7
+ task "Execute system commands in other tasks with sudo"
8
+ task :sudo do
9
+ $RAKE_USE_SUDO = true
10
+ end
@@ -76,7 +76,7 @@ namespace :daemon_kit do
76
76
  desc "Upgrade your local files for a daemon after upgrading daemon-kit"
77
77
  task :upgrade => 'environment' do
78
78
  # Run these
79
- %w{ initializers }.each do |t|
79
+ %w{ initializers rakefile scripts }.each do |t|
80
80
  Rake::Task["daemon_kit:upgrade:#{t}"].invoke
81
81
  end
82
82
 
@@ -87,6 +87,8 @@ namespace :daemon_kit do
87
87
  namespace :upgrade do
88
88
  # Upgrade the initializers
89
89
  task :initializers do
90
+ copy_framework_template( 'config/boot.rb', 'config/boot.rb' )
91
+
90
92
  if File.directory?( File.join(DaemonKit.root, 'config', 'initializers') )
91
93
  mv File.join(DaemonKit.root, 'config', 'initializers'), File.join(DAEMON_ROOT, 'config', 'pre-daemonize')
92
94
  copy_framework_template( 'config', 'pre-daemonize', 'readme' )
@@ -97,6 +99,18 @@ namespace :daemon_kit do
97
99
  copy_framework_template( 'config', 'post-daemonize', 'readme' )
98
100
  end
99
101
  end
102
+
103
+ # Upgrade the Rakefile
104
+ task :rakefile do
105
+ copy_framework_template( 'Rakefile' )
106
+ end
107
+
108
+ # Upgrade the scripts
109
+ task :scripts do
110
+ %w{ console destroy generate }.each do |s|
111
+ copy_framework_template( "script", s )
112
+ end
113
+ end
100
114
  end
101
115
  end
102
116
 
@@ -0,0 +1,62 @@
1
+ require 'erb'
2
+
3
+ namespace :god do
4
+ desc "Generate a stub god config file template for the daemon"
5
+ task :template => 'environment' do
6
+ # Preserve local changes
7
+ if File.exists?( "#{DaemonKit.root}/config/god.erb" ) && ENV['FORCE'].nil?
8
+ puts "Template already exists, use FORCE=1 to overwrite."
9
+ exit 1
10
+ end
11
+
12
+ cp "#{DaemonKit.framework_root}/templates/god/god.erb", "#{DaemonKit.root}/config/god.erb"
13
+ end
14
+
15
+ desc "Parse the god config template into a god config file"
16
+ task :generate => 'environment' do
17
+
18
+ unless File.exists?( "#{DaemonKit.root}/config/god.erb" )
19
+ Rake::Task["god:template"].invoke
20
+ end
21
+
22
+ name = DaemonKit.configuration.daemon_name
23
+
24
+ File.open( "#{DaemonKit.root}/config/#{name}.god", "w+" ) do |f|
25
+ t = File.read( "#{DaemonKit.root}/config/god.erb" )
26
+ f.write( ERB.new( t ).result( binding ) )
27
+ end
28
+
29
+ puts "Monit config generated in config/#{name}.god"
30
+ end
31
+
32
+ desc "Load the god file into god"
33
+ task :load => 'environment' do
34
+ name = DaemonKit.configuration.daemon_name
35
+
36
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god load #{DaemonKit.root}/config/#{name}.god"
37
+ end
38
+
39
+ desc "Refresh the god config file in the running god"
40
+ task :refresh => 'environment' do
41
+ name = DaemonKit.configuration.daemon_name
42
+
43
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god unmonitor #{name}"
44
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god remove #{name}"
45
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god load #{DaemonKit.root}/config/#{name}.god"
46
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god monitor #{name}"
47
+ end
48
+
49
+ desc "Start god monitoring of the config file"
50
+ task :monitor => 'environment' do
51
+ name = DaemonKit.configuration.daemon_name
52
+
53
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god monitor #{name}"
54
+ end
55
+
56
+ desc "Stop god monitoring of the config file"
57
+ task :unmonitor => 'environment' do
58
+ name = DaemonKit.configuration.daemon_name
59
+
60
+ sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god unmonitor #{name}"
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ require 'erb'
2
+
3
+ namespace :monit do
4
+ desc "Generate a stub monit config file template for the daemon"
5
+ task :template => 'environment' do
6
+ # Preserve local changes
7
+ if File.exists?( "#{DaemonKit.root}/config/monit.erb" ) && ENV['FORCE'].nil?
8
+ puts "Template already exists, use FORCE=1 to overwrite."
9
+ exit 1
10
+ end
11
+
12
+ cp "#{DaemonKit.framework_root}/templates/monit/monit.erb", "#{DaemonKit.root}/config/monit.erb"
13
+ end
14
+
15
+ desc "Parse the monit config template into a monit config file"
16
+ task :generate => 'environment' do
17
+
18
+ unless File.exists?( "#{DaemonKit.root}/config/monit.erb" )
19
+ Rake::Task["monit:template"].invoke
20
+ end
21
+
22
+ File.open( "#{DaemonKit.root}/config/monit.conf", "w+" ) do |f|
23
+ t = File.read( "#{DaemonKit.root}/config/monit.erb" )
24
+ f.write( ERB.new( t ).result( binding ) )
25
+ end
26
+
27
+ puts "Monit config generated in config/monit.conf"
28
+ end
29
+ end
data/lib/daemon_kit.rb CHANGED
@@ -1,17 +1,23 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
-
1
+ # TODO: Strip this out eventually so we can run without rubygems
4
2
  require 'rubygems'
5
3
 
4
+ require File.dirname(__FILE__) + '/daemon_kit/core_ext'
5
+
6
+ $:.unshift( File.dirname(__FILE__).to_absolute_path ) unless
7
+ $:.include?( File.dirname(__FILE__).to_absolute_path )
8
+
6
9
  module DaemonKit
7
- VERSION = '0.1.6'
10
+ VERSION = '0.1.7.3'
8
11
 
9
12
  autoload :Initializer, 'daemon_kit/initializer'
10
13
  autoload :Application, 'daemon_kit/application'
14
+ autoload :Arguments, 'daemon_kit/arguments'
11
15
  autoload :Config, 'daemon_kit/config'
16
+ autoload :Safety, 'daemon_kit/safety'
17
+ autoload :PidFile, 'daemon_kit/pid_file'
18
+
12
19
  autoload :Cron, 'daemon_kit/cron'
13
20
  autoload :Jabber, 'daemon_kit/jabber'
14
21
  autoload :AMQP, 'daemon_kit/amqp'
15
22
  autoload :Nanite, 'daemon_kit/nanite'
16
- autoload :Safety, 'daemon_kit/safety'
17
23
  end