summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/face/ca.rb30
-rw-r--r--lib/puppet/face/node/clean.rb151
-rw-r--r--lib/puppet/indirector/report/processor.rb45
-rw-r--r--lib/puppet/indirector/yaml.rb5
-rw-r--r--lib/puppet/reports/store.rb15
-rwxr-xr-xspec/integration/node/facts_spec.rb2
-rwxr-xr-xspec/unit/face/node_spec.rb262
-rwxr-xr-xspec/unit/indirector/report/processor_spec.rb27
-rwxr-xr-xspec/unit/indirector/yaml_spec.rb18
9 files changed, 518 insertions, 37 deletions
diff --git a/lib/puppet/face/ca.rb b/lib/puppet/face/ca.rb
index e643530f0..00591d637 100644
--- a/lib/puppet/face/ca.rb
+++ b/lib/puppet/face/ca.rb
@@ -6,21 +6,21 @@ Puppet::Face.define(:ca, '0.1.0') do
summary "Local Puppet Certificate Authority management."
- description <<TEXT
-This provides local management of the Puppet Certificate Authority.
+ description <<-TEXT
+ This provides local management of the Puppet Certificate Authority.
-You can use this subcommand to sign outstanding certificate requests, list
-and manage local certificates, and inspect the state of the CA.
-TEXT
+ You can use this subcommand to sign outstanding certificate requests, list
+ and manage local certificates, and inspect the state of the CA.
+ TEXT
action :list do
summary "List certificates and/or certificate requests."
- description <<-end
-This will list the current certificates and certificate signing requests
-in the Puppet CA. You will also get the fingerprint, and any certificate
-verification failure reported.
- end
+ description <<-TEXT
+ This will list the current certificates and certificate signing requests
+ in the Puppet CA. You will also get the fingerprint, and any certificate
+ verification failure reported.
+ TEXT
option "--[no-]all" do
summary "Include all certificates and requests."
@@ -37,12 +37,12 @@ verification failure reported.
option "--subject PATTERN" do
summary "Only list if the subject matches PATTERN."
- description <<TEXT
-Only include certificates or requests where subject matches PATTERN.
+ description <<-TEXT
+ Only include certificates or requests where subject matches PATTERN.
-PATTERN is interpreted as a regular expression, allowing complex
-filtering of the content.
-TEXT
+ PATTERN is interpreted as a regular expression, allowing complex
+ filtering of the content.
+ TEXT
end
when_invoked do |options|
diff --git a/lib/puppet/face/node/clean.rb b/lib/puppet/face/node/clean.rb
new file mode 100644
index 000000000..a4df1bfaf
--- /dev/null
+++ b/lib/puppet/face/node/clean.rb
@@ -0,0 +1,151 @@
+Puppet::Face.define(:node, '0.0.1') do
+ action(:clean) do
+ option "--[no-]unexport" do
+ summary "Unexport exported resources"
+ end
+
+ summary "Clean up everything a puppetmaster knows about a node"
+ arguments "<host1> [<host2> ...]"
+ description <<-EOT
+ This includes
+
+ * Signed certificates ($vardir/ssl/ca/signed/node.domain.pem)
+ * Cached facts ($vardir/yaml/facts/node.domain.yaml)
+ * Cached node stuff ($vardir/yaml/node/node.domain.yaml)
+ * Reports ($vardir/reports/node.domain)
+ * Stored configs: it can either remove all data from an host in your
+ storedconfig database, or with --unexport turn every exported resource
+ supporting ensure to absent so that any other host checking out their
+ config can remove those exported configurations.
+
+ This will unexport exported resources of a
+ host, so that consumers of these resources can remove the exported
+ resources and we will safely remove the node from our
+ infrastructure.
+ EOT
+
+ when_invoked do |*args|
+ nodes = args[0..-2]
+ options = args.last
+ raise "At least one node should be passed" if nodes.empty? || nodes == options
+
+ # TODO: this is a hack and should be removed if faces provide the proper
+ # infrastructure to set the run mode.
+ require 'puppet/util/run_mode'
+ $puppet_application_mode = Puppet::Util::RunMode[:master]
+
+ if Puppet::SSL::CertificateAuthority.ca?
+ Puppet::SSL::Host.ca_location = :local
+ else
+ Puppet::SSL::Host.ca_location = :none
+ end
+
+ Puppet::Node::Facts.indirection.terminus_class = :yaml
+ Puppet::Node::Facts.indirection.cache_class = :yaml
+ Puppet::Node.indirection.terminus_class = :yaml
+ Puppet::Node.indirection.cache_class = :yaml
+
+ nodes.each { |node| cleanup(node.downcase, options[:unexport]) }
+ end
+ end
+
+ def cleanup(node, unexport)
+ clean_cert(node)
+ clean_cached_facts(node)
+ clean_cached_node(node)
+ clean_reports(node)
+ clean_storeconfigs(node, unexport)
+ end
+
+ # clean signed cert for +host+
+ def clean_cert(node)
+ if Puppet::SSL::CertificateAuthority.ca?
+ Puppet::Face[:ca, :current].revoke(node)
+ Puppet::Face[:ca, :current].destroy(node)
+ Puppet.info "#{node} certificates removed from ca"
+ else
+ Puppet.info "Not managing #{node} certs as this host is not a CA"
+ end
+ end
+
+ # clean facts for +host+
+ def clean_cached_facts(node)
+ Puppet::Node::Facts.indirection.destroy(node)
+ Puppet.info "#{node}'s facts removed"
+ end
+
+ # clean cached node +host+
+ def clean_cached_node(node)
+ Puppet::Node.indirection.destroy(node)
+ Puppet.info "#{node}'s cached node removed"
+ end
+
+ # clean node reports for +host+
+ def clean_reports(node)
+ Puppet::Transaction::Report.indirection.destroy(node)
+ Puppet.info "#{node}'s reports removed"
+ end
+
+ # clean storeconfig for +node+
+ def clean_storeconfigs(node, do_unexport=false)
+ return unless Puppet[:storeconfigs] && Puppet.features.rails?
+ require 'puppet/rails'
+ Puppet::Rails.connect
+ unless rails_node = Puppet::Rails::Host.find_by_name(node)
+ Puppet.notice "No entries found for #{node} in storedconfigs."
+ return
+ end
+
+ if do_unexport
+ unexport(rails_node)
+ Puppet.notice "Force #{node}'s exported resources to absent"
+ Puppet.warning "Please wait until all other hosts have checked out their configuration before finishing the cleanup with:"
+ Puppet.warning "$ puppet node clean #{node}"
+ else
+ rails_node.destroy
+ Puppet.notice "#{node} storeconfigs removed"
+ end
+ end
+
+ def unexport(node)
+ # fetch all exported resource
+ query = {:include => {:param_values => :param_name}}
+ query[:conditions] = [ "exported=? AND host_id=?", true, node.id ]
+ Puppet::Rails::Resource.find(:all, query).each do |resource|
+ if type_is_ensurable(resource)
+ line = 0
+ param_name = Puppet::Rails::ParamName.find_or_create_by_name("ensure")
+
+ if ensure_param = resource.param_values.find(
+ :first,
+ :conditions => [ 'param_name_id = ?', param_name.id ]
+ )
+ line = ensure_param.line.to_i
+ Puppet::Rails::ParamValue.delete(ensure_param.id);
+ end
+
+ # force ensure parameter to "absent"
+ resource.param_values.create(
+ :value => "absent",
+ :line => line,
+ :param_name => param_name
+ )
+ Puppet.info("#{resource.name} has been marked as \"absent\"")
+ end
+ end
+ end
+
+ def environment
+ @environment ||= Puppet::Node::Environment.new
+ end
+
+ def type_is_ensurable(resource)
+ if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure)
+ return true
+ else
+ type = environment.known_resource_types.find_definition('', resource.restype)
+ return true if type && type.arguments.keys.include?('ensure')
+ end
+ return false
+ end
+end
diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb
index 81b379eb8..7bdadcb36 100644
--- a/lib/puppet/indirector/report/processor.rb
+++ b/lib/puppet/indirector/report/processor.rb
@@ -14,6 +14,12 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
process(request.instance)
end
+ def destroy(request)
+ processors do |mod|
+ mod.destroy(request.key) if mod.respond_to?(:destroy)
+ end
+ end
+
private
# Process the report with each of the configured report types.
@@ -21,23 +27,17 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
# compatible and that's good enough for now.
def process(report)
Puppet.debug "Recieved report to process from #{report.host}"
- return if Puppet[:reports] == "none"
-
- reports.each do |name|
- Puppet.debug "Processing report from #{report.host} with processor #{name}"
- if mod = Puppet::Reports.report(name)
- # We have to use a dup because we're including a module in the
- # report.
- newrep = report.dup
- begin
- newrep.extend(mod)
- newrep.process
- rescue => detail
- puts detail.backtrace if Puppet[:trace]
- Puppet.err "Report #{name} failed: #{detail}"
- end
- else
- Puppet.warning "No report named '#{name}'"
+ processors do |mod|
+ Puppet.debug "Processing report from #{report.host} with processor #{mod}"
+ # We have to use a dup because we're including a module in the
+ # report.
+ newrep = report.dup
+ begin
+ newrep.extend(mod)
+ newrep.process
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Report #{name} failed: #{detail}"
end
end
end
@@ -47,4 +47,15 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = Puppet[:reports].gsub(/(^\s+)|(\s+$)/, '').split(/\s*,\s*/)
end
+
+ def processors(&blk)
+ return if Puppet[:reports] == "none"
+ reports.each do |name|
+ if mod = Puppet::Reports.report(name)
+ yield(mod)
+ else
+ Puppet.warning "No report named '#{name}'"
+ end
+ end
+ end
end
diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb
index 23997e97a..7b12d25e2 100644
--- a/lib/puppet/indirector/yaml.rb
+++ b/lib/puppet/indirector/yaml.rb
@@ -47,6 +47,11 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
File.join(base, self.class.indirection_name.to_s, name.to_s + ext)
end
+ def destroy(request)
+ file_path = path(request.key)
+ File.unlink(file_path) if File.exists?(file_path)
+ end
+
def search(request)
Dir.glob(path(request.key,'')).collect do |file|
YAML.load_file(file)
diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb
index 625a263b3..997206ec4 100644
--- a/lib/puppet/reports/store.rb
+++ b/lib/puppet/reports/store.rb
@@ -41,5 +41,20 @@ Puppet::Reports.register_report(:store) do
# Only testing cares about the return value
file
end
+
+ # removes all reports for a given host
+ def self.destroy(host)
+ client = host.gsub("..",".")
+ dir = File.join(Puppet[:reportdir], client)
+
+ if File.exists?(dir)
+ Dir.entries(dir).each do |file|
+ next if ['.','..'].include?(file)
+ file = File.join(dir, file)
+ File.unlink(file) if File.file?(file)
+ end
+ Dir.rmdir(dir)
+ end
+ end
end
diff --git a/spec/integration/node/facts_spec.rb b/spec/integration/node/facts_spec.rb
index f54d7f9aa..e87a0bdeb 100755
--- a/spec/integration/node/facts_spec.rb
+++ b/spec/integration/node/facts_spec.rb
@@ -7,7 +7,7 @@ require 'spec_helper'
describe Puppet::Node::Facts do
describe "when using the indirector" do
- after { Puppet::Util::Cacher.expire }
+ after(:each) { Puppet::Util::Cacher.expire }
it "should expire any cached node instances when it is saved" do
Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml
diff --git a/spec/unit/face/node_spec.rb b/spec/unit/face/node_spec.rb
index 027a4cce0..7151353a0 100755
--- a/spec/unit/face/node_spec.rb
+++ b/spec/unit/face/node_spec.rb
@@ -3,5 +3,265 @@ require 'spec_helper'
require 'puppet/face'
describe Puppet::Face[:node, '0.0.1'] do
- it "REVISIT: really should have some tests"
+ describe '#cleanup' do
+ it "should clean everything" do
+ {
+ "cert" => ['hostname'],
+ "cached_facts" => ['hostname'],
+ "cached_node" => ['hostname'],
+ "reports" => ['hostname'],
+ "storeconfigs" => ['hostname', :unexport]
+ }.each { |k, v| subject.expects("clean_#{k}".to_sym).with(*v) }
+ subject.cleanup('hostname', :unexport)
+ end
+ end
+
+ describe 'when running #clean' do
+ before :each do
+ Puppet::Node::Facts.indirection.stubs(:terminus_class=)
+ Puppet::Node::Facts.indirection.stubs(:cache_class=)
+ Puppet::Node.stubs(:terminus_class=)
+ Puppet::Node.stubs(:cache_class=)
+ end
+
+ it 'should invoke #cleanup' do
+ subject.expects(:cleanup).with('hostname', nil)
+ subject.clean('hostname')
+ end
+ end
+
+ describe "clean action" do
+ before :each do
+ Puppet::Node::Facts.indirection.stubs(:terminus_class=)
+ Puppet::Node::Facts.indirection.stubs(:cache_class=)
+ Puppet::Node.stubs(:terminus_class=)
+ Puppet::Node.stubs(:cache_class=)
+ subject.stubs(:cleanup)
+ end
+
+ it "should have a clean action" do
+ subject.should be_action :clean
+ end
+
+ it "should not accept a call with no arguments" do
+ expect { subject.clean() }.should raise_error
+ end
+
+ it "should accept a node name" do
+ expect { subject.clean('hostname') }.should_not raise_error
+ end
+
+ it "should accept more than one node name" do
+ expect do
+ subject.clean('hostname', 'hostname2', {})
+ end.should_not raise_error
+
+ expect do
+ subject.clean('hostname', 'hostname2', 'hostname3', { :unexport => true })
+ end.should_not raise_error
+ end
+
+ it "should accept the option --unexport" do
+ expect { subject.help('hostname', :unexport => true) }.
+ should_not raise_error ArgumentError
+ end
+
+ context "clean action" do
+ subject { Puppet::Face[:node, :current] }
+ before :each do
+ Puppet::Util::Log.stubs(:newdestination)
+ Puppet::Util::Log.stubs(:level=)
+ end
+
+ describe "during setup" do
+ it "should set facts terminus and cache class to yaml" do
+ Puppet::Node::Facts.indirection.expects(:terminus_class=).with(:yaml)
+ Puppet::Node::Facts.indirection.expects(:cache_class=).with(:yaml)
+
+ subject.clean('hostname')
+ end
+
+ it "should run in master mode" do
+ subject.clean('hostname')
+ $puppet_application_mode.name.should == :master
+ end
+
+ it "should set node cache as yaml" do
+ Puppet::Node.indirection.expects(:terminus_class=).with(:yaml)
+ Puppet::Node.indirection.expects(:cache_class=).with(:yaml)
+
+ subject.clean('hostname')
+ end
+
+ it "should manage the certs if the host is a CA" do
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true)
+ Puppet::SSL::Host.expects(:ca_location=).with(:local)
+ subject.clean('hostname')
+ end
+
+ it "should not manage the certs if the host is not a CA" do
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(false)
+ Puppet::SSL::Host.expects(:ca_location=).with(:none)
+ subject.clean('hostname')
+ end
+ end
+
+ describe "when cleaning certificate" do
+ before :each do
+ Puppet::SSL::Host.stubs(:destroy)
+ @ca = mock()
+ Puppet::SSL::CertificateAuthority.stubs(:instance).returns(@ca)
+ end
+
+ it "should send the :destroy order to the ca if we are a CA" do
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true)
+ @ca.expects(:revoke).with(@host)
+ @ca.expects(:destroy).with(@host)
+ subject.clean_cert(@host)
+ end
+
+ it "should not destroy the certs if we are not a CA" do
+ Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(false)
+ @ca.expects(:revoke).never
+ @ca.expects(:destroy).never
+ subject.clean_cert(@host)
+ end
+ end
+
+ describe "when cleaning cached facts" do
+ it "should destroy facts" do
+ @host = 'node'
+ Puppet::Node::Facts.indirection.expects(:destroy).with(@host)
+
+ subject.clean_cached_facts(@host)
+ end
+ end
+
+ describe "when cleaning cached node" do
+ it "should destroy the cached node" do
+ Puppet::Node::Yaml.any_instance.expects(:destroy)
+ subject.clean_cached_node(@host)
+ end
+ end
+
+ describe "when cleaning archived reports" do
+ it "should tell the reports to remove themselves" do
+ Puppet::Transaction::Report.indirection.stubs(:destroy).with(@host)
+
+ subject.clean_reports(@host)
+ end
+ end
+
+ describe "when cleaning storeconfigs entries for host", :if => Puppet.features.rails? do
+ before :each do
+ # Stub this so we don't need access to the DB
+ require 'puppet/rails/host'
+
+ Puppet.stubs(:[]).with(:storeconfigs).returns(true)
+
+ Puppet::Rails.stubs(:connect)
+ @rails_node = stub_everything 'rails_node'
+ Puppet::Rails::Host.stubs(:find_by_name).returns(@rails_node)
+ end
+
+ it "should connect to the database" do
+ Puppet::Rails.expects(:connect)
+ subject.clean_storeconfigs(@host, false)
+ end
+
+ it "should find the right host entry" do
+ Puppet::Rails::Host.expects(:find_by_name).with(@host).returns(@rails_node)
+
+ subject.clean_storeconfigs(@host, false)
+ end
+
+ describe "without unexport" do
+ it "should remove the host and it's content" do
+ @rails_node.expects(:destroy)
+
+ subject.clean_storeconfigs(@host, false)
+ end
+ end
+
+ describe "with unexport" do
+ before :each do
+ @rails_node.stubs(:id).returns(1234)
+
+ @type = stub_everything 'type'
+ @type.stubs(:validattr?).with(:ensure).returns(true)
+
+ @ensure_name = stub_everything 'ensure_name', :id => 23453
+ Puppet::Rails::ParamName.stubs(:find_or_create_by_name).returns(@ensure_name)
+
+ @param_values = stub_everything 'param_values'
+ @resource = stub_everything 'resource', :param_values => @param_values, :restype => "File"
+ Puppet::Rails::Resource.stubs(:find).returns([@resource])
+ end
+
+ it "should find all resources" do
+ Puppet::Rails::Resource.expects(:find).with(:all, {:include => {:param_values => :param_name}, :conditions => ["exported=? AND host_id=?", true, 1234]}).returns([])
+
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ describe "with an exported native type" do
+ before :each do
+ Puppet::Type.stubs(:type).returns(@type)
+ @type.expects(:validattr?).with(:ensure).returns(true)
+ end
+
+ it "should test a native type for ensure as an attribute" do
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should delete the old ensure parameter" do
+ ensure_param = stub 'ensure_param', :id => 12345, :line => 12
+ @param_values.stubs(:find).returns(ensure_param)
+ Puppet::Rails::ParamValue.expects(:delete).with(12345);
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should add an ensure => absent parameter" do
+ @param_values.expects(:create).with(:value => "absent",
+ :line => 0,
+ :param_name => @ensure_name)
+ subject.clean_storeconfigs(@host, true)
+ end
+ end
+
+ describe "with an exported definition" do
+ it "should try to lookup a definition and test it for the ensure argument" do
+ Puppet::Type.stubs(:type).returns(nil)
+ definition = stub_everything 'definition', :arguments => { 'ensure' => 'present' }
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition)
+ subject.clean_storeconfigs(@host, true)
+ end
+ end
+
+ it "should not unexport the resource of an unkown type" do
+ Puppet::Type.stubs(:type).returns(nil)
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil)
+ Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
+ subject.clean_storeconfigs(@host)
+ end
+
+ it "should not unexport the resource of a not ensurable native type" do
+ Puppet::Type.stubs(:type).returns(@type)
+ @type.expects(:validattr?).with(:ensure).returns(false)
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil)
+ Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should not unexport the resource of a not ensurable definition" do
+ Puppet::Type.stubs(:type).returns(nil)
+ definition = stub_everything 'definition', :arguments => { 'foobar' => 'someValue' }
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition)
+ Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
+ subject.clean_storeconfigs(@host, true)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/unit/indirector/report/processor_spec.rb b/spec/unit/indirector/report/processor_spec.rb
index fbc70a104..c64cc7eff 100755
--- a/spec/unit/indirector/report/processor_spec.rb
+++ b/spec/unit/indirector/report/processor_spec.rb
@@ -15,15 +15,21 @@ describe Puppet::Transaction::Report::Processor do
it "should provide a method for saving reports" do
Puppet::Transaction::Report::Processor.new.should respond_to(:save)
end
+
+ it "should provide a method for cleaning reports" do
+ Puppet::Transaction::Report::Processor.new.should respond_to(:destroy)
+ end
+
end
-describe Puppet::Transaction::Report::Processor, " when saving a report" do
+describe Puppet::Transaction::Report::Processor, " when processing a report" do
before do
Puppet.settings.stubs(:use)
@reporter = Puppet::Transaction::Report::Processor.new
+ @request = stub 'request', :instance => stub("report", :host => 'hostname'), :key => 'node'
end
- it "should not process the report if reports are set to 'none'" do
+ it "should not save the report if reports are set to 'none'" do
Puppet::Reports.expects(:report).never
Puppet[:reports] = 'none'
@@ -34,9 +40,24 @@ describe Puppet::Transaction::Report::Processor, " when saving a report" do
@reporter.save(request)
end
- it "should process the report with each configured report type" do
+ it "should save the report with each configured report type" do
Puppet.settings.stubs(:value).with(:reports).returns("one,two")
@reporter.send(:reports).should == %w{one two}
+
+ Puppet::Reports.expects(:report).with('one')
+ Puppet::Reports.expects(:report).with('two')
+
+ @reporter.save(@request)
+ end
+
+ it "should destroy reports for each processor that responds to destroy" do
+ Puppet.settings.stubs(:value).with(:reports).returns("http,store")
+ http_report = mock()
+ store_report = mock()
+ store_report.expects(:destroy).with(@request.key)
+ Puppet::Reports.expects(:report).with('http').returns(http_report)
+ Puppet::Reports.expects(:report).with('store').returns(store_report)
+ @reporter.destroy(@request)
end
end
diff --git a/spec/unit/indirector/yaml_spec.rb b/spec/unit/indirector/yaml_spec.rb
index c43dbcaf6..29f6d466f 100755
--- a/spec/unit/indirector/yaml_spec.rb
+++ b/spec/unit/indirector/yaml_spec.rb
@@ -154,5 +154,23 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
Dir.expects(:glob).with(:glob).returns []
@store.search(@request).should == []
end
+
+ describe Puppet::Indirector::Yaml, " when destroying" do
+ it "should unlink the right yaml file if it exists" do
+ path = File.join("/what/ever", @store.class.indirection_name.to_s, @request.key.to_s + ".yaml")
+ File.expects(:exists?).with(path).returns true
+ File.expects(:unlink).with(path)
+
+ @store.destroy(@request)
+ end
+
+ it "should not unlink the yaml file if it does not exists" do
+ path = File.join("/what/ever", @store.class.indirection_name.to_s, @request.key.to_s + ".yaml")
+ File.expects(:exists?).with(path).returns false
+ File.expects(:unlink).with(path).never
+
+ @store.destroy(@request)
+ end
+ end
end
end