summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrice Figureau <brice-puppet@daysofwonder.com>2009-01-18 20:12:53 +0100
committerBrice Figureau <brice-puppet@daysofwonder.com>2009-02-16 20:12:10 +0100
commit8265d6eaf7dd7d4fb2af30363bfbcc698dea1436 (patch)
treed7ff5c50ca2fe0f7036277bf85302e077688f292
parentaf219bf45fe58287f1b46bcfd98dfbe548958b33 (diff)
downloadpuppet-8265d6eaf7dd7d4fb2af30363bfbcc698dea1436.tar.gz
puppet-8265d6eaf7dd7d4fb2af30363bfbcc698dea1436.tar.xz
puppet-8265d6eaf7dd7d4fb2af30363bfbcc698dea1436.zip
Move puppetmasterd to Puppet::Application
Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com>
-rwxr-xr-xbin/puppetmasterd168
-rw-r--r--lib/puppet/application/puppetmasterd.rb138
-rw-r--r--spec/unit/application/puppetmasterd.rb334
3 files changed, 474 insertions, 166 deletions
diff --git a/bin/puppetmasterd b/bin/puppetmasterd
index 3abdb77ea..9f12f678c 100755
--- a/bin/puppetmasterd
+++ b/bin/puppetmasterd
@@ -62,169 +62,5 @@
# Copyright (c) 2005 Reductive Labs, LLC
# Licensed under the GNU Public License
-# Do an initial trap, so that cancels don't get a stack trace.
-trap(:INT) do
- $stderr.puts "Cancelling startup"
- exit(0)
-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 ],
- [ "--logdest", "-l", GetoptLong::REQUIRED_ARGUMENT ],
- [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
- [ "--version", "-V", GetoptLong::NO_ARGUMENT ]
-]
-
-# Add all of the config parameters as valid options.
-Puppet.settings.addargs(options)
-
-result = GetoptLong.new(*options)
-
-options = {
- :setdest => false,
- :verbose => false,
- :debug => false
-}
-
-begin
- result.each { |opt,arg|
- case opt
- # First check to see if the argument is a valid configuration parameter;
- # if so, set it. NOTE: there is a catch-all at the bottom for defaults.rb
- when "--debug"
- options[:debug] = true
- when "--help"
- if Puppet.features.usage?
- RDoc::usage && exit
- else
- puts "No help available unless you have RDoc::usage installed"
- exit
- end
- when "--logdest"
- begin
- Puppet::Util::Log.newdestination(arg)
- options[:setdest] = true
- rescue => detail
- if Puppet[:debug]
- puts detail.backtrace
- end
- $stderr.puts detail.to_s
- end
- when "--version"
- puts "%s" % Puppet.version
- exit
- when "--verbose"
- options[:verbose] = true
- else
- Puppet.settings.handlearg(opt, arg)
- end
- }
-rescue GetoptLong::InvalidOption => detail
- $stderr.puts "Try '#{$0} --help'"
- #$stderr.puts detail
- exit(1)
-end
-
-# Now parse the config
-Puppet.parse_config
-
-# Handle the logging settings.
-if options[:debug] or options[:verbose]
- if options[:debug]
- Puppet::Util::Log.level = :debug
- else
- Puppet::Util::Log.level = :info
- end
-
- unless Puppet[:daemonize]
- Puppet::Util::Log.newdestination(:console)
- options[:setdest] = true
- end
-end
-
-unless options[:setdest]
- Puppet::Util::Log.newdestination(:syslog)
-end
-
-if Puppet.settings.print_configs?
- exit(Puppet.settings.print_configs ? 0 : 1)
-end
-
-Puppet.settings.use :main, :puppetmasterd, :ssl
-
-# A temporary solution, to at least make the master work for now.
-Puppet::Node::Facts.terminus_class = :yaml
-
-# Cache our nodes in yaml. Currently not configurable.
-Puppet::Node.cache_class = :yaml
-
-# Configure all of the SSL stuff.
-if Puppet::SSL::CertificateAuthority.ca?
- Puppet::SSL::Host.ca_location = :local
- Puppet.settings.use :ca
- Puppet::SSL::CertificateAuthority.instance
-else
- Puppet::SSL::Host.ca_location = :none
-end
-
-require 'etc'
-
-if Puppet[:parseonly]
- begin
- Puppet::Parser::Interpreter.new.parser(Puppet[:environment])
- rescue => detail
- Puppet.err detail
- exit 1
- end
- exit(0)
-end
-
-require 'puppet/file_serving/content'
-require 'puppet/file_serving/metadata'
-require 'puppet/checksum'
-
-xmlrpc_handlers = [:Status, :FileServer, :Master, :Report, :Filebucket]
-
-# Just set up serving to all of the indirected classes.
-rest_handlers = Puppet::Indirector::Indirection.instances
-
-if Puppet[:ca]
- xmlrpc_handlers << :CA
-end
-
-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
-
-# And now configure our server to *only* hit the CA for data, because that's
-# all it will have write access to.
-if Puppet::SSL::CertificateAuthority.ca?
- Puppet::SSL::Host.ca_location = :only
-end
-
-if Process.uid == 0
- begin
- Puppet::Util.chuser
- rescue => detail
- puts detail.backtrace if Puppet[:trace]
- $stderr.puts "Could not change user to %s: %s" % [Puppet[:user], detail]
- exit(39)
- end
-end
-
-daemon.daemonize if Puppet[:daemonize]
-
-Puppet.notice "Starting Puppet server version %s" % [Puppet.version]
-
-daemon.start
+require 'puppet/application/puppetmasterd'
+Puppet::Application[:puppetmasterd].run
diff --git a/lib/puppet/application/puppetmasterd.rb b/lib/puppet/application/puppetmasterd.rb
new file mode 100644
index 000000000..b563c0992
--- /dev/null
+++ b/lib/puppet/application/puppetmasterd.rb
@@ -0,0 +1,138 @@
+require 'puppet'
+require 'puppet/application'
+require 'puppet/daemon'
+require 'puppet/network/server'
+
+Puppet::Application.new(:puppetmasterd) do
+
+ should_parse_config
+
+ option("--debug", "-d")
+ option("--verbose", "-v")
+
+ option("--logdest", "-l") do |arg|
+ begin
+ Puppet::Util::Log.newdestination(arg)
+ options[:setdest] = true
+ rescue => detail
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+ $stderr.puts detail.to_s
+ end
+ end
+
+ option("--version", "-V") do |arg|
+ puts "%s" % Puppet.version
+ exit
+ end
+
+ preinit do
+ trap(:INT) do
+ $stderr.puts "Cancelling startup"
+ exit(0)
+ end
+
+ # Create this first-off, so we have ARGV
+ @daemon = Puppet::Daemon.new
+ @daemon.argv = ARGV.dup
+ end
+
+ dispatch do
+ return Puppet[:parseonly] ? :parseonly : :main
+ end
+
+ command(:parseonly) do
+ begin
+ Puppet::Parser::Interpreter.new.parser(Puppet[:environment])
+ rescue => detail
+ Puppet.err detail
+ exit 1
+ end
+ exit(0)
+ end
+
+ command(:main) do
+ require 'etc'
+ require 'puppet/file_serving/content'
+ require 'puppet/file_serving/metadata'
+ require 'puppet/checksum'
+
+ xmlrpc_handlers = [:Status, :FileServer, :Master, :Report, :Filebucket]
+
+ # Just set up serving to all of the indirected classes.
+ rest_handlers = Puppet::Indirector::Indirection.instances
+
+ if Puppet[:ca]
+ xmlrpc_handlers << :CA
+ end
+
+ @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
+
+ # And now configure our server to *only* hit the CA for data, because that's
+ # all it will have write access to.
+ if Puppet::SSL::CertificateAuthority.ca?
+ Puppet::SSL::Host.ca_location = :only
+ end
+
+ if Process.uid == 0
+ begin
+ Puppet::Util.chuser
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ $stderr.puts "Could not change user to %s: %s" % [Puppet[:user], detail]
+ exit(39)
+ end
+ end
+
+ @daemon.daemonize if Puppet[:daemonize]
+
+ Puppet.notice "Starting Puppet server version %s" % [Puppet.version]
+
+ @daemon.start
+ end
+
+ setup do
+ # Handle the logging settings.
+ if options[:debug] or options[:verbose]
+ if options[:debug]
+ Puppet::Util::Log.level = :debug
+ else
+ Puppet::Util::Log.level = :info
+ end
+
+ unless Puppet[:daemonize]
+ Puppet::Util::Log.newdestination(:console)
+ options[:setdest] = true
+ end
+ end
+
+ unless options[:setdest]
+ Puppet::Util::Log.newdestination(:syslog)
+ end
+
+ if Puppet.settings.print_configs?
+ exit(Puppet.settings.print_configs ? 0 : 1)
+ end
+
+ Puppet.settings.use :main, :puppetmasterd, :ssl
+
+ # A temporary solution, to at least make the master work for now.
+ Puppet::Node::Facts.terminus_class = :yaml
+
+ # Cache our nodes in yaml. Currently not configurable.
+ Puppet::Node.cache_class = :yaml
+
+ # Configure all of the SSL stuff.
+ if Puppet::SSL::CertificateAuthority.ca?
+ Puppet::SSL::Host.ca_location = :local
+ Puppet.settings.use :ca
+ Puppet::SSL::CertificateAuthority.instance
+ else
+ Puppet::SSL::Host.ca_location = :none
+ end
+ end
+end
diff --git a/spec/unit/application/puppetmasterd.rb b/spec/unit/application/puppetmasterd.rb
new file mode 100644
index 000000000..773563ac6
--- /dev/null
+++ b/spec/unit/application/puppetmasterd.rb
@@ -0,0 +1,334 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/application/puppetmasterd'
+
+describe "PuppetMaster" do
+ before :each do
+ @puppetmasterd = Puppet::Application[:puppetmasterd]
+ @daemon = stub_everything 'daemon'
+ Puppet::Daemon.stubs(:new).returns(@daemon)
+ end
+
+ it "should ask Puppet::Application to parse Puppet configuration file" do
+ @puppetmasterd.should_parse_config?.should be_true
+ end
+
+ it "should declare a main command" do
+ @puppetmasterd.should respond_to(:main)
+ end
+
+ it "should declare a parseonly command" do
+ @puppetmasterd.should respond_to(:parseonly)
+ end
+
+ it "should declare a preinit block" do
+ @puppetmasterd.should respond_to(:run_preinit)
+ end
+
+ describe "during preinit" do
+ before :each do
+ @puppetmasterd.stubs(:trap)
+ end
+
+ it "should catch INT" do
+ @puppetmasterd.stubs(:trap).with { |arg,block| arg == :INT }
+
+ @puppetmasterd.run_preinit
+ end
+
+ it "should create a Puppet Daemon" do
+ Puppet::Daemon.expects(:new).returns(@daemon)
+
+ @puppetmasterd.run_preinit
+ end
+
+ it "should give ARGV to the Daemon" do
+ argv = stub 'argv'
+ ARGV.stubs(:dup).returns(argv)
+ @daemon.expects(:argv=).with(argv)
+
+ @puppetmasterd.run_preinit
+ end
+
+ end
+
+ [:debug,:verbose].each do |option|
+ it "should declare handle_#{option} method" do
+ @puppetmasterd.should respond_to("handle_#{option}".to_sym)
+ end
+
+ it "should store argument value when calling handle_#{option}" do
+ @puppetmasterd.options.expects(:[]=).with(option, 'arg')
+ @puppetmasterd.send("handle_#{option}".to_sym, 'arg')
+ end
+ end
+
+ describe "when applying options" do
+ it "should exit after printing the version" do
+ @puppetmasterd.stubs(:puts)
+
+ lambda { @puppetmasterd.handle_version(nil) }.should raise_error(SystemExit)
+ end
+
+ it "should set the log destination with --logdest" do
+ Puppet::Log.expects(:newdestination).with("console")
+
+ @puppetmasterd.handle_logdest("console")
+ end
+
+ it "should put the setdest options to true" do
+ @puppetmasterd.options.expects(:[]=).with(:setdest,true)
+
+ @puppetmasterd.handle_logdest("console")
+ end
+ end
+
+ describe "during setup" do
+
+ before :each do
+ Puppet::Log.stubs(:newdestination)
+ Puppet.stubs(:settraps)
+ Puppet::Log.stubs(:level=)
+ Puppet::SSL::CertificateAuthority.stubs(:instance)
+ Puppet::SSL::CertificateAuthority.stubs(:ca?)
+ Puppet.settings.stubs(:use)
+
+ @puppetmasterd.options.stubs(:[]).with(any_parameters)
+ end
+
+ it "should set log level to debug if --debug was passed" do
+ @puppetmasterd.options.stubs(:[]).with(:debug).returns(true)
+
+ Puppet::Log.expects(:level=).with(:debug)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should set log level to info if --verbose was passed" do
+ @puppetmasterd.options.stubs(:[]).with(:verbose).returns(true)
+
+ Puppet::Log.expects(:level=).with(:info)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should set console as the log destination if no --logdest and --daemonize" do
+ @puppetmasterd.stubs(:[]).with(:daemonize).returns(:false)
+
+ Puppet::Log.expects(:newdestination).with(:syslog)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should set syslog as the log destination if no --logdest and not --daemonize" do
+ Puppet::Log.expects(:newdestination).with(:syslog)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should print puppet config if asked to in Puppet config" do
+ @puppetmasterd.stubs(:exit)
+ Puppet.settings.stubs(:print_configs?).returns(true)
+
+ Puppet.settings.expects(:print_configs)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should exit after printing puppet config if asked to in Puppet config" do
+ Puppet.settings.stubs(:print_configs?).returns(true)
+
+ lambda { @puppetmasterd.run_setup }.should raise_error(SystemExit)
+ end
+
+ it "should tell Puppet.settings to use :main,:ssl and :puppetmasterd category" do
+ Puppet.settings.expects(:use).with(:main,:puppetmasterd,:ssl)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should set node facst terminus to yaml" do
+ Puppet::Node::Facts.expects(:terminus_class=).with(:yaml)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should cache class in yaml" do
+ Puppet::Node.expects(:cache_class=).with(:yaml)
+
+ @puppetmasterd.run_setup
+ end
+
+ describe "with no ca" do
+
+ it "should set the ca_location to none" do
+ Puppet::SSL::Host.expects(:ca_location=).with(:none)
+
+ @puppetmasterd.run_setup
+ end
+
+ end
+
+ describe "with a ca configured" do
+
+ before :each do
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true)
+ end
+
+ it "should set the ca_location to local" do
+ Puppet::SSL::Host.expects(:ca_location=).with(:local)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should tell Puppet.settings to use :ca category" do
+ Puppet.settings.expects(:use).with(:ca)
+
+ @puppetmasterd.run_setup
+ end
+
+ it "should instantiate the CertificateAuthority singleton" do
+ Puppet::SSL::CertificateAuthority.expects(:instance)
+
+ @puppetmasterd.run_setup
+ end
+
+
+ end
+
+ end
+
+ describe "when running" do
+
+ it "should dispatch to parseonly if parseonly is set" do
+ Puppet.stubs(:[]).with(:parseonly).returns(true)
+
+ @puppetmasterd.get_command.should == :parseonly
+ end
+
+ it "should dispatch to main if parseonly is not set" do
+ Puppet.stubs(:[]).with(:parseonly).returns(false)
+
+ @puppetmasterd.get_command.should == :main
+ end
+
+ describe "the parseonly command" do
+ before :each do
+ Puppet.stubs(:[]).with(:environment)
+ Puppet.stubs(:[]).with(:manifest).returns("site.pp")
+ @interpreter = stub_everything
+ Puppet.stubs(:err)
+ @puppetmasterd.stubs(:exit)
+ Puppet::Parser::Interpreter.stubs(:new).returns(@interpreter)
+ end
+
+ it "should delegate to the Puppet Parser" do
+
+ @interpreter.expects(:parser)
+
+ @puppetmasterd.parseonly
+ end
+
+ it "should exit with exit code 0 if no error" do
+ @puppetmasterd.expects(:exit).with(0)
+
+ @puppetmasterd.parseonly
+ end
+
+ it "should exit with exit code 1 if error" do
+ @interpreter.stubs(:parser).raises(Puppet::ParseError)
+
+ @puppetmasterd.expects(:exit).with(1)
+
+ @puppetmasterd.parseonly
+ end
+
+ end
+
+ describe "the main command" do
+ before :each do
+ @puppetmasterd.run_preinit
+ @server = stub_everything 'server'
+ Puppet::Network::Server.stubs(:new).returns(@server)
+ Puppet::SSL::Host.stubs(:localhost)
+ Puppet::SSL::CertificateAuthority.stubs(:ca?)
+ Process.stubs(:uid).returns(1000)
+ Puppet.stubs(:service)
+ Puppet.stubs(:[])
+ Puppet.stubs(:notice)
+ Puppet.stubs(:start)
+ end
+
+ it "should create a Server" do
+ Puppet::Network::Server.expects(:new)
+
+ @puppetmasterd.main
+ end
+
+ it "should give the server to the daemon" do
+ @daemon.expects(:server=).with(@server)
+
+ @puppetmasterd.main
+ end
+
+ it "should create the server with the right XMLRPC handlers" do
+ Puppet::Network::Server.expects(:new).with { |args| args[:xmlrpc_handlers] == [:Status, :FileServer, :Master, :Report, :Filebucket]}
+
+ @puppetmasterd.main
+ end
+
+ it "should create the server with a :ca xmlrpc handler if needed" do
+ Puppet.stubs(:[]).with(:ca).returns(true)
+ Puppet::Network::Server.expects(:new).with { |args| args[:xmlrpc_handlers].include?(:CA) }
+
+ @puppetmasterd.main
+ end
+
+ it "should create the server with the right REST handlers" do
+ Puppet::Indirector::Indirection.stubs(:instances).returns("handlers")
+ Puppet::Network::Server.expects(:new).with { |args| args[:handlers] == "handlers"}
+
+ @puppetmasterd.main
+ end
+
+ it "should generate a SSL cert for localhost" do
+ Puppet::SSL::Host.expects(:localhost)
+
+ @puppetmasterd.main
+ end
+
+ it "should make sure to *only* hit the CA for data" do
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true)
+
+ Puppet::SSL::Host.expects(:ca_location=).with(:only)
+
+ @puppetmasterd.main
+ end
+
+ it "should drop privileges if running as root" do
+ Process.stubs(:uid).returns(0)
+
+ Puppet::Util.expects(:chuser)
+
+ @puppetmasterd.main
+ end
+
+ it "should daemonize if needed" do
+ Puppet.stubs(:[]).with(:daemonize).returns(true)
+
+ @daemon.expects(:daemonize)
+
+ @puppetmasterd.main
+ end
+
+ it "should start the service" do
+ @daemon.expects(:start)
+
+ @puppetmasterd.main
+ end
+
+ end
+ end
+end \ No newline at end of file