diff options
Diffstat (limited to 'spec/unit/application/master_spec_spec.rb')
-rw-r--r-- | spec/unit/application/master_spec_spec.rb | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/spec/unit/application/master_spec_spec.rb b/spec/unit/application/master_spec_spec.rb new file mode 100644 index 000000000..c3f4d9e37 --- /dev/null +++ b/spec/unit/application/master_spec_spec.rb @@ -0,0 +1,447 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/application/master' + +describe Puppet::Application::Master do + before :each do + @master = Puppet::Application[:master] + @daemon = stub_everything 'daemon' + Puppet::Daemon.stubs(:new).returns(@daemon) + Puppet::Util::Log.stubs(:newdestination) + Puppet::Util::Log.stubs(:level=) + + Puppet::Node.stubs(:terminus_class=) + Puppet::Node.stubs(:cache_class=) + Puppet::Node::Facts.stubs(:terminus_class=) + Puppet::Node::Facts.stubs(:cache_class=) + Puppet::Transaction::Report.stubs(:terminus_class=) + Puppet::Resource::Catalog.stubs(:terminus_class=) + end + + it "should ask Puppet::Application to parse Puppet configuration file" do + @master.should_parse_config?.should be_true + end + + it "should declare a main command" do + @master.should respond_to(:main) + end + + it "should declare a parseonly command" do + @master.should respond_to(:parseonly) + end + + it "should declare a compile command" do + @master.should respond_to(:compile) + end + + it "should declare a preinit block" do + @master.should respond_to(:preinit) + end + + describe "during preinit" do + before :each do + @master.stubs(:trap) + end + + it "should catch INT" do + @master.stubs(:trap).with { |arg,block| arg == :INT } + + @master.preinit + end + + it "should create a Puppet Daemon" do + Puppet::Daemon.expects(:new).returns(@daemon) + + @master.preinit + end + + it "should give ARGV to the Daemon" do + argv = stub 'argv' + ARGV.stubs(:dup).returns(argv) + @daemon.expects(:argv=).with(argv) + + @master.preinit + end + + end + + [:debug,:verbose].each do |option| + it "should declare handle_#{option} method" do + @master.should respond_to("handle_#{option}".to_sym) + end + + it "should store argument value when calling handle_#{option}" do + @master.options.expects(:[]=).with(option, 'arg') + @master.send("handle_#{option}".to_sym, 'arg') + end + end + + describe "when applying options" do + before do + @master.command_line.stubs(:args).returns([]) + end + + it "should set the log destination with --logdest" do + Puppet::Log.expects(:newdestination).with("console") + + @master.handle_logdest("console") + end + + it "should put the setdest options to true" do + @master.options.expects(:[]=).with(:setdest,true) + + @master.handle_logdest("console") + end + + it "should parse the log destination from ARGV" do + @master.command_line.stubs(:args).returns(%w[--logdest /my/file]) + + Puppet::Util::Log.expects(:newdestination).with("/my/file") + + @master.parse_options + 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) + + @master.options.stubs(:[]).with(any_parameters) + end + + it "should set log level to debug if --debug was passed" do + @master.options.stubs(:[]).with(:debug).returns(true) + + Puppet::Log.expects(:level=).with(:debug) + + @master.setup + end + + it "should set log level to info if --verbose was passed" do + @master.options.stubs(:[]).with(:verbose).returns(true) + + Puppet::Log.expects(:level=).with(:info) + + @master.setup + end + + it "should set console as the log destination if no --logdest and --daemonize" do + @master.stubs(:[]).with(:daemonize).returns(:false) + + Puppet::Log.expects(:newdestination).with(:syslog) + + @master.setup + end + + it "should set syslog as the log destination if no --logdest and not --daemonize" do + Puppet::Log.expects(:newdestination).with(:syslog) + + @master.setup + end + + it "should set syslog as the log destination if --rack" do + @master.options.stubs(:[]).with(:rack).returns(:true) + + Puppet::Log.expects(:newdestination).with(:syslog) + + @master.setup + end + + it "should print puppet config if asked to in Puppet config" do + @master.stubs(:exit) + Puppet.settings.stubs(:print_configs?).returns(true) + + Puppet.settings.expects(:print_configs) + + @master.setup + end + + it "should exit after printing puppet config if asked to in Puppet config" do + Puppet.settings.stubs(:print_configs?).returns(true) + + lambda { @master.setup }.should raise_error(SystemExit) + end + + it "should tell Puppet.settings to use :main,:ssl and :master category" do + Puppet.settings.expects(:use).with(:main,:master,:ssl) + + @master.setup + end + + it "should cache class in yaml" do + Puppet::Node.expects(:cache_class=).with(:yaml) + + @master.setup + end + + describe "with no ca" do + + it "should set the ca_location to none" do + Puppet::SSL::Host.expects(:ca_location=).with(:none) + + @master.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) + + @master.setup + end + + it "should tell Puppet.settings to use :ca category" do + Puppet.settings.expects(:use).with(:ca) + + @master.setup + end + + it "should instantiate the CertificateAuthority singleton" do + Puppet::SSL::CertificateAuthority.expects(:instance) + + @master.setup + end + + + end + + end + + describe "when running" do + before do + @master.preinit + end + + it "should dispatch to parseonly if parseonly is set" do + Puppet.stubs(:[]).with(:parseonly).returns(true) + @master.options[:node] = nil + + @master.expects(:parseonly) + @master.run_command + end + + it "should dispatch to compile if called with --compile" do + @master.options[:node] = "foo" + @master.expects(:compile) + @master.run_command + end + + it "should dispatch to main if parseonly is not set" do + Puppet.stubs(:[]).with(:parseonly).returns(false) + @master.options[:node] = nil + + @master.expects(:main) + @master.run_command + end + + + describe "the parseonly command" do + before :each do + Puppet.stubs(:[]).with(:environment) + Puppet.stubs(:[]).with(:manifest).returns("site.pp") + Puppet.stubs(:err) + @master.stubs(:exit) + @collection = stub_everything + Puppet::Resource::TypeCollection.stubs(:new).returns(@collection) + end + + it "should use a Puppet Resource Type Collection to parse the file" do + @collection.expects(:perform_initial_import) + @master.parseonly + end + + it "should exit with exit code 0 if no error" do + @master.expects(:exit).with(0) + @master.parseonly + end + + it "should exit with exit code 1 if error" do + @collection.stubs(:perform_initial_import).raises(Puppet::ParseError) + @master.expects(:exit).with(1) + @master.parseonly + end + end + + describe "the compile command" do + before do + Puppet.stubs(:[]).with(:environment) + Puppet.stubs(:[]).with(:manifest).returns("site.pp") + Puppet.stubs(:err) + @master.stubs(:jj) + @master.stubs(:exit) + Puppet.features.stubs(:pson?).returns true + end + + it "should fail if pson isn't available" do + Puppet.features.expects(:pson?).returns false + lambda { @master.compile }.should raise_error + end + + it "should compile a catalog for the specified node" do + @master.options[:node] = "foo" + Puppet::Resource::Catalog.expects(:find).with("foo").returns Puppet::Resource::Catalog.new + $stdout.stubs(:puts) + + @master.compile + end + + it "should convert the catalog to a pure-resource catalog and use 'jj' to pretty-print the catalog" do + catalog = Puppet::Resource::Catalog.new + Puppet::Resource::Catalog.expects(:find).returns catalog + + catalog.expects(:to_resource).returns("rescat") + + @master.options[:node] = "foo" + @master.expects(:jj).with("rescat") + + @master.compile + end + + it "should exit with error code 30 if no catalog can be found" do + @master.options[:node] = "foo" + Puppet::Resource::Catalog.expects(:find).returns nil + @master.expects(:exit).with(30) + $stderr.expects(:puts) + + @master.compile + end + + it "should exit with error code 30 if there's a failure" do + @master.options[:node] = "foo" + Puppet::Resource::Catalog.expects(:find).raises ArgumentError + @master.expects(:exit).with(30) + $stderr.expects(:puts) + + @master.compile + end + end + + describe "the main command" do + before :each do + @master.preinit + @server = stub_everything 'server' + Puppet::Network::Server.stubs(:new).returns(@server) + @app = stub_everything 'app' + 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) + + @master.main + end + + it "should give the server to the daemon" do + @daemon.expects(:server=).with(@server) + + @master.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]} + + @master.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) } + + @master.main + end + + it "should generate a SSL cert for localhost" do + Puppet::SSL::Host.expects(:localhost) + + @master.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) + + @master.main + end + + it "should drop privileges if running as root" do + Puppet.features.stubs(:root?).returns true + + Puppet::Util.expects(:chuser) + + @master.main + end + + it "should daemonize if needed" do + Puppet.stubs(:[]).with(:daemonize).returns(true) + + @daemon.expects(:daemonize) + + @master.main + end + + it "should start the service" do + @daemon.expects(:start) + + @master.main + end + + describe "with --rack" do + confine "Rack is not available" => Puppet.features.rack? + + before do + require 'puppet/network/http/rack' + Puppet::Network::HTTP::Rack.stubs(:new).returns(@app) + end + + it "it should create the app with REST and XMLRPC support" do + @master.options.stubs(:[]).with(:rack).returns(:true) + + Puppet::Network::HTTP::Rack.expects(:new).with { |args| + args[:xmlrpc_handlers] == [:Status, :FileServer, :Master, :Report, :Filebucket] and + args[:protocols] == [:rest, :xmlrpc] + } + + @master.main + end + + it "it should not start a daemon" do + @master.options.stubs(:[]).with(:rack).returns(:true) + + @daemon.expects(:start).never + + @master.main + end + + it "it should return the app" do + @master.options.stubs(:[]).with(:rack).returns(:true) + + app = @master.main + app.should equal(@app) + end + + end + + end + end +end |