diff --git a/lib/puppet/executables/client/certhandler.rb b/lib/puppet/executables/client/certhandler.rb index b041397ae..bf3ea167d 100644 --- a/lib/puppet/executables/client/certhandler.rb +++ b/lib/puppet/executables/client/certhandler.rb @@ -1,77 +1,82 @@ module Puppet module Executables module Client class CertHandler attr_writer :wait_for_cert, :one_time attr_reader :new_cert def initialize(wait_time, is_one_time) @wait_for_cert = wait_time @one_time = is_one_time @new_cert = false end # Did we just read a cert? def new_cert? new_cert end # Read, or retrieve if necessary, our certificate. Returns true if we retrieved # a new cert, false if the cert already exists. def read_retrieve #NOTE: ACS this is checking that a file exists, maybe next time just do that? unless read_cert # If we don't already have the certificate, then create a client to # request one. Use the special ca stuff, don't use the normal server and port. retrieve_cert end ! new_cert? end def retrieve_cert caclient = Puppet::Network::Client.ca.new() while true do begin if caclient.request_cert break if read_new_cert else Puppet.notice "Did not receive certificate" if @one_time Puppet.notice "Set to run 'one time'; exiting with no certificate" exit(1) end end rescue StandardError => detail Puppet.err "Could not request certificate: %s" % detail.to_s exit(23) if @one_time end - sleep @wait_for_cert + if @wait_for_cert > 0 + sleep @wait_for_cert + else + Puppet.notice "waitforcert disabled; exiting with no certificate" + exit(1) + end end end def read_cert Puppet::Network::HttpPool.read_cert end def read_new_cert if Puppet::Network::HttpPool.read_cert # If we read it in, then we need to get rid of our existing http connection. # The @new_cert flag will help us do that, in that it provides a way # to notify that the cert status has changed. @new_cert = true Puppet.notice "Got signed certificate" else Puppet.err "Could not read certificates after retrieving them" exit(34) if @one_time end return @new_cert end end end end end diff --git a/spec/unit/executables/client/certhandler.rb b/spec/unit/executables/client/certhandler.rb index 4f8f8139c..69d6de92b 100755 --- a/spec/unit/executables/client/certhandler.rb +++ b/spec/unit/executables/client/certhandler.rb @@ -1,122 +1,135 @@ #!/usr/bin/env ruby Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } require 'puppet/executables/client/certhandler' cert_handler = Puppet::Executables::Client::CertHandler describe cert_handler, "when handling certificates" do before do @caclient = mock('caclient') caclient_class = mock('caclient_class') caclient_class.stubs(:new).returns(@caclient) Puppet::Network::Client.stubs(:ca).returns(caclient_class) end describe "when reading or retrieving the certificate" do before do @handler = cert_handler.new(1,true) end it "should attempt to read the certificate" do @handler.expects(:read_cert).returns true @handler.read_retrieve end it "should delegate to Puppet::Network::HttpPool to read the certificate" do Puppet::Network::HttpPool.expects(:read_cert).returns(true) @handler.read_retrieve end it "should not attempt to retrieve a certificate if one can be read" do @handler.stubs(:read_cert).returns true @handler.expects(:retrieve_cert).never @handler.read_retrieve end it "should attempt to retrieve a certificate if none can be read" do @handler.stubs(:read_cert).returns false @handler.expects(:retrieve_cert) @handler.read_retrieve end it "should delegate to caclient to retrieve a certificate" do @handler.stubs(:read_cert).returns false @caclient.expects(:request_cert).returns(true) @handler.stubs(:read_new_cert).returns(true) @handler.read_retrieve end it "should return true if the certificate exists" do @handler.stubs(:read_cert).returns true @handler.read_retrieve.should be_true end it "should return false when getting a new cert" do #This is the second call to httppool that happens in 'read_new_cert' Puppet::Network::HttpPool.expects(:read_cert).returns(true) @caclient.stubs(:request_cert).returns(true) @handler.stubs(:read_cert).returns(false) @handler.read_retrieve.should be_false end end describe "when waiting for cert" do before do @handler = cert_handler.new(1,false) @handler.stubs(:read_cert).returns false #all waiting for cert tests should loop, which will always happen if sleep is called #yeah, I put the expectation in the setup, deal with it @handler.expects(:sleep).with(1) #This is needed to get out of the loop @handler.stubs(:read_new_cert).returns(true) end it "should loop when the cert request does not return a certificate" do @caclient.stubs(:request_cert).times(2).returns(false).then.returns(true) @handler.retrieve_cert end it "should loop when the cert request raises an Error" do @caclient.stubs(:request_cert).times(2).raises(StandardError, 'Testing').then.returns(true) @handler.retrieve_cert end it "should loop when the new cert can't be read" do @caclient.stubs(:request_cert).returns(true) @handler.stubs(:read_new_cert).times(2).returns(false).then.returns(true) @handler.retrieve_cert end end + describe "when waitforcert is disabled" do + before do + @handler = cert_handler.new(0, false) + @handler.stubs(:read_cert).returns false + end + + it "should exit if the cert request does not return a certificate" do + @caclient.stubs(:request_cert).returns(false) + @handler.expects(:exit).with(1).raises(SystemExit) + lambda { @handler.retrieve_cert }.should raise_error(SystemExit) + end + end + describe "when in one time mode" do before do #true puts us in onetime mode @handler = cert_handler.new(1,true) @handler.stubs(:read_cert).returns false end it "should exit if the cert request does not return a certificate" do @caclient.stubs(:request_cert).returns(false) @handler.expects(:exit).with(1).raises(SystemExit) lambda { @handler.retrieve_cert }.should raise_error(SystemExit) end it "should exit if the cert request raises an exception" do @caclient.stubs(:request_cert).raises(StandardError, 'Testing') @handler.expects(:exit).with(23).raises(SystemExit) lambda { @handler.retrieve_cert }.should raise_error(SystemExit) end it "should exit if the new cert can't be read" do @caclient.stubs(:request_cert).returns(true) #this is the second, call to httppool inside read_new_cert Puppet::Network::HttpPool.stubs(:read_cert).returns(false) @handler.expects(:exit).with(34).raises(SystemExit) lambda { @handler.retrieve_cert }.should raise_error(SystemExit) end end end