diff options
25 files changed, 594 insertions, 65 deletions
diff --git a/lib/puppet/file_serving/configuration.rb b/lib/puppet/file_serving/configuration.rb index b1512e14e..6cd99b267 100644 --- a/lib/puppet/file_serving/configuration.rb +++ b/lib/puppet/file_serving/configuration.rb @@ -30,13 +30,22 @@ class Puppet::FileServing::Configuration # Return a content instance. def content(path, options = {}) - mount, file_path = splitpath(path, options[:node]) + mount, file_path = split_path(path, options[:node]) return nil unless mount mount.file_instance :content, file_path, options end + # Search for a file. + def file_path(key, options = {}) + mount, file_path = split_path(key, options[:node]) + + return nil unless mount + + return mount.file(file_path, options) + end + def initialize @mounts = {} @config_file = nil @@ -48,32 +57,13 @@ class Puppet::FileServing::Configuration # Return a metadata instance. def metadata(path, options = {}) - mount, file_path = splitpath(path, options[:node]) + mount, file_path = split_path(path, options[:node]) return nil unless mount mount.file_instance :metadata, file_path, options end - # Mount a new directory with a name. - def mount(path, name) - if @mounts.include?(name) - if @mounts[name] != path - raise FileServerError, "%s is already mounted at %s" % - [@mounts[name].path, name] - else - # it's already mounted; no problem - return - end - end - - # Let the mounts do their own error-checking. - @mounts[name] = Mount.new(name, path) - @mounts[name].info "Mounted %s" % path - - return @mounts[name] - end - # Is a given mount available? def mounted?(name) @mounts.include?(name) @@ -137,7 +127,7 @@ class Puppet::FileServing::Configuration end # Split the path into the separate mount point and path. - def splitpath(uri, node) + def split_path(uri, node) # Reparse the configuration if necessary. readconfig diff --git a/lib/puppet/file_serving/metadata.rb b/lib/puppet/file_serving/metadata.rb index 73e1f53d4..7adb66981 100644 --- a/lib/puppet/file_serving/metadata.rb +++ b/lib/puppet/file_serving/metadata.rb @@ -23,12 +23,7 @@ class Puppet::FileServing::Metadata @checksum_type = type end - def initialize(path, checksum_type = "md5") - raise ArgumentError.new("Files must be fully qualified") unless path =~ /^#{::File::SEPARATOR}/ - raise ArgumentError.new("Files must exist") unless FileTest.exists?(path) - - @path = path - + def get_attributes stat = File.stat(path) @owner = stat.uid @group = stat.gid @@ -36,10 +31,20 @@ class Puppet::FileServing::Metadata # Set the octal mode, but as a string. @mode = "%o" % (stat.mode & 007777) - @checksum_type = checksum_type @checksum = get_checksum end + def initialize(path = nil) + if path + raise ArgumentError.new("Files must be fully qualified") unless path =~ /^#{::File::SEPARATOR}/ + raise ArgumentError.new("Files must exist") unless FileTest.exists?(path) + + @path = path + end + + @checksum_type = "md5" + end + private # Retrieve our checksum. diff --git a/lib/puppet/file_serving/terminus_helper.rb b/lib/puppet/file_serving/terminus_helper.rb new file mode 100644 index 000000000..b7f560c57 --- /dev/null +++ b/lib/puppet/file_serving/terminus_helper.rb @@ -0,0 +1,22 @@ +# +# Created by Luke Kanies on 2007-10-16. +# Copyright (c) 2007. All rights reserved. + +require 'uri' +require 'puppet/file_serving' +require 'puppet/file_serving/configuration' + +module Puppet::FileServing::TerminusHelper + def key2uri(key) + # Return it directly if it's fully qualified. + if key =~ /^#{::File::SEPARATOR}/ + key = "file://" + key + end + + begin + uri = URI.parse(URI.escape(key)) + rescue => detail + raise ArgumentError, "Could not understand URI %s: %s" % [key, detail.to_s] + end + end +end diff --git a/lib/puppet/file_serving/terminus_selector.rb b/lib/puppet/file_serving/terminus_selector.rb index 0cec4bf98..4525a8570 100644 --- a/lib/puppet/file_serving/terminus_selector.rb +++ b/lib/puppet/file_serving/terminus_selector.rb @@ -9,18 +9,26 @@ require 'puppet/file_serving' # in file-serving indirections. This is necessary because # the terminus varies based on the URI asked for. module Puppet::FileServing::TerminusSelector - PROTOCOL_MAP = {"puppet" => :rest, "file" => :local} + PROTOCOL_MAP = {"puppet" => :rest, "file" => :local, "puppetmounts" => :mounts} # Pick an appropriate terminus based on the protocol. - def select_terminus(uri) + def select_terminus(full_uri) # Short-circuit to :local if it's a fully-qualified path. - return PROTOCOL_MAP["file"] if uri =~ /^#{::File::SEPARATOR}/ + return PROTOCOL_MAP["file"] if full_uri =~ /^#{::File::SEPARATOR}/ begin - uri = URI.parse(URI.escape(uri)) + uri = URI.parse(URI.escape(full_uri)) rescue => detail - raise ArgumentError, "Could not understand URI %s: %s" % [uri, detail.to_s] + raise ArgumentError, "Could not understand URI %s: %s" % [full_uri, detail.to_s] end - return PROTOCOL_MAP[uri.scheme] || raise(ArgumentError, "URI protocol '%s' is not supported for file serving" % uri.scheme) + terminus = PROTOCOL_MAP[uri.scheme] || raise(ArgumentError, "URI protocol '%s' is not supported for file serving" % uri.scheme) + + # This provides a convenient mechanism for people to write configurations work + # well in both a networked and local setting. + if uri.host.nil? and uri.scheme == "puppet" and Puppet.settings[:name] == "puppet" + terminus = :mounts + end + + return terminus end end diff --git a/lib/puppet/indirector/file_content/local.rb b/lib/puppet/indirector/file_content/local.rb index 34d1c7794..a597fea55 100644 --- a/lib/puppet/indirector/file_content/local.rb +++ b/lib/puppet/indirector/file_content/local.rb @@ -3,12 +3,19 @@ # Copyright (c) 2007. All rights reserved. require 'puppet/file_serving/content' +require 'puppet/file_serving/terminus_helper' require 'puppet/indirector/file_content' require 'puppet/indirector/file' class Puppet::Indirector::FileContent::Local < Puppet::Indirector::File desc "Retrieve file contents from disk." - def find(path) + include Puppet::FileServing::TerminusHelper + + def find(key) + uri = key2uri(key) + + return nil unless FileTest.exists?(uri.path) + Puppet::FileServing::Content.new uri.path end end diff --git a/lib/puppet/indirector/file_content/mounts.rb b/lib/puppet/indirector/file_content/mounts.rb new file mode 100644 index 000000000..3d147d65a --- /dev/null +++ b/lib/puppet/indirector/file_content/mounts.rb @@ -0,0 +1,28 @@ +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require 'puppet/file_serving/content' +require 'puppet/file_serving/terminus_helper' +require 'puppet/indirector/file_content' +require 'puppet/indirector/code' + +class Puppet::Indirector::FileContent::Mounts < Puppet::Indirector::Code + desc "Retrieve file contents using Puppet's fileserver." + + include Puppet::FileServing::TerminusHelper + + # This way it can be cleared or whatever and we aren't retaining + # a reference to the old one. + def configuration + Puppet::FileServing::Configuration.create + end + + def find(key) + uri = key2uri(key) + + return nil unless path = configuration.file_path(uri.path) and FileTest.exists?(path) + + Puppet::FileServing::Content.new path + end +end diff --git a/lib/puppet/indirector/file_content/rest.rb b/lib/puppet/indirector/file_content/rest.rb new file mode 100644 index 000000000..9e2de360c --- /dev/null +++ b/lib/puppet/indirector/file_content/rest.rb @@ -0,0 +1,12 @@ +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require 'puppet/file_serving/content' +require 'puppet/file_serving/terminus_helper' +require 'puppet/indirector/file_content' +require 'puppet/indirector/rest' + +class Puppet::Indirector::FileContent::Rest < Puppet::Indirector::REST + desc "Retrieve file contents via a REST HTTP interface." +end diff --git a/lib/puppet/indirector/file_metadata/local.rb b/lib/puppet/indirector/file_metadata/local.rb index f6cfa1f1c..e1d774cc8 100644 --- a/lib/puppet/indirector/file_metadata/local.rb +++ b/lib/puppet/indirector/file_metadata/local.rb @@ -4,13 +4,21 @@ require 'puppet/file_serving/metadata' require 'puppet/indirector/file_metadata' +require 'puppet/file_serving/terminus_helper' require 'puppet/indirector/code' class Puppet::Indirector::FileMetadata::Local < Puppet::Indirector::Code - desc "Retrieve file metadata using Puppet's Resource Abstraction Layer. - Returns everything about the file except its content." + desc "Retrieve file metadata directly from the local filesystem." - def find(file) - Puppet::Node::Facts.new(key, Facter.to_hash) + include Puppet::FileServing::TerminusHelper + + def find(key) + uri = key2uri(key) + + return nil unless FileTest.exists?(uri.path) + data = Puppet::FileServing::Metadata.new uri.path + data.get_attributes + + return data end end diff --git a/lib/puppet/indirector/file_metadata/mounts.rb b/lib/puppet/indirector/file_metadata/mounts.rb new file mode 100644 index 000000000..6d7fe15c6 --- /dev/null +++ b/lib/puppet/indirector/file_metadata/mounts.rb @@ -0,0 +1,28 @@ +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require 'puppet/file_serving/metadata' +require 'puppet/file_serving/terminus_helper' +require 'puppet/indirector/file_metadata' +require 'puppet/indirector/code' + +class Puppet::Indirector::FileMetadata::Mounts < Puppet::Indirector::Code + desc "Retrieve file metadata using Puppet's fileserver." + + include Puppet::FileServing::TerminusHelper + + # This way it can be cleared or whatever and we aren't retaining + # a reference to the old one. + def configuration + Puppet::FileServing::Configuration.create + end + + def find(key) + uri = key2uri(key) + + return nil unless path = configuration.file_path(uri.path) and FileTest.exists?(path) + + Puppet::FileServing::Metadata.new path + end +end diff --git a/lib/puppet/indirector/file_metadata/rest.rb b/lib/puppet/indirector/file_metadata/rest.rb new file mode 100644 index 000000000..dcf875b25 --- /dev/null +++ b/lib/puppet/indirector/file_metadata/rest.rb @@ -0,0 +1,12 @@ +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require 'puppet/file_serving/metadata' +require 'puppet/file_serving/terminus_helper' +require 'puppet/indirector/file_metadata' +require 'puppet/indirector/rest' + +class Puppet::Indirector::FileMetadata::Rest < Puppet::Indirector::REST + desc "Retrieve file metadata via a REST HTTP interface." +end diff --git a/spec/integration/file_serving/content.rb b/spec/integration/file_serving/content.rb new file mode 100755 index 000000000..aee2a9f2d --- /dev/null +++ b/spec/integration/file_serving/content.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/file_serving/content' +require 'shared_behaviours/file_serving' + +describe Puppet::FileServing::Content, " when finding files" do + it_should_behave_like "Puppet::FileServing::Files" + + before do + @test_class = Puppet::FileServing::Content + @indirection = Puppet::FileServing::Content.indirection + end +end diff --git a/spec/integration/file_serving/metadata.rb b/spec/integration/file_serving/metadata.rb new file mode 100755 index 000000000..5600365f1 --- /dev/null +++ b/spec/integration/file_serving/metadata.rb @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/file_serving/metadata' +require 'shared_behaviours/file_serving' + +describe Puppet::FileServing::Metadata, " when finding files" do + it_should_behave_like "Puppet::FileServing::Files" + + before do + @test_class = Puppet::FileServing::Metadata + @indirection = Puppet::FileServing::Metadata.indirection + end +end + diff --git a/spec/integration/indirector/file_content/mounts.rb b/spec/integration/indirector/file_content/mounts.rb new file mode 100755 index 000000000..cd80825c7 --- /dev/null +++ b/spec/integration/indirector/file_content/mounts.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/file_content/mounts' +require 'shared_behaviours/file_server_mounts' + +describe Puppet::Indirector::FileContent::Mounts, " when finding files" do + it_should_behave_like "Puppet::Indirector::FileServerMounts" + + before do + @terminus = Puppet::Indirector::FileContent::Mounts.new + @test_class = Puppet::FileServing::Content + end +end diff --git a/spec/integration/indirector/file_metadata/mounts.rb b/spec/integration/indirector/file_metadata/mounts.rb new file mode 100755 index 000000000..5899a9dbd --- /dev/null +++ b/spec/integration/indirector/file_metadata/mounts.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/file_metadata/mounts' +require 'shared_behaviours/file_server_mounts' + +describe Puppet::Indirector::FileMetadata::Mounts, " when finding files" do + it_should_behave_like "Puppet::Indirector::FileServerMounts" + + before do + @terminus = Puppet::Indirector::FileMetadata::Mounts.new + @test_class = Puppet::FileServing::Metadata + end +end diff --git a/spec/lib/shared_behaviours/file_server_mounts.rb b/spec/lib/shared_behaviours/file_server_mounts.rb new file mode 100644 index 000000000..955f88b44 --- /dev/null +++ b/spec/lib/shared_behaviours/file_server_mounts.rb @@ -0,0 +1,37 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +describe "Puppet::Indirector::FileServerMounts", :shared => true do + # This only works if the shared behaviour is included before + # the 'before' block in the including context. + before do + Puppet::FileServing::Configuration.clear_cache + FileTest.stubs(:exists?).with(Puppet[:fileserverconfig]).returns(true) + FileTest.stubs(:exists?).with("/my/mount/path").returns(true) + FileTest.stubs(:directory?).with("/my/mount/path").returns(true) + FileTest.stubs(:readable?).with("/my/mount/path").returns(true) + + # Use a real mount, so the integration is a bit deeper. + @mount1 = Puppet::FileServing::Configuration::Mount.new("one") + @mount1.path = "/my/mount/path" + + @parser = stub 'parser', :changed? => false + @parser.stubs(:parse).returns("one" => @mount1) + + Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) + + Puppet::FileServing::Configuration.create.stubs(:modules_mount) + end + + it "should use the file server configuration to find files" do + path = "/my/mount/path/my/file" + FileTest.stubs(:exists?).with(path).returns(true) + @test_class.expects(:new).with(path).returns(:myinstance) + FileTest.stubs(:exists?).with("/my/mount/path").returns(true) + @mount1.expects(:file).with("my/file", {}).returns(path) + + @terminus.find("puppetmounts://myhost/one/my/file").should == :myinstance + end +end diff --git a/spec/lib/shared_behaviours/file_serving.rb b/spec/lib/shared_behaviours/file_serving.rb new file mode 100644 index 000000000..ffc96ee78 --- /dev/null +++ b/spec/lib/shared_behaviours/file_serving.rb @@ -0,0 +1,49 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +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) + @test_class.find(uri) + end + + it "should use the rest terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is not 'puppet'" 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) + @test_class.find(uri) + end + + it "should use the mounts terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is 'puppet'" do + uri = "puppet:///mymod/my/file" + Puppet.settings.stubs(:value).with(:name).returns("puppet") + Puppet.settings.stubs(:value).with(:modulepath).returns("") + Puppet.settings.stubs(:value).with(:libdir).returns("") + Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever") + @indirection.terminus(:mounts).expects(:find).with(uri) + @test_class.find(uri) + end + + it "should use the mounts terminus when the 'puppetmounts' URI scheme is used" do + uri = "puppetmounts:///mymod/my/file" + @indirection.terminus(:mounts).expects(:find).with(uri) + @test_class.find(uri) + end + + it "should use the local terminus when the 'file' URI scheme is used" do + uri = "file:///mymod/my/file" + @indirection.terminus(:local).expects(:find).with(uri) + @test_class.find(uri) + end + + it "should use the local terminus when a fully qualified path is provided" do + uri = "/mymod/my/file" + @indirection.terminus(:local).expects(:find).with(uri) + @test_class.find(uri) + end +end + diff --git a/spec/unit/file_serving/configuration.rb b/spec/unit/file_serving/configuration.rb index eabad0838..b0b3527e7 100755 --- a/spec/unit/file_serving/configuration.rb +++ b/spec/unit/file_serving/configuration.rb @@ -117,9 +117,7 @@ describe Puppet::FileServing::Configuration, " when using a module mount" do it "should prefer module mounts to static mounts" end -# We're kind of testing the implementation here, because we know that both -# content and metadata use the same internal method. Oh well. -describe Puppet::FileServing::Configuration, " when using File URIs to pick the correct mount and file" do +describe Puppet::FileServing::Configuration, " when finding files" do include FSConfigurationTesting before do @@ -139,48 +137,50 @@ describe Puppet::FileServing::Configuration, " when using File URIs to pick the it "should fail if the uri does not match a leading slash followed by a valid mount name" do @parser.expects(:parse).returns(@mounts) - proc { @config.metadata("something") }.should raise_error(ArgumentError) + proc { @config.file_path("something") }.should raise_error(ArgumentError) end it "should use the first term after the first slash for the mount name" do @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file_instance) - @config.metadata("/one") + @mount1.expects(:file) + @config.file_path("/one") end it "should use the remainder of the URI after the mount name as the file name" do @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file_instance).with(:metadata, "something/else", {}) - @config.metadata("/one/something/else") + @mount1.expects(:file).with("something/else", {}) + @config.file_path("/one/something/else") end it "should treat a bare name as a mount and no relative file" do @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file_instance).with(:metadata, nil, {}) - @config.metadata("/one") + @mount1.expects(:file).with(nil, {}) + @config.file_path("/one") end it "should treat a name with a trailing slash equivalently to a name with no trailing slash" do @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file_instance).with(:metadata, nil, {}) - @config.metadata("/one/") + @mount1.expects(:file).with(nil, {}) + @config.file_path("/one/") end it "should return nil if the mount cannot be found" do @parser.expects(:changed?).returns(true) @parser.expects(:parse).returns({}) - @config.metadata("/one/something").should be_nil + @config.file_path("/one/something").should be_nil end + it "should return nil if the mount does not contain the file" + it "should reparse the configuration file when it has changed" do - @mount1.stubs(:file_instance).returns("whatever") + @mount1.stubs(:file).returns("whatever") @parser.expects(:changed?).returns(true) @parser.expects(:parse).returns(@mounts) - @config.metadata("/one/something") + @config.file_path("/one/something") @parser.expects(:changed?).returns(true) @parser.expects(:parse).returns({}) - @config.metadata("/one/something").should be_nil + @config.file_path("/one/something").should be_nil end end diff --git a/spec/unit/file_serving/content.rb b/spec/unit/file_serving/content.rb index 6d8e2d0ba..593278bf4 100755 --- a/spec/unit/file_serving/content.rb +++ b/spec/unit/file_serving/content.rb @@ -33,7 +33,7 @@ describe Puppet::FileServing::Content, " when initializing" do proc { Puppet::FileServing::Content.new(@path) }.should raise_error(ArgumentError) end - it "should not read the file" do + it "should not stat the file" do FileTest.expects(:exists?).with(@path).returns(true) File.expects(:read).with(@path).never Puppet::FileServing::Content.new(@path) @@ -52,3 +52,13 @@ describe Puppet::FileServing::Content, " when converting to yaml" do @content.to_yaml.should == "mycontent" end end + +describe Puppet::FileServing::Content, " when converting from yaml" do + # LAK:FIXME This isn't in the right place, but we need some kind of + # control somewhere that requires that all REST connections only pull + # from the file-server, thus guaranteeing they go through our authorization + # hook. + it "should set the URI scheme to 'puppetmounts'" do + pending "We need to figure out where this should be" + end +end diff --git a/spec/unit/file_serving/metadata.rb b/spec/unit/file_serving/metadata.rb index f54a6feb6..1237c3184 100755 --- a/spec/unit/file_serving/metadata.rb +++ b/spec/unit/file_serving/metadata.rb @@ -15,11 +15,19 @@ describe Puppet::FileServing::Metadata do end describe Puppet::FileServing::Metadata, " when initializing" do - it "should require a fully qualified file path" do + it "should allow initialization without a path" do + proc { Puppet::FileServing::Metadata.new() }.should_not raise_error + end + + it "should allow initialization with a path" do + proc { Puppet::FileServing::Metadata.new("unqualified") }.should raise_error(ArgumentError) + end + + it "should the path to be fully qualified if it is provied" do proc { Puppet::FileServing::Metadata.new("unqualified") }.should raise_error(ArgumentError) end - it "should require the path to exist" do + it "should require the path to exist if it is provided" do FileTest.expects(:exists?).with("/no/such/path").returns(false) proc { Puppet::FileServing::Metadata.new("/no/such/path") }.should raise_error(ArgumentError) end @@ -36,6 +44,7 @@ describe Puppet::FileServing::Metadata do @checksum = Digest::MD5.hexdigest("some content\n") FileTest.expects(:exists?).with(@path).returns(true) @metadata = Puppet::FileServing::Metadata.new(@path) + @metadata.get_attributes end it "should accept a file path" do @@ -76,3 +85,13 @@ describe Puppet::FileServing::Metadata do @metadata.checksum.should == "{md5}" + @checksum end end + +describe Puppet::FileServing::Metadata, " when converting from yaml" do + # LAK:FIXME This isn't in the right place, but we need some kind of + # control somewhere that requires that all REST connections only pull + # from the file-server, thus guaranteeing they go through our authorization + # hook. + it "should set the URI scheme to 'puppetmounts'" do + pending "We need to figure out where this should be" + end +end diff --git a/spec/unit/file_serving/terminus_helper.rb b/spec/unit/file_serving/terminus_helper.rb new file mode 100755 index 000000000..f136da553 --- /dev/null +++ b/spec/unit/file_serving/terminus_helper.rb @@ -0,0 +1,50 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/file_serving/terminus_helper' + +module TerminusHelperTesting + def setup + @helper = Object.new + @config = mock 'fs configuration' + Puppet::FileServing::Configuration.stubs(:create).returns(@config) + @helper.extend(Puppet::FileServing::TerminusHelper) + end +end + +describe Puppet::FileServing::TerminusHelper, " when converting a key to a URI" do + include TerminusHelperTesting + + it "should escape the key before parsing" do + URI.expects(:escape).with("mykey").returns("http://myhost/blah") + URI.expects(:parse).with("http://myhost/blah").returns(:myuri) + @helper.key2uri("mykey").should == :myuri + end + + it "should use the URI class to parse the key" do + URI.expects(:parse).with("http://myhost/blah").returns(:myuri) + @helper.key2uri("http://myhost/blah").should == :myuri + end + + it "should set the scheme to 'file' if the key is a fully qualified path" do + URI.expects(:parse).with("file:///myhost/blah").returns(:myuri) + @helper.key2uri("/myhost/blah").should == :myuri + end + + it "should set the host to 'nil' if the key is a fully qualified path" do + URI.expects(:parse).with("file:///myhost/blah").returns(:myuri) + @helper.key2uri("/myhost/blah").should == :myuri + end +end + +describe Puppet::FileServing::TerminusHelper, " when returning file paths" do + include TerminusHelperTesting + + it "should follow links if the links option is set to :follow" + + it "should ignore links if the links option is not set to follow" +end diff --git a/spec/unit/file_serving/terminus_selector.rb b/spec/unit/file_serving/terminus_selector.rb index 4a5683e88..d21e42839 100755 --- a/spec/unit/file_serving/terminus_selector.rb +++ b/spec/unit/file_serving/terminus_selector.rb @@ -13,10 +13,37 @@ describe Puppet::FileServing::TerminusSelector, " when being used to select term @object.extend(Puppet::FileServing::TerminusSelector) end + it "should escape the key before parsing" do + uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something" + URI.expects(:escape).with("mykey").returns("http://myhost/blah") + URI.expects(:parse).with("http://myhost/blah").returns(uri) + @object.select_terminus("mykey") + end + + it "should use the URI class to parse the key" do + uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something" + URI.expects(:parse).with("http://myhost/blah").returns(uri) + @object.select_terminus("http://myhost/blah") + end + it "should choose :rest when the protocol is 'puppet'" do @object.select_terminus("puppet://host/module/file").should == :rest end + it "should choose :mounts when the protocol is 'puppetmounts'" do + @object.select_terminus("puppetmounts://host/module/file").should == :mounts + end + + it "should choose :mounts when no server name is provided and the process name is 'puppet'" do + Puppet.settings.expects(:value).with(:name).returns("puppet") + @object.select_terminus("puppet:///module/file").should == :mounts + end + + it "should choose :rest when no server name is provided and the process name is not 'puppet'" do + Puppet.settings.expects(:value).with(:name).returns("puppetd") + @object.select_terminus("puppet:///module/file").should == :rest + end + it "should choose :local when the protocol is 'file'" do @object.select_terminus("file://host/module/file").should == :local end @@ -25,7 +52,7 @@ describe Puppet::FileServing::TerminusSelector, " when being used to select term @object.select_terminus("/module/file").should == :local end - it "should fail when a protocol other than :puppet or :file is used" do + it "should fail when a protocol other than :puppet, :file, or :puppetmounts is used" do proc { @object.select_terminus("http:///module/file") }.should raise_error(ArgumentError) end end diff --git a/spec/unit/indirector/file_content/local.rb b/spec/unit/indirector/file_content/local.rb index 81ebd8ed0..361628767 100755 --- a/spec/unit/indirector/file_content/local.rb +++ b/spec/unit/indirector/file_content/local.rb @@ -17,13 +17,21 @@ describe Puppet::Indirector::FileContent::Local do end end -describe Puppet::Indirector::FileContent::Local, "when finding a single local" do - before do +describe Puppet::Indirector::FileContent::Local, "when finding a single file" do + it "should return a Content instance created with the full path to the file if the file exists" do @content = Puppet::Indirector::FileContent::Local.new - @path = "/my/local" + @uri = "file:///my/local" + + FileTest.expects(:exists?).with("/my/local").returns true + Puppet::FileServing::Content.expects(:new).with("/my/local").returns(:mycontent) + @content.find(@uri).should == :mycontent end - it "should return nil if the local does not exist" + it "should return nil if the file does not exist" do + @content = Puppet::Indirector::FileContent::Local.new + @uri = "file:///my/local" - it "should return a Content instance with the path set to the local if the local exists" + FileTest.expects(:exists?).with("/my/local").returns false + @content.find(@uri).should be_nil + end end diff --git a/spec/unit/indirector/file_content/mounts.rb b/spec/unit/indirector/file_content/mounts.rb new file mode 100755 index 000000000..0a137d57e --- /dev/null +++ b/spec/unit/indirector/file_content/mounts.rb @@ -0,0 +1,53 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/file_content/mounts' + +describe Puppet::Indirector::FileContent::Mounts do + it "should be registered with the file_content indirection" do + Puppet::Indirector::Terminus.terminus_class(:file_content, :mounts).should equal(Puppet::Indirector::FileContent::Mounts) + end + + it "should be a subclass of the Code terminus" do + Puppet::Indirector::FileContent::Mounts.superclass.should equal(Puppet::Indirector::Code) + end +end + +describe Puppet::Indirector::FileContent::Mounts, "when finding a single file" do + before do + @content = Puppet::Indirector::FileContent::Mounts.new + @uri = "puppetmounts://host/my/local" + end + + it "should use the path portion of the URI as the file name" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local") + @content.find(@uri) + end + + it "should use the FileServing configuration to convert the file name to a fully qualified path" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local") + @content.find(@uri) + end + + it "should return nil if no fully qualified path is found" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local").returns(nil) + @content.find(@uri).should be_nil + end + + it "should return nil if the configuration returns a file path that does not exist" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local").returns("/some/file") + FileTest.expects(:exists?).with("/some/file").returns(false) + @content.find(@uri).should be_nil + end + + it "should return a Content instance if a file is found and it exists" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local").returns("/some/file") + FileTest.expects(:exists?).with("/some/file").returns(true) + Puppet::FileServing::Content.expects(:new).with("/some/file").returns(:mycontent) + @content.find(@uri).should == :mycontent + end +end diff --git a/spec/unit/indirector/file_metadata/local.rb b/spec/unit/indirector/file_metadata/local.rb index 26837b911..604cdf6af 100755 --- a/spec/unit/indirector/file_metadata/local.rb +++ b/spec/unit/indirector/file_metadata/local.rb @@ -12,3 +12,32 @@ describe Puppet::Indirector::FileMetadata::Local do Puppet::Indirector::Terminus.terminus_class(:file_metadata, :local).should equal(Puppet::Indirector::FileMetadata::Local) end end + +describe Puppet::Indirector::FileMetadata::Local, "when finding a single file" do + before do + @content = Puppet::Indirector::FileMetadata::Local.new + @uri = "file:///my/local" + + @data = mock 'metadata' + end + it "should return a Metadata instance created with the full path to the file if the file exists" do + @data.stubs(:get_attributes) + + FileTest.expects(:exists?).with("/my/local").returns true + Puppet::FileServing::Metadata.expects(:new).with("/my/local").returns(@data) + @content.find(@uri).should == @data + end + + it "should collect its attributes when a file is found" do + @data.expects(:get_attributes) + + FileTest.expects(:exists?).with("/my/local").returns true + Puppet::FileServing::Metadata.expects(:new).with("/my/local").returns(@data) + @content.find(@uri).should == @data + end + + it "should return nil if the file does not exist" do + FileTest.expects(:exists?).with("/my/local").returns false + @content.find(@uri).should be_nil + end +end diff --git a/spec/unit/indirector/file_metadata/mounts.rb b/spec/unit/indirector/file_metadata/mounts.rb new file mode 100755 index 000000000..558e920ee --- /dev/null +++ b/spec/unit/indirector/file_metadata/mounts.rb @@ -0,0 +1,54 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2007-10-18. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet/indirector/file_metadata/mounts' + +describe Puppet::Indirector::FileMetadata::Mounts do + it "should be registered with the file_metadata indirection" do + Puppet::Indirector::Terminus.terminus_class(:file_metadata, :mounts).should equal(Puppet::Indirector::FileMetadata::Mounts) + end + + it "should be a subclass of the Code terminus" do + Puppet::Indirector::FileMetadata::Mounts.superclass.should equal(Puppet::Indirector::Code) + end +end + +describe Puppet::Indirector::FileMetadata::Mounts, "when finding a single file" do + before do + @metadata = Puppet::Indirector::FileMetadata::Mounts.new + @uri = "puppetmounts://host/my/local" + end + + it "should use the path portion of the URI as the file name" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local") + @metadata.find(@uri) + end + + it "should use the FileServing configuration to convert the file name to a fully qualified path" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local") + @metadata.find(@uri) + end + + it "should return nil if no fully qualified path is found" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local").returns(nil) + @metadata.find(@uri).should be_nil + end + + it "should return nil if the configuration returns a file path that does not exist" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local").returns("/some/file") + FileTest.expects(:exists?).with("/some/file").returns(false) + @metadata.find(@uri).should be_nil + end + + it "should return a Metadata instance if a file is found and it exists" do + Puppet::FileServing::Configuration.create.expects(:file_path).with("/my/local").returns("/some/file") + FileTest.expects(:exists?).with("/some/file").returns(true) + Puppet::FileServing::Metadata.expects(:new).with("/some/file").returns(:mymetadata) + @metadata.find(@uri).should == :mymetadata + end +end + |