diff options
author | Luke Kanies <luke@madstop.com> | 2008-07-15 23:05:45 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2009-02-06 18:08:39 -0600 |
commit | 25b28c58c22bae718794dc679f10c61665af0b15 (patch) | |
tree | 8d8ebf094326f99dd3a9f7cfac7c329831f402c7 | |
parent | 1afb8216f166dc375dec5778890985a6635aa54f (diff) | |
download | puppet-25b28c58c22bae718794dc679f10c61665af0b15.tar.gz puppet-25b28c58c22bae718794dc679f10c61665af0b15.tar.xz puppet-25b28c58c22bae718794dc679f10c61665af0b15.zip |
Adding a new Agent::Downloader class for downloading files.
This will handling downloading facts and plugins.
Signed-off-by: Luke Kanies <luke@madstop.com>
-rw-r--r-- | lib/puppet/agent/downloader.rb | 78 | ||||
-rwxr-xr-x | spec/unit/agent/downloader.rb | 182 |
2 files changed, 260 insertions, 0 deletions
diff --git a/lib/puppet/agent/downloader.rb b/lib/puppet/agent/downloader.rb new file mode 100644 index 000000000..46a64d52d --- /dev/null +++ b/lib/puppet/agent/downloader.rb @@ -0,0 +1,78 @@ +require 'puppet/agent' + +class Puppet::Agent::Downloader + attr_reader :name, :path, :source, :ignore + + # Determine the timeout value to use. + def self.timeout + timeout = Puppet[:configtimeout] + case timeout + when String: + if timeout =~ /^\d+$/ + timeout = Integer(timeout) + else + raise ArgumentError, "Configuration timeout must be an integer" + end + when Integer: # nothing + else + raise ArgumentError, "Configuration timeout must be an integer" + end + + return timeout + end + + # Evaluate our download, returning the list of changed values. + def evaluate + Puppet.info "Retrieving #{name}" + + files = [] + begin + Timeout.timeout(self.class.timeout) do + catalog.apply do |trans| + trans.changed?.find_all do |resource| + yield resource if block_given? + files << resource[:path] + end + end + end + rescue Puppet::Error, Timeout::Error => detail + puts detail.backtrace if Puppet[:debug] + Puppet.err "Could not retrieve #{name}: %s" % detail + end + + return files + end + + def initialize(name, path, source, ignore = nil) + @name, @path, @source, @ignore = name, path, source, ignore + end + + def catalog + catalog = Puppet::Node::Catalog.new + catalog.add_resource(file) + catalog + end + + def file + args = default_arguments.merge(:path => path, :source => source) + args[:ignore] = ignore if ignore + Puppet::Type.type(:file).create(args) + end + + private + + def default_arguments + { + :path => path, + :recurse => true, + :source => source, + :tag => name, + :owner => Process.uid, + :group => Process.gid, + :purge => true, + :force => true, + :backup => false, + :noop => false + } + end +end diff --git a/spec/unit/agent/downloader.rb b/spec/unit/agent/downloader.rb new file mode 100755 index 000000000..6b07e5bb4 --- /dev/null +++ b/spec/unit/agent/downloader.rb @@ -0,0 +1,182 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/agent/downloader' + +describe Puppet::Agent::Downloader do + it "should require a name" do + lambda { Puppet::Agent::Downloader.new }.should raise_error(ArgumentError) + end + + it "should require a path and a source at initialization" do + lambda { Puppet::Agent::Downloader.new("name") }.should raise_error(ArgumentError) + end + + it "should set the name, path and source appropriately" do + dler = Puppet::Agent::Downloader.new("facts", "path", "source") + dler.name.should == "facts" + dler.path.should == "path" + dler.source.should == "source" + end + + it "should be able to provide a timeout value" do + Puppet::Agent::Downloader.should respond_to(:timeout) + end + + it "should use the configtimeout, converted to an integer, as its timeout" do + Puppet.settings.expects(:value).with(:configtimeout).returns "50" + Puppet::Agent::Downloader.timeout.should == 50 + end + + describe "when creating the file that does the downloading" do + before do + @dler = Puppet::Agent::Downloader.new("foo", "path", "source") + end + + it "should create a file instance with the right path and source" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:path] == "path" and opts[:source] == "source" } + @dler.file + end + + it "should tag the file with the downloader name" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:tag] == "foo" } + @dler.file + end + + it "should always recurse" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:recurse] == true } + @dler.file + end + + it "should always purge" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:purge] == true } + @dler.file + end + + it "should never be in noop" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:noop] == false } + @dler.file + end + + it "should always set the owner to the current UID" do + Process.expects(:uid).returns 51 + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:owner] == 51 } + @dler.file + end + + it "should always set the group to the current GID" do + Process.expects(:gid).returns 61 + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:group] == 61 } + @dler.file + end + + it "should always force the download" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:force] == true } + @dler.file + end + + it "should never back up when downloading" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:backup] == false } + @dler.file + end + + it "should support providing an 'ignore' parameter" do + Puppet::Type.type(:file).expects(:create).with { |opts| opts[:ignore] == ".svn" } + @dler = Puppet::Agent::Downloader.new("foo", "path", "source", ".svn") + @dler.file + end + end + + describe "when creating the catalog to do the downloading" do + before do + @dler = Puppet::Agent::Downloader.new("foo", "path", "source") + end + + it "should create a catalog and add the file to it" do + file = mock 'file' + catalog = mock 'catalog' + + @dler.expects(:file).returns file + + Puppet::Node::Catalog.expects(:new).returns catalog + catalog.expects(:add_resource).with(file) + + @dler.catalog.should equal(catalog) + end + end + + describe "when downloading" do + before do + @dler = Puppet::Agent::Downloader.new("foo", "path", "source") + end + + it "should log that it is downloading" do + Puppet.expects(:info) + Timeout.stubs(:timeout) + + @dler.evaluate + end + + it "should set a timeout for the download" do + Puppet::Agent::Downloader.expects(:timeout).returns 50 + Timeout.expects(:timeout).with(50) + + @dler.evaluate + end + + it "should apply the catalog within the timeout block" do + catalog = mock 'catalog' + @dler.expects(:catalog).returns(catalog) + + Timeout.expects(:timeout).yields + + catalog.expects(:apply) + + @dler.evaluate + end + + it "should return all changed file paths" do + trans = mock 'transaction' + + catalog = mock 'catalog' + @dler.expects(:catalog).returns(catalog) + catalog.expects(:apply).yields(trans) + + Timeout.expects(:timeout).yields + + resource = mock 'resource' + resource.expects(:[]).with(:path).returns "/changed/file" + + trans.expects(:changed?).returns([resource]) + + @dler.evaluate.should == %w{/changed/file} + end + + it "should yield the resources if a block is given" do + trans = mock 'transaction' + + catalog = mock 'catalog' + @dler.expects(:catalog).returns(catalog) + catalog.expects(:apply).yields(trans) + + Timeout.expects(:timeout).yields + + resource = mock 'resource' + resource.expects(:[]).with(:path).returns "/changed/file" + + trans.expects(:changed?).returns([resource]) + + yielded = nil + @dler.evaluate { |r| yielded = r } + yielded.should == resource + end + + it "should catch and log exceptions" do + Puppet.expects(:err) + Timeout.stubs(:timeout).raises(Puppet::Error, "testing") + + lambda { @dler.evaluate }.should_not raise_error + end + end +end |