summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-02-02 17:19:07 -0600
committerLuke Kanies <luke@madstop.com>2009-02-06 18:08:43 -0600
commitc0fcb2137e66af8ba60a959faa221034c6832b69 (patch)
tree10f62605333979ea64445dca5d4d66d58237de97
parent700e823f7c33eb3c5b4d9e467742fd24f63bbeef (diff)
Creating and using a new Puppet::Daemon class
This replaces the short-lived EventManager class, all of the service- and timer-related code in puppet.rb, and moves code from agent.rb, server.rb, and other places into one class responsible for starting, stopping, pids, and more. The Daemon module is no longer in existence, so it's been removed from the classes that were using it. Signed-off-by: Luke Kanies <luke@madstop.com>
-rwxr-xr-xbin/puppetd58
-rwxr-xr-xbin/puppetmasterd19
-rw-r--r--lib/puppet.rb204
-rw-r--r--lib/puppet/agent.rb39
-rw-r--r--lib/puppet/agent/locker.rb1
-rwxr-xr-xlib/puppet/daemon.rb102
-rw-r--r--lib/puppet/event_manager.rb182
-rw-r--r--lib/puppet/network/http_server/mongrel.rb2
-rw-r--r--lib/puppet/network/http_server/webrick.rb2
-rw-r--r--lib/puppet/util/settings.rb19
-rwxr-xr-xspec/unit/agent.rb77
-rwxr-xr-xspec/unit/daemon.rb287
-rwxr-xr-xspec/unit/event_manager.rb266
-rwxr-xr-xspec/unit/network/client.rb4
-rwxr-xr-xspec/unit/util/settings.rb42
-rwxr-xr-xtest/network/daemon.rb70
16 files changed, 520 insertions, 854 deletions
diff --git a/bin/puppetd b/bin/puppetd
index 2a71a9a08..4c7f1d131 100755
--- a/bin/puppetd
+++ b/bin/puppetd
@@ -163,9 +163,14 @@ end
require 'puppet'
require 'puppet/agent'
+require 'puppet/daemon'
require 'puppet/configurer'
require 'getoptlong'
+# Create this now, so it has access to ARGV
+daemon = Puppet::Daemon.new
+daemon.argv = ARGV.dup
+
options = [
[ "--centrallogging", GetoptLong::NO_ARGUMENT ],
[ "--disable", GetoptLong::NO_ARGUMENT ],
@@ -214,7 +219,7 @@ begin
options[:disable] = true
when "--serve"
if Puppet::Network::Handler.handler(arg)
- options[:serve][arg.to_sym] = {}
+ options[:serve] << arg.to_sym
else
raise "Could not find handler for %s" % arg
end
@@ -349,12 +354,14 @@ if options[:enable] or options[:disable]
exit(0)
end
+daemon.agent = agent
+
server = nil
# It'd be nice to daemonize later, but we have to daemonize before the
# waitforcert happens.
if Puppet[:daemonize]
- agent.daemonize
+ daemon.daemonize
end
host = Puppet::SSL::Host.new
@@ -380,40 +387,20 @@ if Puppet[:listen] and ! options[:onetime]
handlers = nil
if options[:serve].empty?
- handlers = {:Runner => {}}
+ handlers = [:Runner]
else
handlers = options[:serve]
end
- handlers.each do |name, hash|
- Puppet.info "Starting handler for %s" % name
- end
-
- args[:Handlers] = handlers
- args[:Port] = Puppet[:puppetport]
-
- require 'puppet/network/http_server/webrick'
-
- begin
- server = Puppet::Network::HTTPServer::WEBrick.new(args)
- rescue => detail
- $stderr.puts detail
- puts detail.backtrace
- exit(1)
- end
+ require 'puppet/network/server'
+ # No REST handlers yet.
+ server = Puppet::Network::Server.new(:handlers => [:facts], :xmlrpc_handlers => handlers, :port => Puppet[:puppetport])
- objects << server
+ daemon.server = server
elsif options[:onetime] and Puppet[:listen]
Puppet.notice "Ignoring --listen on onetime run"
end
-if options[:client]
- objects << agent
-end
-
-# Set traps for INT and TERM
-Puppet.settraps
-
# If --onetime is specified, we don't run 'start', which means we don't
# create a pidfile.
if options[:onetime]
@@ -422,8 +409,7 @@ if options[:onetime]
exit(43)
end
- # Add the service, so the traps work correctly.
- Puppet.newservice(agent)
+ daemon.set_signal_traps
begin
agent.run
@@ -435,17 +421,7 @@ if options[:onetime]
end
exit(0)
else
- if server
- Puppet.newservice(server)
- end
+ Puppet.notice "Starting Puppet client version %s" % [Puppet.version]
- if options[:client]
- Puppet.notice "Starting Puppet client version %s" % [Puppet.version]
- Puppet.newservice(agent)
- end
-
- Puppet.settraps
-
- Puppet.start
+ daemon.start
end
-
diff --git a/bin/puppetmasterd b/bin/puppetmasterd
index 74ec821d4..3abdb77ea 100755
--- a/bin/puppetmasterd
+++ b/bin/puppetmasterd
@@ -70,8 +70,13 @@ end
require 'getoptlong'
require 'puppet'
+require 'puppet/daemon'
require 'puppet/network/server'
+# Create this first-off, so we have ARGV
+daemon = Puppet::Daemon.new
+daemon.argv = ARGV.dup
+
options = [
[ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
[ "--help", "-h", GetoptLong::NO_ARGUMENT ],
@@ -197,7 +202,7 @@ if Puppet[:ca]
xmlrpc_handlers << :CA
end
-server = Puppet::Network::Server.new(:handlers => rest_handlers, :xmlrpc_handlers => xmlrpc_handlers)
+daemon.server = Puppet::Network::Server.new(:handlers => rest_handlers, :xmlrpc_handlers => xmlrpc_handlers)
# Make sure we've got a localhost ssl cert
Puppet::SSL::Host.localhost
@@ -218,16 +223,8 @@ if Process.uid == 0
end
end
-# Tell Puppet to manage this service for us, which has it starting and stopping
-# as appropriate.
-Puppet.newservice(server)
-
-Puppet.settraps
-
-if Puppet[:daemonize]
- server.daemonize
-end
+daemon.daemonize if Puppet[:daemonize]
Puppet.notice "Starting Puppet server version %s" % [Puppet.version]
-Puppet.start
+daemon.start
diff --git a/lib/puppet.rb b/lib/puppet.rb
index dad8936d2..c2d108d7f 100644
--- a/lib/puppet.rb
+++ b/lib/puppet.rb
@@ -8,7 +8,6 @@ end
require 'singleton'
require 'facter'
require 'puppet/error'
-require 'puppet/external/event-loop'
require 'puppet/util'
require 'puppet/util/log'
require 'puppet/util/autoload'
@@ -32,14 +31,7 @@ module Puppet
end
class << self
- # So we can monitor signals and such.
- include SignalObserver
-
include Puppet::Util
-
- # To keep a copy of arguments. Set within Config#addargs, because I'm
- # lazy.
- attr_accessor :args
attr_reader :features
attr_writer :name
end
@@ -117,7 +109,6 @@ module Puppet
# Load all of the configuration parameters.
require 'puppet/defaults'
-
def self.genmanifest
if Puppet[:genmanifest]
puts Puppet.settings.to_manifest
@@ -125,42 +116,6 @@ module Puppet
end
end
- # Run all threads to their ends
- def self.join
- defined? @threads and @threads.each do |t| t.join end
- end
-
- # Create a new service that we're supposed to run
- def self.newservice(service)
- @services ||= []
-
- @services << service
- end
-
- def self.newthread(&block)
- @threads ||= []
-
- @threads << Thread.new do
- yield
- end
- end
-
- def self.newtimer(hash, &block)
- timer = nil
- threadlock(:timers) do
- @timers ||= []
- timer = EventLoop::Timer.new(hash)
- @timers << timer
-
- if block_given?
- observe_signal(timer, :alarm, &block)
- end
- end
-
- # In case they need it for something else.
- timer
- end
-
# Parse the config file for this process.
def self.parse_config
if Puppet[:config] and File.exists? Puppet[:config]
@@ -169,165 +124,6 @@ module Puppet
end
end
- # Relaunch the executable.
- def self.restart
- command = $0 + " " + self.args.join(" ")
- Puppet.notice "Restarting with '%s'" % command
- Puppet.shutdown(false)
- Puppet::Util::Log.reopen
- exec(command)
- end
-
- # Trap a couple of the main signals. This should probably be handled
- # in a way that anyone else can register callbacks for traps, but, eh.
- def self.settraps
- [:INT, :TERM].each do |signal|
- trap(signal) do
- Puppet.notice "Caught #{signal}; shutting down"
- Puppet.debug "Signal caught here:"
- caller.each { |l| Puppet.debug l }
- Puppet.shutdown
- end
- end
-
- # Handle restarting.
- trap(:HUP) do
- if client = @services.find { |s| s.is_a? Puppet::Network::Client.master } and client.running?
- client.restart
- else
- Puppet.restart
- end
- end
-
- # Provide a hook for running clients where appropriate
- trap(:USR1) do
- done = 0
- Puppet.notice "Caught USR1; triggering client run"
- @services.find_all { |s| s.is_a? Puppet::Network::Client }.each do |client|
- if client.respond_to? :running?
- if client.running?
- Puppet.info "Ignoring running %s" % client.class
- else
- done += 1
- begin
- client.runnow
- rescue => detail
- Puppet.err "Could not run client: %s" % detail
- end
- end
- else
- Puppet.info "Ignoring %s; cannot test whether it is running" %
- client.class
- end
- end
-
- unless done > 0
- Puppet.notice "No clients were run"
- end
- end
-
- trap(:USR2) do
- Puppet::Util::Log.reopen
- end
- end
-
- # Shutdown our server process, meaning stop all services and all threads.
- # Optionally, exit.
- def self.shutdown(leave = true)
- Puppet.notice "Shutting down"
- # Unmonitor our timers
- defined? @timers and @timers.each do |timer|
- EventLoop.current.ignore_timer timer
- end
-
- # This seems to exit the process, although I can't find where it does
- # so. Leaving it out doesn't seem to hurt anything.
- #if EventLoop.current.running?
- # EventLoop.current.quit
- #end
-
- # Stop our services
- defined? @services and @services.each do |svc|
- next unless svc.respond_to?(:shutdown)
- begin
- timeout(20) do
- svc.shutdown
- end
- rescue TimeoutError
- Puppet.err "%s could not shut down within 20 seconds" % svc.class
- end
- end
-
- # And wait for them all to die, giving a decent amount of time
- defined? @threads and @threads.each do |thr|
- begin
- timeout(20) do
- thr.join
- end
- rescue TimeoutError
- # Just ignore this, since we can't intelligently provide a warning
- end
- end
-
- if leave
- exit(0)
- end
- end
-
- # Start all of our services and optionally our event loop, which blocks,
- # waiting for someone, somewhere, to generate events of some kind.
- def self.start(block = true)
- # Starting everything in its own thread, fwiw
- defined? @services and @services.dup.each do |svc|
- newthread do
- begin
- svc.start
- rescue => detail
- if Puppet[:trace]
- puts detail.backtrace
- end
- @services.delete svc
- Puppet.err "Could not start %s: %s" % [svc.class, detail]
- end
- end
- end
-
- # We need to give the services a chance to register their timers before
- # we try to start monitoring them.
- sleep 0.5
-
- unless @services.length > 0
- Puppet.notice "No remaining services; exiting"
- exit(1)
- end
-
- if defined? @timers and ! @timers.empty?
- @timers.each do |timer|
- EventLoop.current.monitor_timer timer
- end
- end
-
- if block
- EventLoop.current.run
- end
- end
-
- # Create the timer that our different objects (uh, mostly the client)
- # check.
- def self.timer
- unless defined? @timer
- #Puppet.info "Interval is %s" % Puppet[:runinterval]
- #@timer = EventLoop::Timer.new(:interval => Puppet[:runinterval])
- @timer = EventLoop::Timer.new(
- :interval => Puppet[:runinterval],
- :tolerance => 1,
- :start? => true
- )
- EventLoop.current.monitor_timer @timer
- end
- @timer
- end
-
# XXX this should all be done using puppet objects, not using
# normal mkdir
def self.recmkdir(dir,mode = 0755)
diff --git a/lib/puppet/agent.rb b/lib/puppet/agent.rb
index c91552b16..e7d40f68c 100644
--- a/lib/puppet/agent.rb
+++ b/lib/puppet/agent.rb
@@ -1,17 +1,19 @@
require 'sync'
-require 'puppet/daemon'
+require 'puppet/external/event-loop'
# A general class for triggering a run of another
# class.
class Puppet::Agent
- include Puppet::Daemon
-
require 'puppet/agent/locker'
include Puppet::Agent::Locker
- attr_reader :client_class, :client
+ attr_reader :client_class, :client, :needing_restart, :splayed
attr_accessor :stopping
+ def configure_delayed_restart
+ @needing_restart = true
+ end
+
# Just so we can specify that we are "the" instance.
def initialize(client_class)
@splayed = false
@@ -23,6 +25,16 @@ class Puppet::Agent
client_class.lockfile_path
end
+ def needing_restart?
+ @needing_restart
+ end
+
+ def restart
+ configure_delayed_restart and return if running?
+ Process.kill(:HUP, $$)
+ @needing_restart = false
+ end
+
# Perform a run with our client.
def run
if client
@@ -44,7 +56,12 @@ class Puppet::Agent
end
end
- def shutdown
+ # If the client instance is set, we're mid-run.
+ def running?
+ ! client.nil?
+ end
+
+ def stop
if self.stopping?
Puppet.notice "Already in shutdown"
return
@@ -58,8 +75,6 @@ class Puppet::Agent
Puppet.err "Could not stop %s: %s" % [client_class, detail]
end
end
-
- super
ensure
self.stopping = false
end
@@ -70,7 +85,7 @@ class Puppet::Agent
# Have we splayed already?
def splayed?
- @splayed
+ splayed
end
# Sleep when splay is enabled; else just return.
@@ -88,16 +103,12 @@ class Puppet::Agent
# timer events here.
def start
# Create our timer. Puppet will handle observing it and such.
- Puppet.newtimer(
- :interval => Puppet[:runinterval],
- :tolerance => 1,
- :start? => true
- ) do
+ timer = EventLoop::Timer.new(:interval => Puppet[:runinterval], :tolerance => 1, :start? => true) do
run()
end
# Run once before we start following the timer
- run()
+ timer.sound_alarm
end
def sync
diff --git a/lib/puppet/agent/locker.rb b/lib/puppet/agent/locker.rb
index c24fdad64..eaf19177a 100644
--- a/lib/puppet/agent/locker.rb
+++ b/lib/puppet/agent/locker.rb
@@ -30,7 +30,6 @@ module Puppet::Agent::Locker
def lockfile
unless defined?(@lockfile)
- #@lockfile = Puppet::Util::Pidlock.new(Puppet[:puppetdlockfile])
@lockfile = Puppet::Util::Pidlock.new(lockfile_path)
end
diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb
index b0576124e..5f811d897 100755
--- a/lib/puppet/daemon.rb
+++ b/lib/puppet/daemon.rb
@@ -1,10 +1,11 @@
require 'puppet'
require 'puppet/util/pidlock'
+require 'puppet/external/event-loop'
# A module that handles operations common to all daemons. This is included
# into the Server and Client base classes.
-module Puppet::Daemon
- include Puppet::Util
+class Puppet::Daemon
+ attr_accessor :agent, :server, :argv
def daemonname
Puppet[:name]
@@ -17,7 +18,7 @@ module Puppet::Daemon
exit(0)
end
- setpidfile()
+ create_pidfile()
# Get rid of console logging
Puppet::Util::Log.close(:console)
@@ -38,18 +39,42 @@ module Puppet::Daemon
end
end
- # The path to the pid file for this server
+ # Create a pidfile for our daemon, so we can be stopped and others
+ # don't try to start.
+ def create_pidfile
+ Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
+ unless Puppet::Util::Pidlock.new(pidfile).lock
+ raise "Could not create PID file: %s" % [pidfile]
+ end
+ end
+ end
+
+ # Provide the path to our pidfile.
def pidfile
- if Puppet[:pidfile] != ""
- Puppet[:pidfile]
- else
- File.join(Puppet[:rundir], daemonname() + ".pid")
+ Puppet[:pidfile]
+ end
+
+ def reexec
+ raise Puppet::DevError, "Cannot reexec unless ARGV arguments are set" unless argv
+ command = $0 + " " + argv.join(" ")
+ Puppet.notice "Restarting with '%s'" % command
+ stop(:exit => false)
+ exec(command)
+ end
+
+ def reload
+ return unless agent
+ if agent.running?
+ Puppet.notice "Not triggering already-running agent"
+ return
end
+
+ agent.run
end
- # Remove the pid file
- def rmpidfile
- threadlock(:pidfile) do
+ # Remove the pid file for our daemon.
+ def remove_pidfile
+ Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
locker = Puppet::Util::Pidlock.new(pidfile)
if locker.locked?
locker.unlock or Puppet.err "Could not remove PID file %s" % [pidfile]
@@ -57,25 +82,52 @@ module Puppet::Daemon
end
end
- # Create the pid file.
- def setpidfile
- threadlock(:pidfile) do
- unless Puppet::Util::Pidlock.new(pidfile).lock
- Puppet.err("Could not create PID file: %s" % [pidfile])
- exit(74)
- end
+ def restart
+ if agent and agent.running?
+ agent.configure_delayed_restart
+ else
+ reexec
end
end
- # Shut down our server
- def shutdown
- # Remove our pid file
- rmpidfile()
+ def reopen_logs
+ Puppet::Util::Log.reopen
+ end
- # And close all logs except the console.
- Puppet::Util::Log.destinations.reject { |d| d == :console }.each do |dest|
- Puppet::Util::Log.close(dest)
+ # Trap a couple of the main signals. This should probably be handled
+ # in a way that anyone else can register callbacks for traps, but, eh.
+ def set_signal_traps
+ {:INT => :stop, :TERM => :stop, :HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}.each do |signal, method|
+ trap(signal) do
+ Puppet.notice "Caught #{signal}; calling #{method}"
+ send(method)
+ end
end
end
+
+ # Stop everything
+ def stop(args = {:exit => true})
+ server.stop if server
+
+ agent.stop if agent
+
+ remove_pidfile()
+
+ Puppet::Util::Log.close_all
+
+ exit if args[:exit]
+ end
+
+ def start
+ set_signal_traps
+
+ create_pidfile
+
+ raise Puppet::DevError, "Daemons must have an agent, server, or both" unless agent or server
+ agent.start if agent
+ server.start if server
+
+ EventLoop.current.run
+ end
end
diff --git a/lib/puppet/event_manager.rb b/lib/puppet/event_manager.rb
deleted file mode 100644
index 50c489673..000000000
--- a/lib/puppet/event_manager.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-require 'puppet/external/event-loop'
-
-# Manage events related to starting, stopping, and restarting
-# contained services.
-class Puppet::EventManager
- include SignalObserver
-
- attr_reader :services, :threads, :timers
-
- def initialize
- @services = []
- @threads = []
- @timers = []
- end
-
- # Create a new service that we're supposed to run
- def add_service(service)
- @services << service
- end
-
- def newthread(&block)
- @threads << Thread.new { yield }
- end
-
- # Add a timer we need to pay attention to.
- # This is only used by Puppet::Agent at the moment.
- def newtimer(hash, &block)
- timer = EventLoop::Timer.new(hash)
- @timers << timer
-
- if block_given?
- observe_signal(timer, :alarm, &block)
- end
-
- # In case they need it for something else.
- timer
- end
-
- # Reload any services that can be reloaded. Really, this is just
- # meant to trigger an Agent run.
- def reload
- done = 0
- services.find_all { |service| service.respond_to?(:run) }.each do |service|
- if service.running?
- Puppet.notice "Not triggering already-running %s" % service.class
- next
- end
-
- Puppet.notice "Triggering a run of %s" % service.class
-
- done += 1
- begin
- service.run
- rescue => detail
- Puppet.err "Could not run service %s: %s" % [service.class, detail]
- end
- end
-
- unless done > 0
- Puppet.notice "No services were reloaded"
- end
- end
-
- def reopen_logs
- Puppet::Util::Log.reopen
- end
-
- # Relaunch the executable.
- def restart
- if client = @services.find { |s| s.is_a? Puppet::Network::Client.master } and client.running?
- client.restart
- else
- command = $0 + " " + self.args.join(" ")
- Puppet.notice "Restarting with '%s'" % command
- Puppet.shutdown(false)
- Puppet::Util::Log.reopen
- exec(command)
- end
- end
-
- # Trap a couple of the main signals. This should probably be handled
- # in a way that anyone else can register callbacks for traps, but, eh.
- def set_traps
- {:INT => :shutdown, :TERM => :shutdown, :HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}.each do |signal, method|
- trap(signal) do
- Puppet.notice "Caught #{signal}; calling #{method}"
- send(method)
- end
- end
- end
-
- # Shutdown our server process, meaning stop all services and all threads.
- # Optionally, exit.
- def shutdown(leave = true)
- Puppet.notice "Shutting down"
- stop_timers
-
- stop_services
-
- stop_threads
-
- if leave
- exit(0)
- end
- end
-
- # Start all of our services and optionally our event loop, which blocks,
- # waiting for someone, somewhere, to generate events of some kind.
- def start
- start_services
-
- start_timers
-
- EventLoop.current.run
- end
-
- def start_services
- # Starting everything in its own thread. Otherwise
- # we might have one service stop another service from
- # doing things like registering timers.
- @services.dup.each do |svc|
- begin
- svc.start
- rescue => detail
- if Puppet[:trace]
- puts detail.backtrace
- end
- @services.delete svc
- Puppet.err "Could not start %s: %s" % [svc.class, detail]
- end
- end
-
- # We need to give the services a chance to register their timers before
- # we try to start monitoring them.
- sleep 0.5
-
- unless @services.length > 0
- Puppet.notice "No remaining services; exiting"
- exit(1)
- end
- end
-
- def stop_services
- # Stop our services
- services.each do |svc|
- begin
- timeout(20) do
- svc.shutdown
- end
- rescue TimeoutError
- Puppet.err "%s could not shut down within 20 seconds" % svc.class
- end
- end
- end
-
- # Monitor all of the timers that have been set up.
- def start_timers
- timers.each do |timer|
- EventLoop.current.monitor_timer timer
- end
- end
-
- def stop_timers
- # Unmonitor our timers
- timers.each do |timer|
- EventLoop.current.ignore_timer timer
- end
- end
-
- def stop_threads
- # And wait for them all to die, giving a decent amount of time
- threads.each do |thr|
- begin
- timeout(20) do
- thr.join
- end
- rescue TimeoutError
- # Just ignore this, since we can't intelligently provide a warning
- end
- end
- end
-end
diff --git a/lib/puppet/network/http_server/mongrel.rb b/lib/puppet/network/http_server/mongrel.rb
index e9421c781..924c11728 100644
--- a/lib/puppet/network/http_server/mongrel.rb
+++ b/lib/puppet/network/http_server/mongrel.rb
@@ -34,7 +34,6 @@ require 'puppet/network/xmlrpc/server'
require 'puppet/network/http_server'
require 'puppet/network/client_request'
require 'puppet/network/handler'
-require 'puppet/daemon'
require 'resolv'
@@ -51,7 +50,6 @@ require 'resolv'
# </pre>
module Puppet::Network
class HTTPServer::Mongrel < ::Mongrel::HttpHandler
- include Puppet::Daemon
attr_reader :xmlrpc_server
def initialize(handlers)
diff --git a/lib/puppet/network/http_server/webrick.rb b/lib/puppet/network/http_server/webrick.rb
index 568b4e798..0e835d057 100644
--- a/lib/puppet/network/http_server/webrick.rb
+++ b/lib/puppet/network/http_server/webrick.rb
@@ -1,5 +1,4 @@
require 'puppet'
-require 'puppet/daemon'
require 'webrick'
require 'webrick/https'
require 'fcntl'
@@ -16,7 +15,6 @@ module Puppet
# The old-school, pure ruby webrick server, which is the default serving
# mechanism.
class HTTPServer::WEBrick < WEBrick::HTTPServer
- include Puppet::Daemon
include Puppet::SSLCertificates::Support
# Read the CA cert and CRL and populate an OpenSSL::X509::Store
diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb
index b9736f5ac..0af842c8d 100644
--- a/lib/puppet/util/settings.rb
+++ b/lib/puppet/util/settings.rb
@@ -3,6 +3,7 @@ require 'sync'
require 'puppet/transportable'
require 'getoptlong'
+require 'puppet/external/event-loop'
# The class for handling configuration files.
class Puppet::Util::Settings
@@ -46,9 +47,6 @@ class Puppet::Util::Settings
# Generate the list of valid arguments, in a format that GetoptLong can
# understand, and add them to the passed option list.
def addargs(options)
- # Hackish, but acceptable. Copy the current ARGV for restarting.
- Puppet.args = ARGV.dup
-
# Add all of the config parameters as valid options.
self.each { |name, element|
element.getopt_args.each { |args| options << args }
@@ -496,16 +494,9 @@ class Puppet::Util::Settings
end
# Create a timer to check whether the file should be reparsed.
- def settimer
- if Puppet[:filetimeout] > 0
- @timer = Puppet.newtimer(
- :interval => Puppet[:filetimeout],
- :tolerance => 1,
- :start? => true
- ) do
- self.reparse()
- end
- end
+ def set_filetimeout_timer
+ return unless timeout = self[:filetimeout] and timeout > 0
+ EventLoop::Timer.new(:interval => timeout, :tolerance => 1, :start? => true) { self.reparse() }
end
# Convert the settings we manage into a catalog full of resources that model those settings.
@@ -822,7 +813,7 @@ Generated on #{Time.now}.
# Create a timer so that this file will get checked automatically
# and reparsed if necessary.
- settimer()
+ set_filetimeout_timer()
result = Hash.new { |names, name|
names[name] = {}
diff --git a/spec/unit/agent.rb b/spec/unit/agent.rb
index 5622af4a6..03136c484 100755
--- a/spec/unit/agent.rb
+++ b/spec/unit/agent.rb
@@ -45,14 +45,22 @@ describe Puppet::Agent do
@agent.lockfile_path.should == "/my/lock"
end
- describe "when running" do
+ it "should be considered running if a client instance is available" do
+ client = AgentTestClient.new
+ AgentTestClient.expects(:new).returns client
+
+ client.expects(:run).with { @agent.should be_running }
+ @agent.run
+ end
+
+ describe "when being run" do
it "should splay" do
@agent.expects(:splay)
@agent.run
end
- it "should do nothing if a client instance exists" do
+ it "should do nothing if already running" do
@agent.expects(:client).returns "eh"
AgentTestClient.expects(:new).never
@agent.run
@@ -147,10 +155,10 @@ describe Puppet::Agent do
end
end
- describe "when shutting down" do
+ describe "when stopping" do
it "should do nothing if already stopping" do
@agent.expects(:stopping?).returns true
- @agent.shutdown
+ @agent.stop
end
it "should stop the client if one is available and it responds to 'stop'" do
@@ -158,12 +166,7 @@ describe Puppet::Agent do
@agent.stubs(:client).returns client
client.expects(:stop)
- @agent.shutdown
- end
-
- it "should remove its pid file" do
- @agent.expects(:rmpidfile)
- @agent.shutdown
+ @agent.stop
end
it "should mark itself as stopping while waiting for the client to stop" do
@@ -172,34 +175,68 @@ describe Puppet::Agent do
@agent.stubs(:client).returns client
client.expects(:stop).with { @agent.should be_stopping; true }
- @agent.shutdown
+ @agent.stop
end
end
describe "when starting" do
+ before do
+ @agent.stubs(:observe_signal)
+ end
+
it "should create a timer with the runinterval, a tolerance of 1, and :start? set to true" do
Puppet.settings.expects(:value).with(:runinterval).returns 5
- Puppet.expects(:newtimer).with(:interval => 5, :start? => true, :tolerance => 1)
+ timer = stub 'timer', :sound_alarm => nil
+ EventLoop::Timer.expects(:new).with(:interval => 5, :start? => true, :tolerance => 1).returns timer
+
@agent.stubs(:run)
@agent.start
end
it "should run once immediately" do
- Puppet.stubs(:newtimer)
- @agent.expects(:run)
+ timer = mock 'timer'
+ EventLoop::Timer.expects(:new).returns timer
+
+ timer.expects(:sound_alarm)
+
@agent.start
end
it "should run within the block passed to the timer" do
- Puppet.stubs(:newtimer).yields
- @agent.expects(:run).times(2)
+ timer = stub 'timer', :sound_alarm => nil
+ EventLoop::Timer.expects(:new).returns(timer).yields
@agent.start
end
+ end
- it "should run within the block passed to the timer" do
- Puppet.stubs(:newtimer).yields
- @agent.expects(:run).times(2)
- @agent.start
+ describe "when restarting" do
+ it "should configure itself for a delayed restart if currently running" do
+ @agent.expects(:running?).returns true
+
+ @agent.restart
+
+ @agent.should be_needing_restart
+ end
+
+ it "should hup itself if not running" do
+ @agent.expects(:running?).returns false
+
+ Process.expects(:kill).with(:HUP, $$)
+
+ @agent.restart
+ end
+
+ it "should turn off the needing_restart switch" do
+ @agent.expects(:running?).times(2).returns(true).then.returns false
+
+ Process.stubs(:kill)
+
+ # First call sets up the switch
+ @agent.restart
+
+ # Second call should disable it
+ @agent.restart
+ @agent.should_not be_needing_restart
end
end
end
diff --git a/spec/unit/daemon.rb b/spec/unit/daemon.rb
new file mode 100755
index 000000000..0477decb1
--- /dev/null
+++ b/spec/unit/daemon.rb
@@ -0,0 +1,287 @@
+#!/usr/bin/env ruby"
+
+require File.dirname(__FILE__) + '/../spec_helper'
+require 'puppet/daemon'
+
+describe Puppet::Daemon do
+ before do
+ @daemon = Puppet::Daemon.new
+ end
+
+ it "should be able to manage an agent" do
+ @daemon.should respond_to(:agent)
+ end
+
+ it "should be able to manage a network server" do
+ @daemon.should respond_to(:server)
+ end
+
+ it "should reopen the Log logs when told to reopen logs" do
+ Puppet::Util::Log.expects(:reopen)
+ @daemon.reopen_logs
+ end
+
+ describe "when setting signal traps" do
+ before do
+ @daemon.stubs(:trap)
+ end
+
+ {:INT => :stop, :TERM => :stop, :HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}.each do |signal, method|
+ it "should log and call #{method} when it receives #{signal}" do
+ @daemon.expects(:trap).with(signal).yields
+
+ Puppet.expects(:notice)
+
+ @daemon.expects(method)
+
+ @daemon.set_signal_traps
+ end
+ end
+ end
+
+ describe "when starting" do
+ before do
+ @daemon.stubs(:create_pidfile)
+ @daemon.stubs(:set_signal_traps)
+ EventLoop.current.stubs(:run)
+ end
+
+ it "should fail if it has neither agent nor server" do
+ lambda { @daemon.start }.should raise_error(Puppet::DevError)
+ end
+
+ it "should create its pidfile" do
+ @daemon.stubs(:agent).returns stub('agent', :start => nil)
+
+ @daemon.expects(:create_pidfile)
+ @daemon.start
+ end
+
+ it "should start the agent if the agent is configured" do
+ agent = mock 'agent'
+ agent.expects(:start)
+ @daemon.stubs(:agent).returns agent
+
+ @daemon.start
+ end
+
+ it "should start its server if one is configured" do
+ server = mock 'server'
+ server.expects(:start)
+ @daemon.stubs(:server).returns server
+
+ @daemon.start
+ end
+
+ it "should let the current EventLoop run" do
+ @daemon.stubs(:agent).returns stub('agent', :start => nil)
+ EventLoop.current.expects(:run)
+
+ @daemon.start
+ end
+ end
+
+ describe "when stopping" do
+ before do
+ @daemon.stubs(:remove_pidfile)
+ @daemon.stubs(:exit)
+ Puppet::Util::Log.stubs(:close_all)
+ end
+
+ it "should stop its server if one is configured" do
+ server = mock 'server'
+ server.expects(:stop)
+ @daemon.stubs(:server).returns server
+
+ @daemon.stop
+ end
+
+ it "should stop its agent if one is configured" do
+ agent = mock 'agent'
+ agent.expects(:stop)
+ @daemon.stubs(:agent).returns agent
+
+ @daemon.stop
+ end
+
+ it "should remove its pidfile" do
+ @daemon.expects(:remove_pidfile)
+
+ @daemon.stop
+ end
+
+ it "should close all logs" do
+ Puppet::Util::Log.expects(:close_all)
+
+ @daemon.stop
+ end
+
+ it "should exit unless called with ':exit => false'" do
+ @daemon.expects(:exit)
+ @daemon.stop
+ end
+
+ it "should not exit if called with ':exit => false'" do
+ @daemon.expects(:exit).never
+ @daemon.stop :exit => false
+ end
+ end
+
+ describe "when creating its pidfile" do
+ it "should use an exclusive mutex" do
+ Puppet.settings.expects(:value).with(:name).returns "me"
+
+ sync = mock 'sync'
+ Puppet::Util.expects(:sync).with("me").returns sync
+
+ sync.expects(:synchronize).with(Sync::EX)
+ @daemon.create_pidfile
+ end
+
+ it "should lock the pidfile using the Pidlock class" do
+ pidfile = mock 'pidfile'
+
+ Puppet.settings.stubs(:value).with(:name).returns "eh"
+ Puppet.settings.expects(:value).with(:pidfile).returns "/my/file"
+
+ Puppet::Util::Pidlock.expects(:new).with("/my/file").returns pidfile
+
+ pidfile.expects(:lock).returns true
+ @daemon.create_pidfile
+ end
+
+ it "should fail if it cannot lock" do
+ pidfile = mock 'pidfile'
+
+ Puppet.settings.stubs(:value).with(:name).returns "eh"
+ Puppet.settings.stubs(:value).with(:pidfile).returns "/my/file"
+
+ Puppet::Util::Pidlock.expects(:new).with("/my/file").returns pidfile
+
+ pidfile.expects(:lock).returns false
+
+ lambda { @daemon.create_pidfile }.should raise_error
+ end
+ end
+
+ describe "when removing its pidfile" do
+ it "should use an exclusive mutex" do
+ Puppet.settings.expects(:value).with(:name).returns "me"
+
+ sync = mock 'sync'
+ Puppet::Util.expects(:sync).with("me").returns sync
+
+ sync.expects(:synchronize).with(Sync::EX)
+ @daemon.remove_pidfile
+ end
+
+ it "should do nothing if the pidfile is not present" do
+ pidfile = mock 'pidfile', :locked? => false
+ Puppet::Util::Pidlock.expects(:new).with("/my/file").returns pidfile
+
+ Puppet.settings.stubs(:value).with(:name).returns "eh"
+ Puppet.settings.stubs(:value).with(:pidfile).returns "/my/file"
+
+ pidfile.expects(:unlock).never
+ @daemon.remove_pidfile
+ end
+
+ it "should unlock the pidfile using the Pidlock class" do
+ pidfile = mock 'pidfile', :locked? => true
+ Puppet::Util::Pidlock.expects(:new).with("/my/file").returns pidfile
+ pidfile.expects(:unlock).returns true
+
+ Puppet.settings.stubs(:value).with(:name).returns "eh"
+ Puppet.settings.stubs(:value).with(:pidfile).returns "/my/file"
+
+ @daemon.remove_pidfile
+ end
+
+ it "should warn if it cannot remove the pidfile" do
+ pidfile = mock 'pidfile', :locked? => true
+ Puppet::Util::Pidlock.expects(:new).with("/my/file").returns pidfile
+ pidfile.expects(:unlock).returns false
+
+ Puppet.settings.stubs(:value).with(:name).returns "eh"
+ Puppet.settings.stubs(:value).with(:pidfile).returns "/my/file"
+
+ Puppet.expects :err
+ @daemon.remove_pidfile
+ end
+ end
+
+ describe "when reloading" do
+ it "should do nothing if no agent is configured" do
+ @daemon.reload
+ end
+
+ it "should do nothing if the agent is running" do
+ agent = mock 'agent'
+ agent.expects(:running?).returns true
+
+ @daemon.stubs(:agent).returns agent
+
+ @daemon.reload
+ end
+
+ it "should run the agent if one is available and it is not running" do
+ agent = mock 'agent'
+ agent.expects(:running?).returns false
+ agent.expects :run
+
+ @daemon.stubs(:agent).returns agent
+
+ @daemon.reload
+ end
+ end
+
+ describe "when restarting" do
+ it "should reexec itself if no agent is available" do
+ @daemon.expects(:reexec)
+
+ @daemon.restart
+ end
+
+ it "should reexec itself if the agent is not running" do
+ agent = mock 'agent'
+ agent.expects(:running?).returns false
+ @daemon.stubs(:agent).returns agent
+ @daemon.expects(:reexec)
+
+ @daemon.restart
+ end
+
+ it "should configure the agent for later restart if the agent is running" do
+ agent = mock 'agent'
+ agent.expects(:running?).returns true
+ @daemon.stubs(:agent).returns agent
+ @daemon.expects(:reexec).never
+
+ agent.expects(:configure_delayed_restart)
+
+ @daemon.restart
+ end
+ end
+
+ describe "when reexecing it self" do
+ it "should fail if no argv values are available" do
+ @daemon.expects(:argv).returns nil
+ lambda { @daemon.reexec }.should raise_error(Puppet::DevError)
+ end
+
+ it "should shut down without exiting" do
+ @daemon.argv = %w{foo}
+ @daemon.expects(:stop).with(:exit => false)
+
+ @daemon.stubs(:exec)
+ @daemon.reexec
+ end
+
+ it "should call 'exec' with the original executable and arguments" do
+ @daemon.argv = %w{foo}
+ @daemon.expects(:exec).with($0 + " " + "foo")
+
+ @daemon.reexec
+ end
+ end
+end
diff --git a/spec/unit/event_manager.rb b/spec/unit/event_manager.rb
deleted file mode 100755
index e15461c98..000000000
--- a/spec/unit/event_manager.rb
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../spec_helper'
-
-require 'puppet/event_manager'
-require 'puppet/agent'
-
-describe Puppet::EventManager do
- before do
- @manager = Puppet::EventManager.new
- end
-
- it "should include SignalObserver" do
- Puppet::EventManager.ancestors.should be_include(SignalObserver)
- end
-
- it "should should add the provided service to its list of services when a new service is added" do
- @manager.add_service("foo")
- @manager.services.should be_include("foo")
- end
-
- it "should create a new thread and add it to its thread list when a new thread is added" do
- Thread.expects(:new).returns "foo"
- @manager.newthread {}
- @manager.threads.should be_include("foo")
- end
-
- it "should stop all timers, services, and threads, then exit, when asked to shutdown" do
- @manager.expects(:stop_services)
- @manager.expects(:stop_timers)
- @manager.expects(:stop_threads)
-
- @manager.expects(:exit)
-
- @manager.shutdown
- end
-
- it "should tell the event loop to monitor each timer when told to start timers" do
- timer1 = mock 'timer1'
- timer2 = mock 'timer2'
-
- @manager.expects(:timers).returns [timer1, timer2]
-
- EventLoop.current.expects(:monitor_timer).with timer1
- EventLoop.current.expects(:monitor_timer).with timer2
-
- @manager.start_timers
- end
-
- it "should tell the event loop to stop monitoring each timer when told to stop timers" do
- timer1 = mock 'timer1'
- timer2 = mock 'timer2'
-
- @manager.expects(:timers).returns [timer1, timer2]
-
- EventLoop.current.expects(:ignore_timer).with timer1
- EventLoop.current.expects(:ignore_timer).with timer2
-
- @manager.stop_timers
- end
-
- it "should start all services, monitor all timers, and let the current event loop run when told to start" do
- @manager.expects(:start_services)
- @manager.expects(:start_timers)
-
- EventLoop.current.expects(:run)
-
- @manager.start
- end
-
- it "should reopen the Log logs when told to reopen logs" do
- Puppet::Util::Log.expects(:reopen)
- @manager.reopen_logs
- end
-
- describe "when adding a timer" do
- before do
- @timer = mock("timer")
- EventLoop::Timer.stubs(:new).returns @timer
-
- @manager.stubs(:observe_signal)
- end
-
- it "should create and return a new timer with the provided arguments" do
- timer = mock("timer")
- EventLoop::Timer.expects(:new).with(:foo => :bar).returns @timer
-
- @manager.newtimer(:foo => :bar) {}.should equal(@timer)
- end
-
- it "should add the timer to the list of timers" do
- @manager.newtimer(:foo => :bar) {}
-
- @manager.timers.should be_include(@timer)
- end
-
- it "should set up a signal observer for the timer" do
- @manager.expects(:observe_signal).with { |timer, signal, block| timer == @timer and signal == :alarm }
-
- @manager.newtimer(:foo => :bar) {}
- end
- end
-
- describe "when starting services" do
- before do
- @service = stub 'service', :start => nil
- @manager.stubs(:sleep)
- end
-
- it "should start each service" do
- service = mock 'service'
- service.expects(:start)
-
- @manager.add_service service
-
- @manager.start_services
- end
-
- it "should not fail if a service fails to start" do
- service = mock 'service'
- service.expects(:start).raises "eh"
-
- @manager.add_service @service
- @manager.add_service service
-
- lambda { @manager.start_services }.should_not raise_error
- end
-
- it "should delete failed services from its service list" do
- service = mock 'service'
- service.expects(:start).raises "eh"
-
- @manager.add_service @service
- @manager.add_service service
-
- @manager.start_services
-
- @manager.services.should_not be_include(service)
- end
-
-# it "should start each service in a separate thread" do
-# # They don't expect 'start', because we're stubbing 'newthread'
-# service1 = mock 'service1'
-# service2 = mock 'service2'
-#
-# @manager.add_service service1
-# @manager.add_service service2
-#
-# @manager.expects(:newthread).times(2)
-#
-# @manager.start_services
-# end
-
- it "should exit if no services were able to be started" do
- service = mock 'service'
- service.expects(:start).raises "eh"
-
- @manager.add_service service
-
- @manager.expects(:exit).with(1)
-
- lambda { @manager.start_services }.should_not raise_error
- end
- end
-
- describe "when stopping services" do
- it "should use a timeout" do
- @manager.expects(:timeout).with(20)
- @manager.expects(:services).returns %w{foo}
-
- @manager.stop_services
- end
-
- it "should stop each service" do
- service = mock 'service'
- service.expects(:shutdown)
- @manager.expects(:services).returns [service]
-
- @manager.stop_services
- end
-
- it "should log if a timeout is encountered" do
- service = mock 'service'
- service.expects(:shutdown).raises(TimeoutError)
- @manager.expects(:services).returns [service]
-
- Puppet.expects(:err)
-
- @manager.stop_services
- end
- end
-
- describe "when stopping threads" do
- it "should use a timeout" do
- @manager.expects(:timeout).with(20)
- @manager.expects(:threads).returns %w{foo}
-
- @manager.stop_threads
- end
-
- it "should join each thread" do
- thread = mock 'thread'
- thread.expects(:join)
- @manager.expects(:threads).returns [thread]
-
- @manager.stop_threads
- end
-
- it "should not fail if a timeout is encountered" do
- thread = mock 'thread'
- thread.expects(:join).raises(TimeoutError)
- @manager.expects(:threads).returns [thread]
-
- @manager.stop_threads
- end
- end
-
- describe "when setting traps" do
- before do
- @manager.stubs(:trap)
- end
-
- {:INT => :shutdown, :TERM => :shutdown, :HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}.each do |signal, method|
- it "should log and call #{method} when it receives #{signal}" do
- @manager.expects(:trap).with(signal).yields
-
- Puppet.expects(:notice)
-
- @manager.expects(method)
-
- @manager.set_traps
- end
- end
- end
-
- describe "when reloading" do
- it "should run all services that can be run but are not currently running" do
- service = Puppet::Agent.new(String)
-
- @manager.add_service service
-
- service.expects(:running?).returns false
- service.expects(:run)
-
- @manager.reload
- end
-
- it "should not run services that are already running" do
- service = Puppet::Agent.new(String)
-
- @manager.add_service service
-
- service.expects(:running?).returns true
- service.expects(:run).never
-
- @manager.reload
- end
-
- it "should not try to run services that cannot be run" do
- service = "string"
- @manager.add_service service
-
- @manager.reload
- end
- end
-end
diff --git a/spec/unit/network/client.rb b/spec/unit/network/client.rb
index e9467aad0..cea71d1e5 100755
--- a/spec/unit/network/client.rb
+++ b/spec/unit/network/client.rb
@@ -24,7 +24,7 @@ describe Puppet::Network::Client do
Net::HTTP.stubs(:new).returns http
# Pick a random subclass...
- Puppet::Network::Client.master.new :Server => Puppet[:server]
+ Puppet::Network::Client.runner.new :Server => Puppet[:server]
end
end
@@ -39,7 +39,7 @@ describe Puppet::Network::Client do
Net::HTTP.stubs(:new).returns http
# Pick a random subclass...
- Puppet::Network::Client.master.new :Server => Puppet[:server]
+ Puppet::Network::Client.runner.new :Server => Puppet[:server]
end
end
end
diff --git a/spec/unit/util/settings.rb b/spec/unit/util/settings.rb
index a18dd340a..f84c467e2 100755
--- a/spec/unit/util/settings.rb
+++ b/spec/unit/util/settings.rb
@@ -287,6 +287,14 @@ describe Puppet::Util::Settings do
@settings.setdefaults :section, :one => ["ONE", "a"], :two => ["$one TWO", "b"], :three => ["$one $two THREE", "c"]
end
+ it "should set a timer that triggers reparsing" do
+ @settings.expects(:set_filetimeout_timer)
+ file = "/some/file"
+ @settings.expects(:read_file).with(file).returns("[main]")
+
+ @settings.parse(file)
+ end
+
it "should return values set in the configuration file" do
text = "[main]
one = fileval
@@ -844,6 +852,40 @@ describe Puppet::Util::Settings do
end
end
end
+
+ describe "when setting a timer to trigger configuration file reparsing" do
+ before do
+ @settings = Puppet::Util::Settings.new
+ @settings.setdefaults :foo, :filetimeout => [5, "eh"]
+ end
+
+ it "should do nothing if no filetimeout setting is available" do
+ @settings.expects(:value).with(:filetimeout).returns nil
+ EventLoop::Timer.expects(:new).never
+ @settings.set_filetimeout_timer
+ end
+
+ it "should do nothing if the filetimeout setting is not greater than 0" do
+ @settings.expects(:value).with(:filetimeout).returns -2
+ EventLoop::Timer.expects(:new).never
+ @settings.set_filetimeout_timer
+ end
+
+ it "should create a timer with its interval set to the filetimeout, start? set to true, and a tolerance of 1" do
+ @settings.expects(:value).with(:filetimeout).returns 5
+ EventLoop::Timer.expects(:new).with(:interval => 5, :start? => true, :tolerance => 1)
+
+ @settings.set_filetimeout_timer
+ end
+
+ it "should reparse when the timer goes off" do
+ EventLoop::Timer.expects(:new).with(:interval => 5, :start? => true, :tolerance => 1).yields
+
+ @settings.expects(:reparse)
+
+ @settings.set_filetimeout_timer
+ end
+ end
end
describe Puppet::Util::Settings::CFile do
diff --git a/test/network/daemon.rb b/test/network/daemon.rb
deleted file mode 100755
index 5105c6e4c..000000000
--- a/test/network/daemon.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../lib/puppettest'
-
-require 'puppettest'
-require 'puppet/daemon'
-
-class TestDaemon < Test::Unit::TestCase
- include PuppetTest
-
- class FakeDaemon
- include Puppet::Daemon
- end
-
- def test_pidfile
- daemon = FakeDaemon.new
-
- assert_nothing_raised("removing non-existent file failed") do
- daemon.rmpidfile
- end
-
- Puppet[:pidfile] = tempfile()
- assert_nothing_raised "could not lock" do
- daemon.setpidfile
- end
-
- assert(FileTest.exists?(daemon.pidfile),
- "did not create pidfile")
-
- assert_nothing_raised("removing non-existent file failed") do
- daemon.rmpidfile
- end
-
- assert(! FileTest.exists?(daemon.pidfile),
- "did not remove pidfile")
- end
-
- def test_daemonize
- daemon = FakeDaemon.new
- Puppet[:pidfile] = tempfile()
-
- exiter = tempfile()
-
- assert_nothing_raised("Could not fork and daemonize") do
- fork do
- daemon.send(:daemonize)
- # Wait a max of 5 secs
- 50.times do
- if FileTest.exists?(exiter)
- daemon.rmpidfile
- exit(0)
- end
- sleep 0.1
- end
- exit(0)
- end
- end
- sleep(0.1)
- assert(FileTest.exists?(Puppet[:pidfile]),
- "did not create pidfile on daemonize")
-
- File.open(exiter, "w") { |f| f.puts "" }
-
- sleep(0.2)
- assert(! FileTest.exists?(Puppet[:pidfile]),
- "did not remove pidfile on process death")
- end
-end
-
-