diff options
Diffstat (limited to 'spec/integration')
-rwxr-xr-x | spec/integration/bin/puppetmasterd.rb | 109 | ||||
-rwxr-xr-x | spec/integration/defaults.rb | 13 | ||||
-rwxr-xr-x | spec/integration/file_serving/configuration.rb | 4 | ||||
-rwxr-xr-x | spec/integration/indirector/rest.rb | 63 | ||||
-rwxr-xr-x | spec/integration/network/server/webrick.rb | 38 | ||||
-rwxr-xr-x | spec/integration/node/catalog.rb | 2 | ||||
-rwxr-xr-x | spec/integration/node/facts.rb | 6 | ||||
-rwxr-xr-x | spec/integration/ssl/certificate_authority.rb | 137 | ||||
-rwxr-xr-x | spec/integration/ssl/certificate_request.rb | 57 | ||||
-rwxr-xr-x | spec/integration/ssl/certificate_revocation_list.rb | 42 | ||||
-rwxr-xr-x | spec/integration/ssl/host.rb | 90 | ||||
-rwxr-xr-x | spec/integration/transaction/report.rb | 2 |
12 files changed, 526 insertions, 37 deletions
diff --git a/spec/integration/bin/puppetmasterd.rb b/spec/integration/bin/puppetmasterd.rb new file mode 100755 index 000000000..447344472 --- /dev/null +++ b/spec/integration/bin/puppetmasterd.rb @@ -0,0 +1,109 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +describe "puppetmasterd" do + before do + # Get a safe temporary file + file = Tempfile.new("puppetmaster_integration_testing") + @dir = file.path + file.delete + + Dir.mkdir(@dir) + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + Puppet[:certdnsnames] = "localhost" + + @@port = 12345 + end + + after { + stop + + Puppet::SSL::Host.ca_location = :none + + system("rm -rf %s" % @dir) + Puppet.settings.clear + } + + def arguments + rundir = File.join(Puppet[:vardir], "run") + @pidfile = File.join(rundir, "testing.pid") + args = "" + args += " --confdir %s" % Puppet[:confdir] + args += " --rundir %s" % rundir + args += " --pidfile %s" % @pidfile + args += " --vardir %s" % Puppet[:vardir] + args += " --certdnsnames %s" % Puppet[:certdnsnames] + args += " --masterport %s" % @@port + args += " --user %s" % Puppet::Util::SUIDManager.uid + args += " --group %s" % Puppet::Util::SUIDManager.gid + args += " --autosign true" + end + + def start(addl_args = "") + Puppet.settings.mkdir(:manifestdir) + Puppet.settings.write(:manifest) do |f| + f.puts { "notify { testing: }" } + end + + args = arguments + addl_args + + output = %x{puppetmasterd #{args}}.chomp + end + + def stop + if @pidfile and FileTest.exist?(@pidfile) + pid = File.read(@pidfile).chomp.to_i + Process.kill(:TERM, pid) + end + end + + it "should create a PID file" do + start + + FileTest.exist?(@pidfile).should be_true + end + + it "should be serving status information over REST" + + it "should be serving status information over xmlrpc" do + start + + sleep 0.5 + + client = Puppet::Network::Client.status.new(:Server => "localhost", :Port => @@port) + + FileUtils.mkdir_p(File.dirname(Puppet[:autosign])) + File.open(Puppet[:autosign], "w") { |f| + f.puts Puppet[:certname] + } + + client.cert + retval = client.status + + retval.should == 1 + end + + it "should exit with return code 0 after parsing if --parseonly is set and there are no errors" do + start(" --parseonly > /dev/null") + sleep(1) + + ps = Facter["ps"].value || "ps -ef" + pid = nil + %x{#{ps}}.chomp.split(/\n/).each { |line| + next if line =~ /^puppet/ # skip normal master procs + if line =~ /puppetmasterd.+--manifest/ + ary = line.split(" ") + pid = ary[1].to_i + end + } + + $?.should == 0 + + pid.should be_nil + end + + it "should exit with return code 1 after parsing if --parseonly is set and there are errors" +end diff --git a/spec/integration/defaults.rb b/spec/integration/defaults.rb index b14a141fb..b6f6bf109 100755 --- a/spec/integration/defaults.rb +++ b/spec/integration/defaults.rb @@ -5,13 +5,20 @@ require File.dirname(__FILE__) + '/../spec_helper' require 'puppet/defaults' describe "Puppet defaults" do - describe "when setting the :factpath" do - after { Puppet.settings.clear } - + after { Puppet.settings.clear } + describe "when configuring the :crl" do it "should add the :factpath to Facter's search paths" do Facter.expects(:search).with("/my/fact/path") Puppet.settings[:factpath] = "/my/fact/path" end end + + describe "when setting the :factpath" do + + it "should warn if :cacrl is set to false" do + Puppet.expects(:warning) + Puppet.settings[:cacrl] = 'false' + end + end end diff --git a/spec/integration/file_serving/configuration.rb b/spec/integration/file_serving/configuration.rb index 6975594a8..cb5a23d3b 100755 --- a/spec/integration/file_serving/configuration.rb +++ b/spec/integration/file_serving/configuration.rb @@ -10,7 +10,7 @@ require 'puppet/file_serving/configuration' describe Puppet::FileServing::Configuration, " when finding files with Puppet::FileServing::Mount" do before do # Just in case it already exists. - Puppet::FileServing::Configuration.clear_cache + Puppet::Util::Cacher.invalidate @mount = Puppet::FileServing::Mount.new("mymount") FileTest.stubs(:exists?).with("/my/path").returns(true) @@ -38,6 +38,6 @@ describe Puppet::FileServing::Configuration, " when finding files with Puppet::F end after do - Puppet::FileServing::Configuration.clear_cache + Puppet::Util::Cacher.invalidate end end diff --git a/spec/integration/indirector/rest.rb b/spec/integration/indirector/rest.rb index 7edd0b865..584fedde0 100755 --- a/spec/integration/indirector/rest.rb +++ b/spec/integration/indirector/rest.rb @@ -31,19 +31,42 @@ end describe Puppet::Indirector::REST do + before do + Puppet[:masterport] = 34343 + Puppet[:server] = "localhost" + + # Get a safe temporary file + @tmpfile = Tempfile.new("webrick_integration_testing") + @dir = @tmpfile.path + "_dir" + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + Puppet.settings[:http_enable_post_connection_check] = false + + Puppet::SSL::Host.ca_location = :local + + Puppet::TestIndirectedFoo.terminus_class = :rest + Puppet::TestIndirectedFoo.indirection.terminus.stubs(:rest_connection_details).returns(:host => "127.0.0.1", :port => "34343") + end + + after do + Puppet::Network::HttpPool.instance_variable_set("@ssl_host", nil) + end + describe "when using webrick" do before :each do + Puppet::Util::Cacher.invalidate + Puppet[:servertype] = 'webrick' - @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :test_indirected_foo ] } - @server = Puppet::Network::Server.new(@params) - @server.listen + Puppet[:server] = '127.0.0.1' + Puppet[:certname] = '127.0.0.1' - # the autoloader was clearly not written test-first. We subvert the integration test to get around its bullshit. - Puppet::Indirector::Terminus.stubs(:terminus_class).returns(Puppet::TestIndirectedFoo::Rest) - Puppet::TestIndirectedFoo.indirection.stubs(:terminus_class).returns :rest + ca = Puppet::SSL::CertificateAuthority.new + ca.generate(Puppet[:certname]) unless Puppet::SSL::Certificate.find(Puppet[:certname]) - # Stub the connection information. - Puppet::TestIndirectedFoo.indirection.terminus(:rest).stubs(:rest_connection_details).returns(:host => "localhost", :port => 34343) + @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :test_indirected_foo ], :xmlrpc_handlers => [ :status ] } + @server = Puppet::Network::Server.new(@params) + @server.listen end describe "when finding a model instance over REST" do @@ -118,7 +141,7 @@ describe Puppet::Indirector::REST do end it 'should return the instance of the model class associated with the provided lookup key' do - Puppet::TestIndirectedFoo.search('bar').collect(&:value).should == @model_instances.collect(&:value) + Puppet::TestIndirectedFoo.search('bar').collect { |i| i.value }.should == @model_instances.collect { |i| i.value } end it 'should set a version timestamp on model instances' do @@ -251,15 +274,19 @@ describe Puppet::Indirector::REST do before :each do Puppet[:servertype] = 'mongrel' @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :test_indirected_foo ] } + + # Make sure we never get a cert, since mongrel can't speak ssl + Puppet::SSL::Certificate.stubs(:find).returns nil + + # We stub ssl to be off, since mongrel can't speak ssl + Net::HTTP.any_instance.stubs(:use_ssl?).returns false + @server = Puppet::Network::Server.new(@params) @server.listen + end - # the autoloader was clearly not written test-first. We subvert the integration test to get around its bullshit. - Puppet::Indirector::Terminus.stubs(:terminus_class).returns(Puppet::TestIndirectedFoo::Rest) - Puppet::TestIndirectedFoo.indirection.stubs(:terminus_class).returns :rest - - # Stub the connection information. - Puppet::TestIndirectedFoo.indirection.terminus(:rest).stubs(:rest_connection_details).returns(:host => "localhost", :port => 34343) + after do + @server.unlisten end describe "when finding a model instance over REST" do @@ -334,7 +361,7 @@ describe Puppet::Indirector::REST do end it 'should return the instance of the model class associated with the provided lookup key' do - Puppet::TestIndirectedFoo.search('bar').collect(&:value).should == @model_instances.collect(&:value) + Puppet::TestIndirectedFoo.search('bar').collect { |i| i.value }.should == @model_instances.collect { |i| i.value } end it 'should set an expiration on model instances' do @@ -456,9 +483,5 @@ describe Puppet::Indirector::REST do end end end - - after :each do - @server.unlisten - end end end diff --git a/spec/integration/network/server/webrick.rb b/spec/integration/network/server/webrick.rb index 41714271f..e74920782 100755 --- a/spec/integration/network/server/webrick.rb +++ b/spec/integration/network/server/webrick.rb @@ -2,46 +2,68 @@ require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/network/server' +require 'puppet/ssl/certificate_authority' require 'socket' describe Puppet::Network::Server do describe "when using webrick" do before :each do Puppet[:servertype] = 'webrick' - @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :node ] } + @params = { :address => "127.0.0.1", :port => 34343, :handlers => [ :node ], :xmlrpc_handlers => [ :status ] } + + # Get a safe temporary file + @tmpfile = Tempfile.new("webrick_integration_testing") + @dir = @tmpfile.path + "_dir" + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + + Puppet::SSL::Host.ca_location = :local + + ca = Puppet::SSL::CertificateAuthority.new + ca.generate(Puppet[:certname]) unless Puppet::SSL::Certificate.find(Puppet[:certname]) + end + + after do + @tmpfile.delete + Puppet.settings.clear + + system("rm -rf %s" % @dir) + + Puppet::Util::Cacher.invalidate end - + describe "before listening" do it "should not be reachable at the specified address and port" do lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error end end - + describe "when listening" do it "should be reachable on the specified address and port" do @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) @server.listen lambda { TCPSocket.new('127.0.0.1', 34343) }.should_not raise_error end - + it "should not allow multiple servers to listen on the same address and port" do @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) @server.listen @server2 = Puppet::Network::Server.new(@params.merge(:port => 34343)) lambda { @server2.listen }.should raise_error end - + after :each do @server.unlisten if @server.listening? end end - + describe "after unlistening" do it "should not be reachable on the port and address assigned" do - @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) + @server = Puppet::Network::Server.new(@params.merge(:port => 34343)) @server.listen @server.unlisten - lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error(Errno::ECONNREFUSED) + lambda { TCPSocket.new('127.0.0.1', 34343) }.should raise_error(Errno::ECONNREFUSED) end end end diff --git a/spec/integration/node/catalog.rb b/spec/integration/node/catalog.rb index 941d2cc6c..285b85869 100755 --- a/spec/integration/node/catalog.rb +++ b/spec/integration/node/catalog.rb @@ -7,13 +7,13 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe Puppet::Node::Catalog do describe "when using the indirector" do + after { Puppet::Util::Cacher.invalidate } before do # This is so the tests work w/out networking. Facter.stubs(:to_hash).returns({"hostname" => "foo.domain.com"}) Facter.stubs(:value).returns("eh") end - after { Puppet::Node::Catalog.indirection.clear_cache } it "should be able to delegate to the :yaml terminus" do Puppet::Node::Catalog.indirection.stubs(:terminus_class).returns :yaml diff --git a/spec/integration/node/facts.rb b/spec/integration/node/facts.rb index c2f876578..cef3d79d4 100755 --- a/spec/integration/node/facts.rb +++ b/spec/integration/node/facts.rb @@ -7,13 +7,15 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe Puppet::Node::Facts do describe "when using the indirector" do - after { Puppet::Node::Facts.indirection.clear_cache } + after { Puppet::Util::Cacher.invalidate } it "should expire any cached node instances when it is saved" do Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml + + Puppet::Node::Facts.indirection.terminus(:yaml).should equal(Puppet::Node::Facts.indirection.terminus(:yaml)) terminus = Puppet::Node::Facts.indirection.terminus(:yaml) + terminus.stubs :save - terminus.expects(:save) Puppet::Node.expects(:expire).with("me") facts = Puppet::Node::Facts.new("me") diff --git a/spec/integration/ssl/certificate_authority.rb b/spec/integration/ssl/certificate_authority.rb new file mode 100755 index 000000000..d838bc586 --- /dev/null +++ b/spec/integration/ssl/certificate_authority.rb @@ -0,0 +1,137 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2008-4-17. +# Copyright (c) 2008. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/ssl/certificate_authority' +require 'tempfile' + +describe Puppet::SSL::CertificateAuthority do + before do + # Get a safe temporary file + file = Tempfile.new("ca_integration_testing") + @dir = file.path + file.delete + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + + Puppet::SSL::Host.ca_location = :local + @ca = Puppet::SSL::CertificateAuthority.new + end + + after { + Puppet::SSL::Host.ca_location = :none + + system("rm -rf %s" % @dir) + Puppet.settings.clear + + Puppet::Util::Cacher.invalidate + + Puppet::SSL::CertificateAuthority.instance_variable_set("@instance", nil) + } + + it "should create a CA host" do + @ca.host.should be_ca + end + + it "should be able to generate a certificate" do + @ca.generate_ca_certificate + + @ca.host.certificate.should be_instance_of(Puppet::SSL::Certificate) + end + + it "should be able to generate a new host certificate" do + @ca.generate("newhost") + + Puppet::SSL::Certificate.find("newhost").should be_instance_of(Puppet::SSL::Certificate) + end + + it "should be able to revoke a host certificate" do + pending("This test doesn't actually work yet") do + @ca.generate("newhost") + + @ca.revoke("newhost") + + lambda { @ca.verify("newhost") }.should raise_error + end + end + + it "should have a CRL" do + @ca.generate_ca_certificate + @ca.crl.should_not be_nil + end + + it "should be able to read in a previously created CRL" do + @ca.generate_ca_certificate + + # Create it to start with. + @ca.crl + + Puppet::SSL::CertificateAuthority.new.crl.should_not be_nil + end + + describe "when signing certificates" do + before do + @host = Puppet::SSL::Host.new("luke.madstop.com") + + # We have to provide the key, since when we're in :ca_only mode, we can only interact + # with the CA key. + key = Puppet::SSL::Key.new(@host.name) + key.generate + + @host.key = key + @host.generate_certificate_request + + path = File.join(Puppet[:requestdir], "luke.madstop.com.pem") + end + + it "should be able to sign certificates" do + @ca.sign("luke.madstop.com") + end + + it "should save the signed certificate" do + @ca.sign("luke.madstop.com") + + Puppet::SSL::Certificate.find("luke.madstop.com").should be_instance_of(Puppet::SSL::Certificate) + end + + it "should be able to sign multiple certificates" do + @other = Puppet::SSL::Host.new("other.madstop.com") + okey = Puppet::SSL::Key.new(@other.name) + okey.generate + @other.key = okey + @other.generate_certificate_request + + @ca.sign("luke.madstop.com") + @ca.sign("other.madstop.com") + + Puppet::SSL::Certificate.find("other.madstop.com").should be_instance_of(Puppet::SSL::Certificate) + Puppet::SSL::Certificate.find("luke.madstop.com").should be_instance_of(Puppet::SSL::Certificate) + end + + it "should save the signed certificate to the :signeddir" do + @ca.sign("luke.madstop.com") + + client_cert = File.join(Puppet[:signeddir], "luke.madstop.com.pem") + File.read(client_cert).should == Puppet::SSL::Certificate.find("luke.madstop.com").content.to_s + end + + it "should save valid certificates" do + @ca.sign("luke.madstop.com") + + ssl = %x{which openssl} + + unless ssl + pending "No ssl available" + else + ca_cert = Puppet[:cacert] + client_cert = File.join(Puppet[:signeddir], "luke.madstop.com.pem") + output = %x{openssl verify -CAfile #{ca_cert} #{client_cert}} + $?.should == 0 + end + end + end +end diff --git a/spec/integration/ssl/certificate_request.rb b/spec/integration/ssl/certificate_request.rb new file mode 100755 index 000000000..f428718e7 --- /dev/null +++ b/spec/integration/ssl/certificate_request.rb @@ -0,0 +1,57 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2008-4-17. +# Copyright (c) 2008. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/ssl/certificate_request' +require 'tempfile' + +describe Puppet::SSL::CertificateRequest do + before do + # Get a safe temporary file + file = Tempfile.new("csr_integration_testing") + @dir = file.path + file.delete + + Puppet.settings.clear + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + + @csr = Puppet::SSL::CertificateRequest.new("luke.madstop.com") + + @key = OpenSSL::PKey::RSA.new(512) + end + + after do + system("rm -rf %s" % @dir) + Puppet.settings.clear + + # This is necessary so the terminus instances don't lie around. + Puppet::Util::Cacher.invalidate + end + + it "should be able to generate CSRs" do + @csr.generate(@key) + end + + it "should be able to save CSRs" do + @csr.save + end + + it "should be able to find saved certificate requests via the Indirector" do + @csr.generate(@key) + @csr.save + + Puppet::SSL::CertificateRequest.find("luke.madstop.com").should be_instance_of(Puppet::SSL::CertificateRequest) + end + + it "should save the completely CSR when saving" do + @csr.generate(@key) + @csr.save + + Puppet::SSL::CertificateRequest.find("luke.madstop.com").content.to_s.should == @csr.content.to_s + end +end diff --git a/spec/integration/ssl/certificate_revocation_list.rb b/spec/integration/ssl/certificate_revocation_list.rb new file mode 100755 index 000000000..246654816 --- /dev/null +++ b/spec/integration/ssl/certificate_revocation_list.rb @@ -0,0 +1,42 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2008-5-5. +# Copyright (c) 2008. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/ssl/certificate_revocation_list' +require 'tempfile' + +describe Puppet::SSL::CertificateRevocationList do + before do + # Get a safe temporary file + file = Tempfile.new("ca_integration_testing") + @dir = file.path + file.delete + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + + Puppet::SSL::Host.ca_location = :local + end + + after { + Puppet::SSL::Host.ca_location = :none + + system("rm -rf %s" % @dir) + Puppet.settings.clear + + # This is necessary so the terminus instances don't lie around. + Puppet::Util::Cacher.invalidate + } + + it "should be able to read in written out CRLs with no revoked certificates" do + ca = Puppet::SSL::CertificateAuthority.new + + raise "CRL not created" unless FileTest.exist?(Puppet[:hostcrl]) + + crl = Puppet::SSL::CertificateRevocationList.new("crl_int_testing") + crl.read(Puppet[:hostcrl]) + end +end diff --git a/spec/integration/ssl/host.rb b/spec/integration/ssl/host.rb new file mode 100755 index 000000000..65f10cef3 --- /dev/null +++ b/spec/integration/ssl/host.rb @@ -0,0 +1,90 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2008-4-17. +# Copyright (c) 2008. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/ssl/host' +require 'tempfile' + +describe Puppet::SSL::Host do + before do + # Get a safe temporary file + file = Tempfile.new("host_integration_testing") + @dir = file.path + file.delete + + Puppet.settings[:confdir] = @dir + Puppet.settings[:vardir] = @dir + + Puppet::SSL::Host.ca_location = :local + + @host = Puppet::SSL::Host.new("luke.madstop.com") + @ca = Puppet::SSL::CertificateAuthority.new + end + + after { + Puppet::SSL::Host.ca_location = :none + + system("rm -rf %s" % @dir) + Puppet.settings.clear + Puppet::Util::Cacher.invalidate + } + + it "should be considered a CA host if its name is equal to 'ca'" do + Puppet::SSL::Host.new("ca").should be_ca + end + + describe "when managing its key" do + it "should be able to generate and save a key" do + @host.generate_key + end + + it "should save the key such that the Indirector can find it" do + @host.generate_key + + Puppet::SSL::Key.find(@host.name).content.to_s.should == @host.key.to_s + end + + it "should save the private key into the :privatekeydir" do + @host.generate_key + File.read(File.join(Puppet.settings[:privatekeydir], "luke.madstop.com.pem")).should == @host.key.to_s + end + end + + describe "when managing its certificate request" do + it "should be able to generate and save a certificate request" do + @host.generate_certificate_request + end + + it "should save the certificate request such that the Indirector can find it" do + @host.generate_certificate_request + + Puppet::SSL::CertificateRequest.find(@host.name).content.to_s.should == @host.certificate_request.to_s + end + + it "should save the private certificate request into the :privatekeydir" do + @host.generate_certificate_request + File.read(File.join(Puppet.settings[:requestdir], "luke.madstop.com.pem")).should == @host.certificate_request.to_s + end + end + + describe "when the CA host" do + it "should never store its key in the :privatekeydir" do + Puppet.settings.use(:main, :ssl, :ca) + @ca = Puppet::SSL::Host.new(Puppet::SSL::Host.ca_name) + @ca.generate_key + + FileTest.should_not be_exist(File.join(Puppet[:privatekeydir], "ca.pem")) + end + end + + it "should pass the verification of its own SSL store" do + @host.generate + @ca = Puppet::SSL::CertificateAuthority.new + @ca.sign(@host.name) + + @host.ssl_store.verify(@host.certificate.content).should be_true + end +end diff --git a/spec/integration/transaction/report.rb b/spec/integration/transaction/report.rb index 48e59f203..6bbd5eb10 100755 --- a/spec/integration/transaction/report.rb +++ b/spec/integration/transaction/report.rb @@ -7,7 +7,7 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe Puppet::Transaction::Report do describe "when using the indirector" do - after { Puppet::Transaction::Report.indirection.clear_cache } + after { Puppet::Util::Cacher.invalidate } it "should be able to delegate to the :processor terminus" do Puppet::Transaction::Report.indirection.stubs(:terminus_class).returns :processor |