summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-04-08 18:21:18 -0500
committerLuke Kanies <luke@madstop.com>2008-04-08 18:21:18 -0500
commitbf728d23caca4f58ae4ede1a2d477c9fc15e0bdc (patch)
treed79ae6e23667f0a1b201537914a025c9f677aa74
parent644d6baae132a097170631f90521e878e31a5a0a (diff)
downloadpuppet-bf728d23caca4f58ae4ede1a2d477c9fc15e0bdc.tar.gz
puppet-bf728d23caca4f58ae4ede1a2d477c9fc15e0bdc.tar.xz
puppet-bf728d23caca4f58ae4ede1a2d477c9fc15e0bdc.zip
Intermediate commit.
This commit adds a Request instance into the indirection, pushing it all the way to the terminus instances. It's a big commit because it requires modifying every terminus class. There are still some thorny design issues. In particular, who should be responsible for making the request object? I've tried having both the indirection class and the Indirector module creating it, and both have their issues. Also, the Catalog class previously allowed passing Node instances directly to the find method, which is now no longer possible because the Request class would treat the node as the instance being found. We need the request class to have two modes, one when it's passed an instance and one when it's passed a key.
-rw-r--r--lib/puppet/indirector.rb49
-rw-r--r--lib/puppet/indirector/checksum/file.rb4
-rw-r--r--lib/puppet/indirector/direct_file_server.rb14
-rw-r--r--lib/puppet/indirector/file.rb28
-rw-r--r--lib/puppet/indirector/file_metadata/file.rb4
-rw-r--r--lib/puppet/indirector/indirection.rb50
-rw-r--r--lib/puppet/indirector/memory.rb14
-rw-r--r--lib/puppet/indirector/plain.rb4
-rw-r--r--lib/puppet/indirector/request.rb2
-rw-r--r--lib/puppet/indirector/yaml.rb28
-rw-r--r--lib/puppet/transaction/report.rb4
-rwxr-xr-xspec/integration/indirector/direct_file_server.rb10
-rwxr-xr-xspec/integration/node/catalog.rb34
-rw-r--r--spec/shared_behaviours/file_serving.rb12
-rw-r--r--spec/shared_behaviours/memory_terminus.rb32
-rwxr-xr-xspec/unit/indirector.rb98
-rwxr-xr-xspec/unit/indirector/catalog/compiler.rb4
-rwxr-xr-xspec/unit/indirector/checksum/file.rb17
-rwxr-xr-xspec/unit/indirector/direct_file_server.rb24
-rwxr-xr-xspec/unit/indirector/file.rb50
-rwxr-xr-xspec/unit/indirector/file_metadata/file.rb50
-rwxr-xr-xspec/unit/indirector/indirection.rb215
-rwxr-xr-xspec/unit/indirector/memory.rb30
-rwxr-xr-xspec/unit/indirector/node/memory.rb5
-rwxr-xr-xspec/unit/indirector/plain.rb6
-rwxr-xr-xspec/unit/indirector/request.rb18
-rwxr-xr-xspec/unit/indirector/yaml.rb34
-rwxr-xr-xspec/unit/node.rb4
-rwxr-xr-xspec/unit/node/catalog.rb4
-rwxr-xr-xspec/unit/node/facts.rb6
-rwxr-xr-xspec/unit/transaction/report.rb14
31 files changed, 473 insertions, 395 deletions
diff --git a/lib/puppet/indirector.rb b/lib/puppet/indirector.rb
index c30c097b2..a8a7a84d1 100644
--- a/lib/puppet/indirector.rb
+++ b/lib/puppet/indirector.rb
@@ -9,6 +9,7 @@ module Puppet::Indirector
require 'puppet/indirector/indirection'
require 'puppet/indirector/terminus'
+ require 'puppet/indirector/envelope'
# Declare that the including class indirects its methods to
# this terminus. The terminus name must be the name of a Puppet
@@ -20,6 +21,7 @@ module Puppet::Indirector
# populate this class with the various new methods
extend ClassMethods
include InstanceMethods
+ include Puppet::Indirector::Envelope
# instantiate the actual Terminus for that type and this name (:ldap, w/ args :node)
# & hook the instantiated Terminus into this class (Node: @indirection = terminus)
@@ -28,41 +30,32 @@ module Puppet::Indirector
end
module ClassMethods
- attr_reader :indirection
+ attr_reader :indirection
- def cache_class=(klass)
- indirection.cache_class = klass
- end
+ def cache_class=(klass)
+ indirection.cache_class = klass
+ end
- def terminus_class=(klass)
- indirection.terminus_class = klass
- end
+ def terminus_class=(klass)
+ indirection.terminus_class = klass
+ end
- def find(*args)
- indirection.find(*args)
- end
+ def find(*args)
+ indirection.find Puppet::Indirector::Request.new(indirection.name, :find, *args)
+ end
- def destroy(*args)
- indirection.destroy(*args)
- end
+ def destroy(*args)
+ indirection.destroy Puppet::Indirector::Request.new(indirection.name, :destroy, *args)
+ end
- def search(*args)
- indirection.search(*args)
- end
-
- def version(*args)
- indirection.version(*args)
- end
+ def search(*args)
+ indirection.search Puppet::Indirector::Request.new(indirection.name, :search, *args)
+ end
end
module InstanceMethods
- # Make it easy for the model to set versions,
- # which are used for caching and such.
- attr_accessor :version
-
- # these become instance methods
- def save(*args)
- self.class.indirection.save(self, *args)
- end
+ def save(*args)
+ self.class.indirection.save Puppet::Indirector::Request.new(self.class.indirection.name, :save, self, *args)
+ end
end
end
diff --git a/lib/puppet/indirector/checksum/file.rb b/lib/puppet/indirector/checksum/file.rb
index 3b196a1f8..5489b40e8 100644
--- a/lib/puppet/indirector/checksum/file.rb
+++ b/lib/puppet/indirector/checksum/file.rb
@@ -18,8 +18,8 @@ class Puppet::Checksum::File < Puppet::Indirector::File
path.join(File::SEPARATOR)
end
- def save(file)
- path = File.dirname(path(file.name))
+ def save(request)
+ path = File.dirname(path(request.key))
# Make the directories if necessary.
unless FileTest.directory?(path)
diff --git a/lib/puppet/indirector/direct_file_server.rb b/lib/puppet/indirector/direct_file_server.rb
index 31cc9aa16..1711356f9 100644
--- a/lib/puppet/indirector/direct_file_server.rb
+++ b/lib/puppet/indirector/direct_file_server.rb
@@ -11,17 +11,17 @@ class Puppet::Indirector::DirectFileServer < Puppet::Indirector::Terminus
include Puppet::Util::URIHelper
include Puppet::FileServing::TerminusHelper
- def find(key, options = {})
- uri = key2uri(key)
+ def find(request)
+ uri = key2uri(request.key)
return nil unless FileTest.exists?(uri.path)
- instance = model.new(key, :path => uri.path)
- instance.links = options[:links] if options[:links]
+ instance = model.new(request.key, :path => uri.path)
+ instance.links = request.options[:links] if request.options[:links]
return instance
end
- def search(key, options = {})
- uri = key2uri(key)
+ def search(request)
+ uri = key2uri(request.key)
return nil unless FileTest.exists?(uri.path)
- path2instances(key, uri.path, options)
+ path2instances(request.key, uri.path, request.options)
end
end
diff --git a/lib/puppet/indirector/file.rb b/lib/puppet/indirector/file.rb
index 8c984154b..e5382155f 100644
--- a/lib/puppet/indirector/file.rb
+++ b/lib/puppet/indirector/file.rb
@@ -3,27 +3,27 @@ require 'puppet/indirector/terminus'
# An empty terminus type, meant to just return empty objects.
class Puppet::Indirector::File < Puppet::Indirector::Terminus
# Remove files on disk.
- def destroy(name)
+ def destroy(request)
if respond_to?(:path)
- path = path(name)
+ path = path(request.key)
else
- path = name
+ path = request.key
end
- raise Puppet::Error.new("File %s does not exist; cannot destroy" % [name]) unless File.exist?(path)
+ raise Puppet::Error.new("File %s does not exist; cannot destroy" % [request.key]) unless File.exist?(path)
begin
File.unlink(path)
rescue => detail
- raise Puppet::Error, "Could not remove %s: %s" % [name, detail]
+ raise Puppet::Error, "Could not remove %s: %s" % [request.key, detail]
end
end
# Return a model instance for a given file on disk.
- def find(name)
+ def find(request)
if respond_to?(:path)
- path = path(name)
+ path = path(request.key)
else
- path = name
+ path = request.key
end
return nil unless File.exist?(path)
@@ -38,20 +38,20 @@ class Puppet::Indirector::File < Puppet::Indirector::Terminus
end
# Save a new file to disk.
- def save(file)
+ def save(request)
if respond_to?(:path)
- path = path(file.name)
+ path = path(request.key)
else
- path = file.path
+ path = request.key
end
dir = File.dirname(path)
- raise Puppet::Error.new("Cannot save %s; parent directory %s does not exist" % [file, dir]) unless File.directory?(dir)
+ raise Puppet::Error.new("Cannot save %s; parent directory %s does not exist" % [request.key, dir]) unless File.directory?(dir)
begin
- File.open(path, "w") { |f| f.print file.content }
+ File.open(path, "w") { |f| f.print request.instance.content }
rescue => detail
- raise Puppet::Error, "Could not write %s: %s" % [file, detail]
+ raise Puppet::Error, "Could not write %s: %s" % [request.key, detail]
end
end
end
diff --git a/lib/puppet/indirector/file_metadata/file.rb b/lib/puppet/indirector/file_metadata/file.rb
index b36846bbe..c46015c38 100644
--- a/lib/puppet/indirector/file_metadata/file.rb
+++ b/lib/puppet/indirector/file_metadata/file.rb
@@ -9,14 +9,14 @@ require 'puppet/indirector/direct_file_server'
class Puppet::Indirector::FileMetadata::File < Puppet::Indirector::DirectFileServer
desc "Retrieve file metadata directly from the local filesystem."
- def find(key, options = {})
+ def find(request)
return unless data = super
data.collect_attributes
return data
end
- def search(key, options = {})
+ def search(request)
return unless result = super
result.each { |instance| instance.collect_attributes }
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index 1b6613035..56cd687af 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -126,6 +126,11 @@ class Puppet::Indirector::Indirection
end
end
+ # Set up our request object.
+ def request(key, method, arguments = nil)
+ Puppet::Indirector::Request.new(self.name, key, method, arguments)
+ end
+
# Return the singleton terminus for this indirection.
def terminus(terminus_name = nil)
# Get the name of the terminus.
@@ -167,28 +172,27 @@ class Puppet::Indirector::Indirection
end
end
- def find(key, *args)
- request = request(key, :find, *args)
+ def find(request)
terminus = prepare(request)
# See if our instance is in the cache and up to date.
- if cache? and cached = cache.find(key, *args)
+ if cache? and cached = cache.find(request)
if cached.expired?
- Puppet.info "Cached %s %s expired at %s; not using" % [self.name, key, cached.expiration]
+ Puppet.info "Cached %s %s expired at %s; not using" % [self.name, request.key, cached.expiration]
else
- Puppet.debug "Using cached %s %s" % [self.name, key]
+ Puppet.debug "Using cached %s %s" % [self.name, request.key]
return cached
end
end
# Otherwise, return the result from the terminus, caching if appropriate.
- if result = terminus.find(key, *args)
- # Include the envelope module, so we can set the expiration.
- result.extend(Puppet::Indirector::Envelope)
+ if result = terminus.find(request)
result.expiration ||= self.expiration
if cache?
- Puppet.info "Caching %s %s" % [self.name, key]
- cache.save(result, *args)
+ Puppet.info "Caching %s %s" % [self.name, request.key]
+ cached_request = request.clone
+ cached_request.instance = result
+ cache.save(cached_request)
end
return result
@@ -198,38 +202,35 @@ class Puppet::Indirector::Indirection
end
# Remove something via the terminus.
- def destroy(key, *args)
- request = request(key, :destroy, *args)
+ def destroy(request)
terminus = prepare(request)
- terminus.destroy(key, *args)
+ terminus.destroy(request)
- if cache? and cached = cache.find(key, *args)
- cache.destroy(key, *args)
+ if cache? and cached = cache.find(request)
+ cache.destroy(request)
end
nil
end
# Search for more than one instance. Should always return an array.
- def search(key, *args)
- request = request(key, :search, *args)
+ def search(request)
terminus = prepare(request)
- result = terminus.search(key, *args)
+ result = terminus.search(request)
result
end
# Save the instance in the appropriate terminus. This method is
# normally an instance method on the indirected class.
- def save(instance, *args)
- request = request(instance.name, :save, *args)
+ def save(request)
terminus = prepare(request)
# If caching is enabled, save our document there
- cache.save(instance, *args) if cache?
- terminus.save(instance, *args)
+ cache.save(request) if cache?
+ terminus.save(request)
end
private
@@ -268,9 +269,4 @@ class Puppet::Indirector::Indirection
end
return klass.new
end
-
- # Set up our request object.
- def request(key, method, arguments = nil)
- Puppet::Indirector::Request.new(self.name, key, method, arguments)
- end
end
diff --git a/lib/puppet/indirector/memory.rb b/lib/puppet/indirector/memory.rb
index b97e6ffb6..19acc14e2 100644
--- a/lib/puppet/indirector/memory.rb
+++ b/lib/puppet/indirector/memory.rb
@@ -6,16 +6,16 @@ class Puppet::Indirector::Memory < Puppet::Indirector::Terminus
@instances = {}
end
- def destroy(name)
- raise ArgumentError.new("Could not find %s to destroy" % name) unless @instances.include?(name)
- @instances.delete(name)
+ def destroy(request)
+ raise ArgumentError.new("Could not find %s to destroy" % request.key) unless @instances.include?(request.key)
+ @instances.delete(request.key)
end
- def find(name)
- @instances[name]
+ def find(request)
+ @instances[request.key]
end
- def save(instance)
- @instances[instance.name] = instance
+ def save(request)
+ @instances[request.key] = request.instance
end
end
diff --git a/lib/puppet/indirector/plain.rb b/lib/puppet/indirector/plain.rb
index 8bdf8469c..2caa0946d 100644
--- a/lib/puppet/indirector/plain.rb
+++ b/lib/puppet/indirector/plain.rb
@@ -3,7 +3,7 @@ require 'puppet/indirector/terminus'
# An empty terminus type, meant to just return empty objects.
class Puppet::Indirector::Plain < Puppet::Indirector::Terminus
# Just return nothing.
- def find(name)
- indirection.model.new(name)
+ def find(request)
+ indirection.model.new(request.key)
end
end
diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb
index 708862b28..68b7ee160 100644
--- a/lib/puppet/indirector/request.rb
+++ b/lib/puppet/indirector/request.rb
@@ -5,7 +5,7 @@ require 'puppet/indirector'
class Puppet::Indirector::Request
attr_accessor :indirection_name, :key, :method, :options, :instance
- def initialize(indirection_name, key, method, options = {})
+ def initialize(indirection_name, method, key, options = {})
@indirection_name, @method, @options = indirection_name, method, (options || {})
if key.is_a?(String) or key.is_a?(Symbol)
diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb
index 4dd29159e..23bca02b8 100644
--- a/lib/puppet/indirector/yaml.rb
+++ b/lib/puppet/indirector/yaml.rb
@@ -3,23 +3,22 @@ require 'puppet/indirector/terminus'
# The base class for YAML indirection termini.
class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
# Read a given name's file in and convert it from YAML.
- def find(name)
- raise ArgumentError.new("You must specify the name of the object to retrieve") unless name
- file = path(name)
+ def find(request)
+ file = path(request.key)
return nil unless FileTest.exist?(file)
begin
return from_yaml(File.read(file))
rescue => detail
- raise Puppet::Error, "Could not read YAML data for %s %s: %s" % [indirection.name, name, detail]
+ raise Puppet::Error, "Could not read YAML data for %s %s: %s" % [indirection.name, request.key, detail]
end
end
# Convert our object to YAML and store it to the disk.
- def save(object)
- raise ArgumentError.new("You can only save objects that respond to :name") unless object.respond_to?(:name)
+ def save(request)
+ raise ArgumentError.new("You can only save objects that respond to :name") unless request.instance.respond_to?(:name)
- file = path(object.name)
+ file = path(request.key)
basedir = File.dirname(file)
@@ -29,15 +28,15 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
end
begin
- File.open(file, "w", 0660) { |f| f.print to_yaml(object) }
+ File.open(file, "w", 0660) { |f| f.print to_yaml(request.instance) }
rescue TypeError => detail
- Puppet.err "Could not save %s %s: %s" % [self.name, object.name, detail]
+ Puppet.err "Could not save %s %s: %s" % [self.name, request.key, detail]
end
end
- def version(name)
- return nil unless FileTest.exist?(path(name))
- return File.stat(path(name)).mtime
+ # Return the path to a given node's file.
+ def path(name)
+ File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml")
end
private
@@ -49,9 +48,4 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
def to_yaml(object)
YAML.dump(object)
end
-
- # Return the path to a given node's file.
- def path(name)
- File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml")
- end
end
diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb
index 56f8a602a..bd62ebbe6 100644
--- a/lib/puppet/transaction/report.rb
+++ b/lib/puppet/transaction/report.rb
@@ -34,6 +34,10 @@ class Puppet::Transaction::Report
end
end
+ def name
+ host
+ end
+
# Create a new metric.
def newmetric(name, hash)
metric = Puppet::Util::Metric.new(name)
diff --git a/spec/integration/indirector/direct_file_server.rb b/spec/integration/indirector/direct_file_server.rb
index 383486986..40b753a6c 100755
--- a/spec/integration/indirector/direct_file_server.rb
+++ b/spec/integration/indirector/direct_file_server.rb
@@ -19,7 +19,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with the files
it "should return an instance of the model" do
FileTest.expects(:exists?).with(@filepath).returns(true)
- @terminus.find("file://host#{@filepath}").should be_instance_of(Puppet::FileServing::Content)
+ @terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}")).should be_instance_of(Puppet::FileServing::Content)
end
it "should return an instance capable of returning its content" do
@@ -27,7 +27,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with the files
File.stubs(:lstat).with(@filepath).returns(stub("stat", :ftype => "file"))
File.expects(:read).with(@filepath).returns("my content")
- instance = @terminus.find("file://host#{@filepath}")
+ instance = @terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}"))
instance.content.should == "my content"
end
@@ -50,10 +50,12 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with FileServi
end
Dir.expects(:entries).with(@filepath).returns @subfiles
+
+ @request = @terminus.indirection.request(:search, "file:///my/file", :recurse => true)
end
it "should return an instance for every file in the fileset" do
- result = @terminus.search("file:///my/file", :recurse => true)
+ result = @terminus.search(@request)
result.should be_instance_of(Array)
result.length.should == 3
result.each { |r| r.should be_instance_of(Puppet::FileServing::Content) }
@@ -65,7 +67,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with FileServi
File.expects(:read).with(File.join(@filepath, name)).returns("#{name} content")
end
- @terminus.search("file:///my/file", :recurse => true).each do |instance|
+ @terminus.search(@request).each do |instance|
case instance.key
when /one/: instance.content.should == "one content"
when /two/: instance.content.should == "two content"
diff --git a/spec/integration/node/catalog.rb b/spec/integration/node/catalog.rb
new file mode 100755
index 000000000..d0ddfd8aa
--- /dev/null
+++ b/spec/integration/node/catalog.rb
@@ -0,0 +1,34 @@
+#!/usr/bin/env ruby
+#
+# Created by Luke Kanies on 2007-10-18.
+# Copyright (c) 2007. All rights reserved.
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Node::Catalog do
+ describe "when using the indirector" do
+ 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
+
+ # Load now, before we stub the exists? method.
+ Puppet::Node::Catalog.indirection.terminus(:yaml)
+
+ file = File.join(Puppet[:yamldir], "catalog", "me.yaml")
+ FileTest.expects(:exist?).with(file).returns false
+ Puppet::Node::Catalog.find("me").should be_nil
+ end
+
+ it "should be able to delegate to the :compiler terminus" do
+ Puppet::Node::Catalog.indirection.stubs(:terminus_class).returns :compiler
+
+ # Load now, before we stub the exists? method.
+ compiler = Puppet::Node::Catalog.indirection.terminus(:compiler)
+
+ compiler.expects(:compile).with("me").returns nil
+
+ Puppet::Node::Catalog.find("me").should be_nil
+ end
+ end
+end
diff --git a/spec/shared_behaviours/file_serving.rb b/spec/shared_behaviours/file_serving.rb
index b5ab6b0fd..82f207243 100644
--- a/spec/shared_behaviours/file_serving.rb
+++ b/spec/shared_behaviours/file_serving.rb
@@ -6,7 +6,7 @@
describe "Puppet::FileServing::Files", :shared => true do
it "should use the rest terminus when the 'puppet' URI scheme is used and a host name is present" do
uri = "puppet://myhost/mymod/my/file"
- @indirection.terminus(:rest).expects(:find).with(uri)
+ @indirection.terminus(:rest).expects(:find)
@test_class.find(uri)
end
@@ -14,7 +14,7 @@ describe "Puppet::FileServing::Files", :shared => true do
uri = "puppet:///mymod/my/file"
Puppet.settings.stubs(:value).with(:name).returns("puppetd")
Puppet.settings.stubs(:value).with(:modulepath).returns("")
- @indirection.terminus(:rest).expects(:find).with(uri)
+ @indirection.terminus(:rest).expects(:find)
@test_class.find(uri)
end
@@ -27,27 +27,27 @@ describe "Puppet::FileServing::Files", :shared => true do
Puppet.settings.stubs(:value).with(:libdir).returns("")
Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
Puppet.settings.stubs(:value).with(:environment).returns("")
- @indirection.terminus(:file_server).expects(:find).with(uri)
+ @indirection.terminus(:file_server).expects(:find)
@indirection.terminus(:file_server).stubs(:authorized?).returns(true)
@test_class.find(uri)
end
it "should use the file_server terminus when the 'puppetmounts' URI scheme is used" do
uri = "puppetmounts:///mymod/my/file"
- @indirection.terminus(:file_server).expects(:find).with(uri)
+ @indirection.terminus(:file_server).expects(:find)
@indirection.terminus(:file_server).stubs(:authorized?).returns(true)
@test_class.find(uri)
end
it "should use the file terminus when the 'file' URI scheme is used" do
uri = "file:///mymod/my/file"
- @indirection.terminus(:file).expects(:find).with(uri)
+ @indirection.terminus(:file).expects(:find)
@test_class.find(uri)
end
it "should use the file terminus when a fully qualified path is provided" do
uri = "/mymod/my/file"
- @indirection.terminus(:file).expects(:find).with(uri)
+ @indirection.terminus(:file).expects(:find)
@test_class.find(uri)
end
end
diff --git a/spec/shared_behaviours/memory_terminus.rb b/spec/shared_behaviours/memory_terminus.rb
new file mode 100644
index 000000000..a00dc9f74
--- /dev/null
+++ b/spec/shared_behaviours/memory_terminus.rb
@@ -0,0 +1,32 @@
+#
+# Created by Luke Kanies on 2008-4-8.
+# Copyright (c) 2008. All rights reserved.
+
+describe "A Memory Terminus", :shared => true do
+ it "should find no instances by default" do
+ @searcher.find(@request).should be_nil
+ end
+
+ it "should be able to find instances that were previously saved" do
+ @searcher.save(@request)
+ @searcher.find(@request).should equal(@instance)
+ end
+
+ it "should replace existing saved instances when a new instance with the same name is saved" do
+ @searcher.save(@request)
+ two = stub 'second', :name => @name
+ trequest = stub 'request', :key => @name, :instance => two
+ @searcher.save(trequest)
+ @searcher.find(@request).should equal(two)
+ end
+
+ it "should be able to remove previously saved instances" do
+ @searcher.save(@request)
+ @searcher.destroy(@request)
+ @searcher.find(@request).should be_nil
+ end
+
+ it "should fail when asked to destroy an instance that does not exist" do
+ proc { @searcher.destroy(@request) }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/unit/indirector.rb b/spec/unit/indirector.rb
index 1a5867c51..892e70c1f 100755
--- a/spec/unit/indirector.rb
+++ b/spec/unit/indirector.rb
@@ -21,6 +21,10 @@ describe Puppet::Indirector, "when registering an indirection" do
before do
@thingie = Class.new do
extend Puppet::Indirector
+ attr_reader :name
+ def initialize(name)
+ @name = name
+ end
end
end
@@ -55,48 +59,92 @@ describe Puppet::Indirector, "when registering an indirection" do
end
end
-describe Puppet::Indirector, " when redirecting a model" do
+describe "Delegated Indirection Method", :shared => true do
+ it "should create an indirection request with the indirection name, the method being delegated, and all of the arguments to the method call" do
+ Puppet::Indirector::Request.expects(:new).with(@indirection.name, @method, "me", :one => :two)
+ @indirection.stubs(@method)
+ @thingie.send(@method, "me", :one => :two)
+ end
+
+ it "should delegate to the indirection" do
+ @indirection.expects(@method)
+ @thingie.send(@method, "me")
+ end
+
+ it "should pass the indirection's request instance to the indirection's method" do
+ request = mock 'request'
+ Puppet::Indirector::Request.expects(:new).returns request
+ @indirection.expects(@method).with(request)
+ @thingie.send(@method, "me")
+ end
+
+ it "should return the results of the delegation as its result" do
+ request = mock 'request'
+ @indirection.expects(@method).returns "yay"
+ @thingie.send(@method, "me").should == "yay"
+ end
+end
+
+describe Puppet::Indirector, "when redirecting a model" do
before do
@thingie = Class.new do
extend Puppet::Indirector
+ attr_reader :name
+ def initialize(name)
+ @name = name
+ end
end
@indirection = @thingie.send(:indirects, :test)
end
- it "should give the model the ability set a version" do
- thing = @thingie.new
- thing.should respond_to(:version=)
+ it "should include the Envelope module in the model" do
+ @thingie.ancestors.should be_include(Puppet::Indirector::Envelope)
end
- it "should give the model the ability retrieve a version" do
- thing = @thingie.new
- thing.should respond_to(:version)
+ describe "when finding instances via the model" do
+ before { @method = :find }
+ it_should_behave_like "Delegated Indirection Method"
end
- it "should give the model the ability to lookup a model instance by letting the indirection perform the lookup" do
- @indirection.expects(:find)
- @thingie.find
+ describe "when destroying instances via the model" do
+ before { @method = :destroy }
+ it_should_behave_like "Delegated Indirection Method"
end
- it "should give the model the ability to remove model instances from a terminus by letting the indirection remove the instance" do
- @indirection.expects(:destroy)
- @thingie.destroy
+ describe "when searching for instances via the model" do
+ before { @method = :search }
+ it_should_behave_like "Delegated Indirection Method"
end
- it "should give the model the ability to search for model instances by letting the indirection find the matching instances" do
- @indirection.expects(:search)
- @thingie.search
- end
+ # This is an instance method, so it behaves a bit differently.
+ describe "when saving instances via the model" do
+ before do
+ @instance = @thingie.new("me")
+ end
- it "should give the model the ability to store a model instance by letting the indirection store the instance" do
- thing = @thingie.new
- @indirection.expects(:save).with(thing)
- thing.save
- end
+ it "should pass the method name, the instance, plus all passed arguments to the indirection's request method" do
+ Puppet::Indirector::Request.expects(:new).with(@indirection.name, :save, @instance, :one => :two)
+ @indirection.stubs(:save)
+ @instance.save(:one => :two)
+ end
- it "should give the model the ability to look up an instance's version by letting the indirection perform the lookup" do
- @indirection.expects(:version).with(:thing)
- @thingie.version(:thing)
+ it "should delegate to the indirection" do
+ @indirection.expects(:save)
+ @instance.save
+ end
+
+ it "should pass the indirection's request instance to the indirection's method" do
+ request = mock 'request'
+ Puppet::Indirector::Request.expects(:new).returns request
+ @indirection.expects(:save).with(request)
+ @instance.save
+ end
+
+ it "should return the results of the delegation as its result" do
+ request = mock 'request'
+ @indirection.expects(:save).returns "yay"
+ @instance.save.should == "yay"
+ end
end
it "should give the model the ability to set the indirection terminus class" do
diff --git a/spec/unit/indirector/catalog/compiler.rb b/spec/unit/indirector/catalog/compiler.rb
index a4a0acd58..5a26302d1 100755
--- a/spec/unit/indirector/catalog/compiler.rb
+++ b/spec/unit/indirector/catalog/compiler.rb
@@ -75,7 +75,9 @@ describe Puppet::Node::Catalog::Compiler, " when finding nodes" do
it "should fail if it cannot find the node" do
@node.stubs :merge
Puppet::Node.expects(:find_by_any_name).with(@name).returns(nil)
- proc { @compiler.find(@name) }.should raise_error(Puppet::Error)
+ request = stub 'request', :key => @name
+ @compiler.find(request)
+ proc { @compiler.find(request) }.should raise_error(Puppet::Error)
end
end
diff --git a/spec/unit/indirector/checksum/file.rb b/spec/unit/indirector/checksum/file.rb
index 64425904f..857d7b050 100755
--- a/spec/unit/indirector/checksum/file.rb
+++ b/spec/unit/indirector/checksum/file.rb
@@ -38,6 +38,8 @@ describe Puppet::Checksum::File do
Puppet.stubs(:[]).with(:bucketdir).returns(@dir)
@path = @store.path(@value)
+
+ @request = stub 'request', :key => @value
end
@@ -76,7 +78,7 @@ describe Puppet::Checksum::File do
# The smallest test that will use the calculated path
it "should look for the calculated path" do
File.expects(:exist?).with(@path).returns(false)
- @store.find(@value)
+ @store.find(@request)
end
it "should return an instance of Puppet::Checksum created with the content if the file exists" do
@@ -87,18 +89,18 @@ describe Puppet::Checksum::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).returns(content)
- @store.find(@value).should equal(sum)
+ @store.find(@request).should equal(sum)
end
it "should return nil if no file is found" do
File.expects(:exist?).with(@path).returns(false)
- @store.find(@value).should be_nil
+ @store.find(@request).should be_nil
end
it "should fail intelligently if a found file cannot be read" do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).raises(RuntimeError)
- proc { @store.find(@value) }.should raise_error(Puppet::Error)
+ proc { @store.find(@request) }.should raise_error(Puppet::Error)
end
end
@@ -112,7 +114,7 @@ describe Puppet::Checksum::File do
File.expects(:open).with(@path, "w")
file = stub 'file', :name => @value
- @store.save(file)
+ @store.save(@request)
end
it "should make any directories necessary for storage" do
@@ -122,8 +124,7 @@ describe Puppet::Checksum::File do
File.expects(:directory?).with(File.dirname(@path)).returns(true)
File.expects(:open).with(@path, "w")
- file = stub 'file', :name => @value
- @store.save(file)
+ @store.save(@request)
end
end
@@ -132,7 +133,7 @@ describe Puppet::Checksum::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:unlink).with(@path)
- @store.destroy(@value)
+ @store.destroy(@request)
end
end
end
diff --git a/spec/unit/indirector/direct_file_server.rb b/spec/unit/indirector/direct_file_server.rb
index a89b938e7..a8583716a 100755
--- a/spec/unit/indirector/direct_file_server.rb
+++ b/spec/unit/indirector/direct_file_server.rb
@@ -23,19 +23,21 @@ describe Puppet::Indirector::DirectFileServer do
@server = @direct_file_class.new
@uri = "file:///my/local"
+
+ @request = stub 'request', :key => @uri, :options => {}
end
describe Puppet::Indirector::DirectFileServer, "when finding a single file" do
it "should return nil if the file does not exist" do
FileTest.expects(:exists?).with("/my/local").returns false
- @server.find(@uri).should be_nil
+ @server.find(@request).should be_nil
end
it "should return a Content instance created with the full path to the file if the file exists" do
FileTest.expects(:exists?).with("/my/local").returns true
@model.expects(:new).returns(:mycontent)
- @server.find(@uri).should == :mycontent
+ @server.find(@request).should == :mycontent
end
end
@@ -49,18 +51,20 @@ describe Puppet::Indirector::DirectFileServer do
it "should create the Content instance with the original key as the key" do
@model.expects(:new).with { |key, options| key == @uri }.returns(@data)
- @server.find(@uri)
+ @server.find(@request)
end
it "should pass the full path to the instance" do
@model.expects(:new).with { |key, options| options[:path] == "/my/local" }.returns(@data)
- @server.find(@uri)
+ @server.find(@request)
end
it "should pass the :links setting on to the created Content instance if the file exists and there is a value for :links" do
@model.expects(:new).returns(@data)
@data.expects(:links=).with(:manage)
- @server.find(@uri, :links => :manage)
+
+ @request.stubs(:options).returns(:links => :manage)
+ @server.find(@request)
end
end
@@ -68,25 +72,27 @@ describe Puppet::Indirector::DirectFileServer do
it "should return nil if the file does not exist" do
FileTest.expects(:exists?).with("/my/local").returns false
- @server.find(@uri).should be_nil
+ @server.find(@request).should be_nil
end
it "should pass the original key to :path2instances" do
FileTest.expects(:exists?).with("/my/local").returns true
@server.expects(:path2instances).with { |uri, path, options| uri == @uri }
- @server.search(@uri)
+ @server.search(@request)
end
it "should use :path2instances from the terminus_helper to return instances if the file exists" do
FileTest.expects(:exists?).with("/my/local").returns true
@server.expects(:path2instances)
- @server.search(@uri)
+ @server.search(@request)
end
it "should pass any options on to :path2instances" do
FileTest.expects(:exists?).with("/my/local").returns true
@server.expects(:path2instances).with { |uri, path, options| options == {:testing => :one, :other => :two}}
- @server.search(@uri, :testing => :one, :other => :two)
+
+ @request.stubs(:options).returns(:testing => :one, :other => :two)
+ @server.search(@request)
end
end
end
diff --git a/spec/unit/indirector/file.rb b/spec/unit/indirector/file.rb
index fa10743ef..67ead4cdb 100755
--- a/spec/unit/indirector/file.rb
+++ b/spec/unit/indirector/file.rb
@@ -21,6 +21,8 @@ describe Puppet::Indirector::File do
@path = "/my/file"
@dir = "/my"
+
+ @request = stub 'request', :key => @path
end
describe Puppet::Indirector::File, " when finding files" do
@@ -37,7 +39,7 @@ describe Puppet::Indirector::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).returns(content)
- @searcher.find(@path)
+ @searcher.find(@request)
end
it "should create the model instance with the content as the only argument to initialization" do
@@ -48,18 +50,18 @@ describe Puppet::Indirector::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).returns(content)
- @searcher.find(@path).should equal(file)
+ @searcher.find(@request).should equal(file)
end
it "should return nil if no file is found" do
File.expects(:exist?).with(@path).returns(false)
- @searcher.find(@path).should be_nil
+ @searcher.find(@request).should be_nil
end
it "should fail intelligently if a found file cannot be read" do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).raises(RuntimeError)
- proc { @searcher.find(@path) }.should raise_error(Puppet::Error)
+ proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
end
it "should use the path() method to calculate the path if it exists" do
@@ -68,42 +70,39 @@ describe Puppet::Indirector::File do
end
File.expects(:exist?).with(@path.upcase).returns(false)
- @searcher.find(@path)
+ @searcher.find(@request)
end
end
describe Puppet::Indirector::File, " when saving files" do
+ before do
+ @content = "my content"
+ @file = stub 'file', :content => @content, :path => @path, :name => @path
+ @request.stubs(:instance).returns @file
+ end
it "should provide a method to save file contents at a specified path" do
filehandle = mock 'file'
- content = "my content"
File.expects(:directory?).with(@dir).returns(true)
File.expects(:open).with(@path, "w").yields(filehandle)
- filehandle.expects(:print).with(content)
-
- file = stub 'file', :content => content, :path => @path, :name => @path
+ filehandle.expects(:print).with(@content)
- @searcher.save(file)
+ @searcher.save(@request)
end
it "should fail intelligently if the file's parent directory does not exist" do
File.expects(:directory?).with(@dir).returns(false)
- file = stub 'file', :path => @path, :name => @path
-
- proc { @searcher.save(file) }.should raise_error(Puppet::Error)
+ proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
end
it "should fail intelligently if a file cannot be written" do
filehandle = mock 'file'
- content = "my content"
File.expects(:directory?).with(@dir).returns(true)
File.expects(:open).with(@path, "w").yields(filehandle)
- filehandle.expects(:print).with(content).raises(ArgumentError)
-
- file = stub 'file', :content => content, :path => @path, :name => @path
+ filehandle.expects(:print).with(@content).raises(ArgumentError)
- proc { @searcher.save(file) }.should raise_error(Puppet::Error)
+ proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
end
it "should use the path() method to calculate the path if it exists" do
@@ -111,10 +110,11 @@ describe Puppet::Indirector::File do
name.upcase
end
- file = stub 'file', :name => "/yay"
+ # Reset the key to something without a parent dir, so no checks are necessary
+ @request.stubs(:key).returns "/my"
- File.expects(:open).with("/YAY", "w")
- @searcher.save(file)
+ File.expects(:open).with("/MY", "w")
+ @searcher.save(@request)
end
end
@@ -124,20 +124,20 @@ describe Puppet::Indirector::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:unlink).with(@path)
- @searcher.destroy(@path)
+ @searcher.destroy(@request)
end
it "should throw an exception if the file is not found" do
File.expects(:exist?).with(@path).returns(false)
- proc { @searcher.destroy(@path) }.should raise_error(Puppet::Error)
+ proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
end
it "should fail intelligently if the file cannot be removed" do
File.expects(:exist?).with(@path).returns(true)
File.expects(:unlink).with(@path).raises(ArgumentError)
- proc { @searcher.destroy(@path) }.should raise_error(Puppet::Error)
+ proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
end
it "should use the path() method to calculate the path if it exists" do
@@ -148,7 +148,7 @@ describe Puppet::Indirector::File do
File.expects(:exist?).with("/MY/FILE").returns(true)
File.expects(:unlink).with("/MY/FILE")
- @searcher.destroy(@path)
+ @searcher.destroy(@request)
end
end
end
diff --git a/spec/unit/indirector/file_metadata/file.rb b/spec/unit/indirector/file_metadata/file.rb
index 0a37a6895..9474620c7 100755
--- a/spec/unit/indirector/file_metadata/file.rb
+++ b/spec/unit/indirector/file_metadata/file.rb
@@ -15,34 +15,38 @@ describe Puppet::Indirector::FileMetadata::File do
it "should be a subclass of the DirectFileServer terminus" do
Puppet::Indirector::FileMetadata::File.superclass.should equal(Puppet::Indirector::DirectFileServer)
end
-end
-describe Puppet::Indirector::FileMetadata::File, "when creating the instance for a single found file" do
- before do
- @metadata = Puppet::Indirector::FileMetadata::File.new
- @uri = "file:///my/local"
- @data = mock 'metadata'
- @data.stubs(:collect_attributes)
- FileTest.expects(:exists?).with("/my/local").returns true
- end
+ describe "when creating the instance for a single found file" do
+ before do
+ @metadata = Puppet::Indirector::FileMetadata::File.new
+ @uri = "file:///my/local"
+ @data = mock 'metadata'
+ @data.stubs(:collect_attributes)
+ FileTest.expects(:exists?).with("/my/local").returns true
- it "should collect its attributes when a file is found" do
- @data.expects(:collect_attributes)
+ @request = stub 'request', :key => @uri, :options => {}
+ end
- Puppet::FileServing::Metadata.expects(:new).returns(@data)
- @metadata.find(@uri).should == @data
- end
-end
+ it "should collect its attributes when a file is found" do
+ @data.expects(:collect_attributes)
-describe Puppet::Indirector::FileMetadata::File, "when searching for multiple files" do
- before do
- @metadata = Puppet::Indirector::FileMetadata::File.new
- @uri = "file:///my/local"
+ Puppet::FileServing::Metadata.expects(:new).returns(@data)
+ @metadata.find(@request).should == @data
+ end
end
- it "should collect the attributes of the instances returned" do
- FileTest.expects(:exists?).with("/my/local").returns true
- @metadata.expects(:path2instances).returns( [mock("one", :collect_attributes => nil), mock("two", :collect_attributes => nil)] )
- @metadata.search(@uri)
+ describe "when searching for multiple files" do
+ before do
+ @metadata = Puppet::Indirector::FileMetadata::File.new
+ @uri = "file:///my/local"
+
+ @request = stub 'request', :key => @uri, :options => {}
+ end
+
+ it "should collect the attributes of the instances returned" do
+ FileTest.expects(:exists?).with("/my/local").returns true
+ @metadata.expects(:path2instances).returns( [mock("one", :collect_attributes => nil), mock("two", :collect_attributes => nil)] )
+ @metadata.search(@request)
+ end
end
end
diff --git a/spec/unit/indirector/indirection.rb b/spec/unit/indirector/indirection.rb
index 8768076c6..f33444bbf 100755
--- a/spec/unit/indirector/indirection.rb
+++ b/spec/unit/indirector/indirection.rb
@@ -55,6 +55,8 @@ describe Puppet::Indirector::Indirection do
@instance = stub 'instance', :expiration => nil, :expiration= => nil, :name => "whatever"
@name = :mything
+
+ @request = stub 'instance', :key => "/my/key", :instance => @instance, :options => {}
end
it "should allow setting the ttl" do
@@ -73,57 +75,67 @@ describe Puppet::Indirector::Indirection do
Time.stubs(:now).returns now
@indirection.expiration.should == (Time.now + 100)
end
-
- describe "and looking for a model instance" do
- it "should create a request with the indirection name, the sought-after name, the :find method, and any passed arguments" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).with(@indirection.name, @name, :find, {:one => :two}).returns request
- @indirection.stubs(:check_authorization)
- @terminus.stubs(:find)
+ it "should have a method for creating an indirection request instance" do
+ @indirection.should respond_to(:request)
+ end
- @indirection.find(@name, :one => :two)
+ describe "creates a request" do
+ it "should create it with its name as the request's indirection name" do
+ Puppet::Indirector::Request.expects(:new).with { |name, *other| @indirection.name == name }
+ @indirection.request(:funtest, "yayness")
end
- it "should let the :select_terminus method choose the terminus if the method is defined" do
+ it "should require a method and key" do
+ Puppet::Indirector::Request.expects(:new).with { |name, method, key, *other| method == :funtest and key == "yayness" }
+ @indirection.request(:funtest, "yayness")
+ end
+
+ it "should support optional arguments" do
+ Puppet::Indirector::Request.expects(:new).with { |name, method, key, other| other == {:one => :two} }
+ @indirection.request(:funtest, "yayness", :one => :two)
+ end
+
+ it "should default to the arguments being nil" do
+ Puppet::Indirector::Request.expects(:new).with { |name, method, key, args| args.nil? }
+ @indirection.request(:funtest, "yayness")
+ end
+
+ it "should return the request" do
request = mock 'request'
Puppet::Indirector::Request.expects(:new).returns request
-
+ @indirection.request(:funtest, "yayness").should equal(request)
+ end
+ end
+
+ describe "and looking for a model instance" do
+ it "should let the :select_terminus method choose the terminus if the method is defined" do
# Define the method, so our respond_to? hook matches.
class << @indirection
def select_terminus(request)
end
end
- @indirection.expects(:select_terminus).with(request).returns :test_terminus
+ @indirection.expects(:select_terminus).with(@request).returns :test_terminus
@indirection.stubs(:check_authorization)
@terminus.expects(:find)
- @indirection.find(@name)
+ @indirection.find(@request)
end
it "should let the appropriate terminus perform the lookup" do
- @terminus.expects(:find).with(@name).returns(@instance)
- @indirection.find(@name).should == @instance
+ @terminus.expects(:find).with(@request).returns(@instance)
+ @indirection.find(@request).should == @instance
end
it "should return nil if nothing is returned by the terminus" do
- @terminus.expects(:find).with(@name).returns(nil)
- @indirection.find(@name).should be_nil
- end
-
- it "should extend any found instance with the Envelope module" do
- @terminus.stubs(:find).returns(@instance)
-
- @instance.expects(:extend).with(Puppet::Indirector::Envelope)
- @indirection.find(@name)
+ @terminus.expects(:find).with(@request).returns(nil)
+ @indirection.find(@request).should be_nil
end
it "should set the expiration date on any instances without one set" do
- # Otherwise, our stub method doesn't get used, so the tests fail.
- @instance.stubs(:extend)
@terminus.stubs(:find).returns(@instance)
@indirection.expects(:expiration).returns :yay
@@ -131,12 +143,10 @@ describe Puppet::Indirector::Indirection do
@instance.expects(:expiration).returns(nil)
@instance.expects(:expiration=).with(:yay)
- @indirection.find(@name)
+ @indirection.find(@request)
end
it "should not override an already-set expiration date on returned instances" do
- # Otherwise, our stub method doesn't get used, so the tests fail.
- @instance.stubs(:extend)
@terminus.stubs(:find).returns(@instance)
@indirection.expects(:expiration).never
@@ -144,7 +154,7 @@ describe Puppet::Indirector::Indirection do
@instance.expects(:expiration).returns(:yay)
@instance.expects(:expiration=).never
- @indirection.find(@name)
+ @indirection.find(@request)
end
describe "when caching is enabled" do
@@ -157,23 +167,23 @@ describe Puppet::Indirector::Indirection do
it "should first look in the cache for an instance" do
@terminus.expects(:find).never
- @cache.expects(:find).with(@name).returns @instance
+ @cache.expects(:find).with(@request).returns @instance
- @indirection.find(@name)
+ @indirection.find(@request)
end
it "should return the cached object if it is not expired" do
@instance.stubs(:expired?).returns false
@cache.stubs(:find).returns @instance
- @indirection.find(@name).should equal(@instance)
+ @indirection.find(@request).should equal(@instance)
end
it "should send a debug log if it is using the cached object" do
Puppet.expects(:debug)
@cache.stubs(:find).returns @instance
- @indirection.find(@name)
+ @indirection.find(@request)
end
it "should not return the cached object if it is expired" do
@@ -181,7 +191,7 @@ describe Puppet::Indirector::Indirection do
@cache.stubs(:find).returns @instance
@terminus.stubs(:find).returns nil
- @indirection.find(@name).should be_nil
+ @indirection.find(@request).should be_nil
end
it "should send an info log if it is using the cached object" do
@@ -190,63 +200,67 @@ describe Puppet::Indirector::Indirection do
@cache.stubs(:find).returns @instance
@terminus.stubs(:find).returns nil
- @indirection.find(@name)
+ @indirection.find(@request)
end
it "should cache any objects not retrieved from the cache" do
- @cache.expects(:find).with(@name).returns nil
+ @cache.expects(:find).with(@request).returns nil
- @terminus.expects(:find).with(@name).returns(@instance)
- @cache.expects(:save).with(@instance)
+ @terminus.expects(:find).with(@request).returns(@instance)
+ @cache.expects(:save)
- @indirection.find(@name)
+ @request.expects(:clone).returns(stub('newreq', :instance= => nil))
+
+ @indirection.find(@request)
+ end
+
+ it "should cache a clone of the request with the instance set to the cached object" do
+ @cache.expects(:find).with(@request).returns nil
+
+ newreq = mock 'request'
+ @request.expects(:clone).returns newreq
+ newreq.expects(:instance=).with(@instance)
+
+ @terminus.expects(:find).with(@request).returns(@instance)
+ @cache.expects(:save).with(newreq)
+
+ @indirection.find(@request)
end
it "should send an info log that the object is being cached" do
@cache.stubs(:find).returns nil
+ @request.expects(:clone).returns(stub('newreq', :instance= => nil))
+
@terminus.stubs(:find).returns(@instance)
@cache.stubs(:save)
Puppet.expects(:info)
- @indirection.find(@name)
+ @indirection.find(@request)
end
end
end
describe "and storing a model instance" do
- it "should create a request with the indirection name, the instance's name, the :save method, and any passed arguments" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).with(@indirection.name, @instance.name, :save, {:one => :two}).returns request
-
- @indirection.stubs(:check_authorization)
- @terminus.stubs(:save)
-
- @indirection.save(@instance, :one => :two)
- end
-
it "should let the :select_terminus method choose the terminus if the method is defined" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).returns request
-
# Define the method, so our respond_to? hook matches.
class << @indirection
- def select_terminus(request)
+ def select_terminus(req)
end
end
- @indirection.expects(:select_terminus).with(request).returns :test_terminus
+ @indirection.expects(:select_terminus).with(@request).returns :test_terminus
@indirection.stubs(:check_authorization)
@terminus.expects(:save)
- @indirection.save(@instance)
+ @indirection.save(@request)
end
it "should let the appropriate terminus store the instance" do
- @terminus.expects(:save).with(@instance).returns(@instance)
- @indirection.save(@instance).should == @instance
+ @terminus.expects(:save).with(@request).returns(@instance)
+ @indirection.save(@request).should == @instance
end
describe "when caching is enabled" do
@@ -258,50 +272,37 @@ describe Puppet::Indirector::Indirection do
end
it "should save the object to the cache" do
- @cache.expects(:save).with(@instance)
+ @cache.expects(:save).with(@request)
@terminus.stubs(:save)
- @indirection.save(@instance)
+ @indirection.save(@request)
end
end
end
describe "and removing a model instance" do
- it "should create a request with the indirection name, the name of the instance being destroyed, the :destroy method, and any passed arguments" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).with(@indirection.name, "me", :destroy, {:one => :two}).returns request
-
- @indirection.stubs(:check_authorization)
- @terminus.stubs(:destroy)
-
- @indirection.destroy("me", :one => :two)
- end
-
it "should let the :select_terminus method choose the terminus if the method is defined" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).returns request
-
# Define the method, so our respond_to? hook matches.
class << @indirection
def select_terminus(request)
end
end
- @indirection.expects(:select_terminus).with(request).returns :test_terminus
+ @indirection.expects(:select_terminus).with(@request).returns :test_terminus
@indirection.stubs(:check_authorization)
@terminus.expects(:destroy)
- @indirection.destroy(@name)
+ @indirection.destroy(@request)
end
it "should delegate the instance removal to the appropriate terminus" do
- @terminus.expects(:destroy).with(@name)
- @indirection.destroy(@name)
+ @terminus.expects(:destroy).with(@request)
+ @indirection.destroy(@request)
end
it "should return nil" do
@terminus.stubs(:destroy)
- @indirection.destroy(@name).should be_nil
+ @indirection.destroy(@request).should be_nil
end
describe "when caching is enabled" do
@@ -314,47 +315,34 @@ describe Puppet::Indirector::Indirection do
it "should destroy any found object in the cache" do
cached = mock 'cache'
- @cache.expects(:find).with(@name).returns cached
- @cache.expects(:destroy).with(@name)
+ @cache.expects(:find).with(@request).returns cached
+ @cache.expects(:destroy).with(@request)
@terminus.stubs(:destroy)
- @indirection.destroy(@name)
+ @indirection.destroy(@request)
end
end
end
describe "and searching for multiple model instances" do
- it "should create a request with the indirection name, the search key, the :search method, and any passed arguments" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).with(@indirection.name, "me", :search, {:one => :two}).returns request
-
- @indirection.stubs(:check_authorization)
- @terminus.stubs(:search)
-
- @indirection.search("me", :one => :two)
- end
-
it "should let the :select_terminus method choose the terminus if the method is defined" do
- request = mock 'request'
- Puppet::Indirector::Request.expects(:new).returns request
-
# Define the method, so our respond_to? hook matches.
class << @indirection
- def select_terminus(request)
+ def select_terminus(req)
end
end
- @indirection.expects(:select_terminus).with(request).returns :test_terminus
+ @indirection.expects(:select_terminus).with(@request).returns :test_terminus
@indirection.stubs(:check_authorization)
@terminus.expects(:search)
- @indirection.search("me")
+ @indirection.search(@request)
end
it "should let the appropriate terminus find the matching instances" do
- @terminus.expects(:search).with(@name).returns(@instance)
- @indirection.search(@name).should == @instance
+ @terminus.expects(:search).with(@request).returns(@instance)
+ @indirection.search(@request).should == @instance
end
end
@@ -365,69 +353,72 @@ describe Puppet::Indirector::Indirection do
def authorized?
end
end
+
+ @request = stub 'instance', :key => "/my/key", :instance => @instance, :options => {:node => "mynode"}
end
it "should not check authorization if a node name is not provided" do
@terminus.expects(:authorized?).never
@terminus.stubs(:find)
- @indirection.find("/my/key")
+
+ # The quotes are necessary here, else it looks like a block.
+ @request.stubs(:options).returns({})
+ @indirection.find(@request)
end
it "should pass the request to the terminus's authorization method" do
- request = stub 'request', :options => {:node => "yayhost"}
- Puppet::Indirector::Request.expects(:new).returns(request)
- @terminus.expects(:authorized?).with(request).returns(true)
+ @terminus.expects(:authorized?).with(@request).returns(true)
@terminus.stubs(:find)
- @indirection.find("/my/key", :node => "mynode")
+ @indirection.find(@request)
end
it "should fail while finding instances if authorization returns false" do
@terminus.expects(:authorized?).returns(false)
@terminus.stubs(:find)
- proc { @indirection.find("/my/key", :node => "mynode") }.should raise_error(ArgumentError)
+ proc { @indirection.find(@request) }.should raise_error(ArgumentError)
end
it "should continue finding instances if authorization returns true" do
@terminus.expects(:authorized?).returns(true)
@terminus.stubs(:find)
- @indirection.find("/my/key", :node => "mynode")
+ @indirection.find(@request)
end
it "should fail while saving instances if authorization returns false" do
@terminus.expects(:authorized?).returns(false)
@terminus.stubs(:save)
- proc { @indirection.save(@instance, :node => "mynode") }.should raise_error(ArgumentError)
+ proc { @indirection.save(@request) }.should raise_error(ArgumentError)
end
it "should continue saving instances if authorization returns true" do
@terminus.expects(:authorized?).returns(true)
@terminus.stubs(:save)
- @indirection.save(@instance, :node => "mynode")
+ @indirection.save(@request)
end
it "should fail while destroying instances if authorization returns false" do
@terminus.expects(:authorized?).returns(false)
@terminus.stubs(:destroy)
- proc { @indirection.destroy("/my/key", :node => "mynode") }.should raise_error(ArgumentError)
+ proc { @indirection.destroy(@request) }.should raise_error(ArgumentError)
end
it "should continue destroying instances if authorization returns true" do
@terminus.expects(:authorized?).returns(true)
@terminus.stubs(:destroy)
- @indirection.destroy(@instance, :node => "mynode")
+ @indirection.destroy(@request)
end
it "should fail while searching for instances if authorization returns false" do
@terminus.expects(:authorized?).returns(false)
@terminus.stubs(:search)
- proc { @indirection.search("/my/key", :node => "mynode") }.should raise_error(ArgumentError)
+ proc { @indirection.search(@request) }.should raise_error(ArgumentError)
end
it "should continue searching for instances if authorization returns true" do
@terminus.expects(:authorized?).returns(true)
@terminus.stubs(:search)
- @indirection.search("/my/key", :node => "mynode")
+ @indirection.search(@request)
end
end
diff --git a/spec/unit/indirector/memory.rb b/spec/unit/indirector/memory.rb
index 2e9a7f8f3..3b754a1eb 100755
--- a/spec/unit/indirector/memory.rb
+++ b/spec/unit/indirector/memory.rb
@@ -3,33 +3,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/indirector/memory'
-describe "A Memory Terminus", :shared => true do
- it "should find no instances by default" do
- @searcher.find(@name).should be_nil
- end
-
- it "should be able to find instances that were previously saved" do
- @searcher.save(@instance)
- @searcher.find(@name).should equal(@instance)
- end
-
- it "should replace existing saved instances when a new instance with the same name is saved" do
- @searcher.save(@instance)
- two = stub 'second', :name => @name
- @searcher.save(two)
- @searcher.find(@name).should equal(two)
- end
-
- it "should be able to remove previously saved instances" do
- @searcher.save(@instance)
- @searcher.destroy(@instance.name)
- @searcher.find(@name).should be_nil
- end
-
- it "should fail when asked to destroy an instance that does not exist" do
- proc { @searcher.destroy(@instance) }.should raise_error(ArgumentError)
- end
-end
+require 'shared_behaviours/memory_terminus'
describe Puppet::Indirector::Memory do
it_should_behave_like "A Memory Terminus"
@@ -49,5 +23,7 @@ describe Puppet::Indirector::Memory do
@searcher = @memory_class.new
@name = "me"
@instance = stub 'instance', :name => @name
+
+ @request = stub 'request', :key => @name, :instance => @instance
end
end
diff --git a/spec/unit/indirector/node/memory.rb b/spec/unit/indirector/node/memory.rb
index a924c6209..71e01d4f3 100755
--- a/spec/unit/indirector/node/memory.rb
+++ b/spec/unit/indirector/node/memory.rb
@@ -4,14 +4,15 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/indirector/node/memory'
-# All of our behaviour is described here, so we always have to include it.
-require File.dirname(__FILE__) + '/../memory'
+require 'shared_behaviours/memory_terminus'
describe Puppet::Node::Memory do
before do
@name = "me"
@searcher = Puppet::Node::Memory.new
@instance = stub 'instance', :name => @name
+
+ @request = stub 'request', :key => @name, :instance => @instance
end
it_should_behave_like "A Memory Terminus"
diff --git a/spec/unit/indirector/plain.rb b/spec/unit/indirector/plain.rb
index 1277739af..aca2816f2 100755
--- a/spec/unit/indirector/plain.rb
+++ b/spec/unit/indirector/plain.rb
@@ -17,11 +17,13 @@ describe Puppet::Indirector::Plain do
end
@searcher = @plain_class.new
+
+ @request = stub 'request', :key => "yay"
end
it "should return return an instance of the indirected model" do
object = mock 'object'
- @model.expects(:new).with("yay").returns object
- @searcher.find("yay").should equal(object)
+ @model.expects(:new).with(@request.key).returns object
+ @searcher.find(@request).should equal(object)
end
end
diff --git a/spec/unit/indirector/request.rb b/spec/unit/indirector/request.rb
index fd57c5297..cdb40b181 100755
--- a/spec/unit/indirector/request.rb
+++ b/spec/unit/indirector/request.rb
@@ -10,45 +10,45 @@ describe Puppet::Indirector::Request do
end
it "should use provided value as the key if it is a string" do
- Puppet::Indirector::Request.new(:ind, "mykey", :method).key.should == "mykey"
+ Puppet::Indirector::Request.new(:ind, :method, "mykey").key.should == "mykey"
end
it "should use provided value as the key if it is a symbol" do
- Puppet::Indirector::Request.new(:ind, :mykey, :method).key.should == :mykey
+ Puppet::Indirector::Request.new(:ind, :method, :mykey).key.should == :mykey
end
it "should use the name of the provided instance as its key if an instance is provided as the key instead of a string" do
instance = mock 'instance', :name => "mykey"
- request = Puppet::Indirector::Request.new(:ind, instance, :method)
+ request = Puppet::Indirector::Request.new(:ind, :method, instance)
request.key.should == "mykey"
request.instance.should equal(instance)
end
it "should support options specified as a hash" do
- lambda { Puppet::Indirector::Request.new(:ind, :key, :method, :one => :two) }.should_not raise_error(ArgumentError)
+ lambda { Puppet::Indirector::Request.new(:ind, :method, :key, :one => :two) }.should_not raise_error(ArgumentError)
end
it "should support nil options" do
- lambda { Puppet::Indirector::Request.new(:ind, :key, :method, nil) }.should_not raise_error(ArgumentError)
+ lambda { Puppet::Indirector::Request.new(:ind, :method, :key, nil) }.should_not raise_error(ArgumentError)
end
it "should support unspecified options" do
- lambda { Puppet::Indirector::Request.new(:ind, :key, :method) }.should_not raise_error(ArgumentError)
+ lambda { Puppet::Indirector::Request.new(:ind, :method, :key) }.should_not raise_error(ArgumentError)
end
it "should fail if options are specified as anything other than nil or a hash" do
- lambda { Puppet::Indirector::Request.new(:ind, :key, :method, [:one, :two]) }.should raise_error(ArgumentError)
+ lambda { Puppet::Indirector::Request.new(:ind, :method, :key, [:one, :two]) }.should raise_error(ArgumentError)
end
it "should use an empty options hash if nil was provided" do
- Puppet::Indirector::Request.new(:ind, :key, :method, nil).options.should == {}
+ Puppet::Indirector::Request.new(:ind, :method, :key, nil).options.should == {}
end
end
it "should look use the Indirection class to return the appropriate indirection" do
ind = mock 'indirection'
Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns ind
- request = Puppet::Indirector::Request.new(:myind, :key, :method)
+ request = Puppet::Indirector::Request.new(:myind, :method, :key)
request.indirection.should equal(ind)
end
diff --git a/spec/unit/indirector/yaml.rb b/spec/unit/indirector/yaml.rb
index 339529ab0..53d12f426 100755
--- a/spec/unit/indirector/yaml.rb
+++ b/spec/unit/indirector/yaml.rb
@@ -21,37 +21,28 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
@dir = "/what/ever"
Puppet.settings.stubs(:value).with(:yamldir).returns(@dir)
- end
-
- it "should use the mtime of the written file as the version" do
- stat = mock 'stat'
- FileTest.stubs(:exist?).returns true
- File.expects(:stat).returns stat
- time = Time.now
- stat.expects(:mtime).returns time
- @store.version(:me).should equal(time)
+ @request = stub 'request', :key => :me, :instance => @subject
end
describe Puppet::Indirector::Yaml, " when choosing file location" do
-
it "should store all files in a single file root set in the Puppet defaults" do
- @store.send(:path, :me).should =~ %r{^#{@dir}}
+ @store.path(:me).should =~ %r{^#{@dir}}
end
it "should use the terminus name for choosing the subdirectory" do
- @store.send(:path, :me).should =~ %r{^#{@dir}/my_yaml}
+ @store.path(:me).should =~ %r{^#{@dir}/my_yaml}
end
it "should use the object's name to determine the file name" do
- @store.send(:path, :me).should =~ %r{me.yaml$}
+ @store.path(:me).should =~ %r{me.yaml$}
end
end
describe Puppet::Indirector::Yaml, " when storing objects as YAML" do
-
it "should only store objects that respond to :name" do
- proc { @store.save(Object.new) }.should raise_error(ArgumentError)
+ @request.stubs(:instance).returns Object.new
+ proc { @store.save(@request) }.should raise_error(ArgumentError)
end
it "should convert Ruby objects to YAML and write them to disk" do
@@ -62,7 +53,7 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
File.expects(:open).with(path, "w", 0660).yields(file)
file.expects(:print).with(yaml)
- @store.save(@subject)
+ @store.save(@request)
end
it "should create the indirection subdirectory if it does not exist" do
@@ -75,16 +66,11 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
File.expects(:open).with(path, "w", 0660).yields(file)
file.expects(:print).with(yaml)
- @store.save(@subject)
+ @store.save(@request)
end
end
describe Puppet::Indirector::Yaml, " when retrieving YAML" do
-
- it "should require the name of the object to retrieve" do
- proc { @store.find(nil) }.should raise_error(ArgumentError)
- end
-
it "should read YAML in from disk and convert it to Ruby objects" do
path = @store.send(:path, @subject.name)
@@ -92,7 +78,7 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
FileTest.expects(:exist?).with(path).returns(true)
File.expects(:read).with(path).returns(yaml)
- @store.find(@subject.name).instance_variable_get("@name").should == :me
+ @store.find(@request).instance_variable_get("@name").should == :me
end
it "should fail coherently when the stored YAML is invalid" do
@@ -104,7 +90,7 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
FileTest.expects(:exist?).with(path).returns(true)
File.expects(:read).with(path).returns(yaml)
- proc { @store.find(@subject.name) }.should raise_error(Puppet::Error)
+ proc { @store.find(@request) }.should raise_error(Puppet::Error)
end
end
end
diff --git a/spec/unit/node.rb b/spec/unit/node.rb
index e62bd5d07..421fcd635 100755
--- a/spec/unit/node.rb
+++ b/spec/unit/node.rb
@@ -117,9 +117,9 @@ end
describe Puppet::Node, " when indirecting" do
it "should redirect to the indirection" do
- @indirection = mock 'indirection'
+ @indirection = stub 'indirection', :name => :node
Puppet::Node.stubs(:indirection).returns(@indirection)
- @indirection.expects(:find).with(:my_node.to_s)
+ @indirection.expects(:find)
Puppet::Node.find(:my_node.to_s)
end
diff --git a/spec/unit/node/catalog.rb b/spec/unit/node/catalog.rb
index 360dd87f2..cd27b925b 100755
--- a/spec/unit/node/catalog.rb
+++ b/spec/unit/node/catalog.rb
@@ -777,14 +777,14 @@ end
describe Puppet::Node::Catalog, " when indirecting" do
before do
- @indirection = mock 'indirection'
+ @indirection = stub 'indirection', :name => :catalog
Puppet::Indirector::Indirection.clear_cache
end
it "should redirect to the indirection for retrieval" do
Puppet::Node::Catalog.stubs(:indirection).returns(@indirection)
- @indirection.expects(:find).with(:myconfig)
+ @indirection.expects(:find)
Puppet::Node::Catalog.find(:myconfig)
end
diff --git a/spec/unit/node/facts.rb b/spec/unit/node/facts.rb
index 743a7082e..1bfccd32e 100755
--- a/spec/unit/node/facts.rb
+++ b/spec/unit/node/facts.rb
@@ -6,7 +6,7 @@ require 'puppet/node/facts'
describe Puppet::Node::Facts, " when indirecting" do
before do
- @indirection = mock 'indirection'
+ @indirection = stub 'indirection', :request => mock('request'), :name => :facts
# We have to clear the cache so that the facts ask for our indirection stub,
# instead of anything that might be cached.
@@ -16,13 +16,13 @@ describe Puppet::Node::Facts, " when indirecting" do
it "should redirect to the specified fact store for retrieval" do
Puppet::Node::Facts.stubs(:indirection).returns(@indirection)
- @indirection.expects(:find).with(:my_facts)
+ @indirection.expects(:find)
Puppet::Node::Facts.find(:my_facts)
end
it "should redirect to the specified fact store for storage" do
Puppet::Node::Facts.stubs(:indirection).returns(@indirection)
- @indirection.expects(:save).with(@facts)
+ @indirection.expects(:save)
@facts.save
end
diff --git a/spec/unit/transaction/report.rb b/spec/unit/transaction/report.rb
index 8fc3f0794..644f8d709 100755
--- a/spec/unit/transaction/report.rb
+++ b/spec/unit/transaction/report.rb
@@ -9,18 +9,18 @@ require 'puppet/transaction/report'
describe Puppet::Transaction::Report, " when being indirect" do
it "should redirect :find to the indirection" do
- @indirection = mock 'indirection'
+ @indirection = stub 'indirection', :name => :report
Puppet::Transaction::Report.stubs(:indirection).returns(@indirection)
- @indirection.expects(:find).with(:report)
+ @indirection.expects(:find)
Puppet::Transaction::Report.find(:report)
end
it "should redirect :save to the indirection" do
Facter.stubs(:value).returns("eh")
- @indirection = mock 'indirection'
+ @indirection = stub 'indirection', :name => :report
Puppet::Transaction::Report.stubs(:indirection).returns(@indirection)
report = Puppet::Transaction::Report.new
- @indirection.expects(:save).with(report)
+ @indirection.expects(:save)
report.save
end
@@ -28,6 +28,12 @@ describe Puppet::Transaction::Report, " when being indirect" do
Puppet::Transaction::Report.indirection.terminus_class.should == :processor
end
+ it "should delegate its name attribute to its host method" do
+ report = Puppet::Transaction::Report.new
+ report.expects(:host).returns "me"
+ report.name.should == "me"
+ end
+
after do
Puppet::Indirector::Indirection.clear_cache
end