diff options
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 |