diff options
author | Nick Lewis <nick@puppetlabs.com> | 2011-08-16 11:45:55 -0700 |
---|---|---|
committer | Nick Lewis <nick@puppetlabs.com> | 2011-08-16 11:45:55 -0700 |
commit | 66d852bb2c2b66ff5e7c9966fdb510e2edd529db (patch) | |
tree | c5e682eda7956676f43091927723842c76f6802d | |
parent | 39116d4a6ed4861e46b16ba26c679a8b346fca00 (diff) | |
parent | 1049458461b5ec5e1e48ad0244d63eb24626b09d (diff) | |
download | puppet-66d852bb2c2b66ff5e7c9966fdb510e2edd529db.tar.gz puppet-66d852bb2c2b66ff5e7c9966fdb510e2edd529db.tar.xz puppet-66d852bb2c2b66ff5e7c9966fdb510e2edd529db.zip |
Merge branch '2.7.x'
Conflicts:
lib/puppet/provider/augeas/augeas.rb
spec/unit/node_spec.rb
-rw-r--r-- | lib/puppet/provider/exec/posix.rb | 32 | ||||
-rwxr-xr-x | lib/puppet/type/exec.rb | 17 | ||||
-rwxr-xr-x | spec/integration/node_spec.rb | 3 | ||||
-rwxr-xr-x | spec/unit/application/apply_spec.rb | 10 | ||||
-rwxr-xr-x | spec/unit/node_spec.rb | 5 | ||||
-rwxr-xr-x | spec/unit/provider/exec/posix_spec.rb | 209 |
6 files changed, 142 insertions, 134 deletions
diff --git a/lib/puppet/provider/exec/posix.rb b/lib/puppet/provider/exec/posix.rb index 157d0f28d..782f1eac6 100644 --- a/lib/puppet/provider/exec/posix.rb +++ b/lib/puppet/provider/exec/posix.rb @@ -76,26 +76,26 @@ Puppet::Type.type(:exec).provide :posix do def checkexe(command) exe = extractexe(command) - if resource[:path] - if Puppet.features.posix? and !File.exists?(exe) - withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do - exe = which(exe) || raise(ArgumentError,"Could not find command '#{exe}'") - end - elsif Puppet.features.microsoft_windows? and !File.exists?(exe) - resource[:path].each do |path| - [".exe", ".ps1", ".bat", ".com", ""].each do |extension| - file = File.join(path, exe+extension) - return if File.exists?(file) - end - end + if File.expand_path(exe) == exe + if !File.exists?(exe) + raise ArgumentError, "Could not find command '#{exe}'" + elsif !File.file?(exe) + raise ArgumentError, "'#{exe}' is a #{File.ftype(exe)}, not a file" + elsif !File.executable?(exe) + raise ArgumentError, "'#{exe}' is not executable" end + return end - raise ArgumentError, "Could not find command '#{exe}'" unless File.exists?(exe) - unless File.executable?(exe) - raise ArgumentError, - "'#{exe}' is not executable" + if resource[:path] + withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do + return if which(exe) + end end + + # 'which' will only return the command if it's executable, so we can't + # distinguish not found from not executable + raise ArgumentError, "Could not find command '#{exe}'" end def extractexe(command) diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb index 3ba488f19..35e0c96d7 100755 --- a/lib/puppet/type/exec.rb +++ b/lib/puppet/type/exec.rb @@ -311,17 +311,20 @@ module Puppet end newcheck(:creates, :parent => Puppet::Parameter::Path) do - desc "A file that this command creates. If this + desc <<-EOT + A file that this command creates. If this parameter is provided, then the command will only be run - if the specified file does not exist: + if the specified file does not exist. - exec { \"tar xf /my/tar/file.tar\": - cwd => \"/var/tmp\", - creates => \"/var/tmp/myfile\", - path => [\"/usr/bin\", \"/usr/sbin\"] + exec { "tar -xf /Volumes/nfs02/important.tar": + cwd => "/var/tmp", + creates => "/var/tmp/myfile", + path => ["/usr/bin", "/usr/sbin"] } - " + In this example, if `/var/tmp/myfile` is ever deleted, the exec + will bring it back by re-extracting the tarball. + EOT accept_arrays diff --git a/spec/integration/node_spec.rb b/spec/integration/node_spec.rb index 4ea6142e2..b81a1fdc3 100755 --- a/spec/integration/node_spec.rb +++ b/spec/integration/node_spec.rb @@ -10,6 +10,9 @@ require 'puppet/node' describe Puppet::Node do describe "when delegating indirection calls" do before do + Puppet::Node.indirection.reset_terminus_class + Puppet::Node.indirection.cache_class = nil + @name = "me" @node = Puppet::Node.new(@name) end diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb index f3ad893d3..1723258a6 100755 --- a/spec/unit/application/apply_spec.rb +++ b/spec/unit/application/apply_spec.rb @@ -12,6 +12,14 @@ describe Puppet::Application::Apply do Puppet::Util::Log.stubs(:newdestination) end + after :each do + Puppet::Node::Facts.indirection.reset_terminus_class + Puppet::Node::Facts.indirection.cache_class = nil + + Puppet::Node.indirection.reset_terminus_class + Puppet::Node.indirection.cache_class = nil + end + [:debug,:loadclasses,:verbose,:use_nodes,:detailed_exitcodes].each do |option| it "should declare handle_#{option} method" do @apply.should respond_to("handle_#{option}".to_sym) @@ -48,7 +56,6 @@ describe Puppet::Application::Apply do end describe "during setup" do - before :each do Puppet::Log.stubs(:newdestination) Puppet.stubs(:parse_config) @@ -111,7 +118,6 @@ describe Puppet::Application::Apply do end describe "when executing" do - it "should dispatch to 'apply' if it was called with 'apply'" do @apply.options[:catalog] = "foo" diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index 5f3e3b44d..a47c716f4 100755 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -201,11 +201,8 @@ end describe Puppet::Node, "when indirecting" do it "should default to the 'plain' node terminus" do Puppet::Node.indirection.reset_terminus_class - Puppet::Node.indirection.terminus_class.should == :plain - end - it "should not have a cache class defined" do - Puppet::Node.indirection.cache_class.should be_nil + Puppet::Node.indirection.terminus_class.should == :plain end end diff --git a/spec/unit/provider/exec/posix_spec.rb b/spec/unit/provider/exec/posix_spec.rb index 50697d826..876b9724d 100755 --- a/spec/unit/provider/exec/posix_spec.rb +++ b/spec/unit/provider/exec/posix_spec.rb @@ -1,120 +1,119 @@ #!/usr/bin/env rspec require 'spec_helper' -provider_class = Puppet::Type.type(:exec).provider(:posix) +describe Puppet::Type.type(:exec).provider(:posix) do + include PuppetSpec::Files + + def make_exe + command = tmpfile('my_command') + FileUtils.touch(command) + File.chmod(0755, command) + command + end + + let(:resource) { Puppet::Type.type(:exec).new(:title => '/foo') } + let(:provider) { described_class.new(resource) } -describe provider_class do before :each do - @resource = Puppet::Resource.new(:exec, 'foo') - @provider = provider_class.new(@resource) + Puppet.features.stubs(:posix?).returns(true) + Puppet.features.stubs(:microsoft_windows?).returns(false) + end + + describe "#validatecmd" do + it "should fail if no path is specified and the command is not fully qualified" do + expect { provider.validatecmd("foo") }.to raise_error( + Puppet::Error, + "'foo' is not qualified and no path was specified. Please qualify the command or specify a path." + ) + end + + it "should pass if a path is given" do + provider.resource[:path] = ['/bogus/bin'] + provider.validatecmd("../foo") + end + + it "should pass if command is fully qualifed" do + provider.resource[:path] = ['/bogus/bin'] + provider.validatecmd("/bin/blah/foo") + end end - ["posix", "microsoft_windows"].each do |feature| - describe "when in #{feature} environment" do - before :each do - if feature == "microsoft_windows" - Puppet.features.stubs(:microsoft_windows?).returns(true) - Puppet.features.stubs(:posix?).returns(false) - else - Puppet.features.stubs(:posix?).returns(true) - Puppet.features.stubs(:microsoft_windows?).returns(false) - end + describe "#run" do + describe "when the command is an absolute path" do + let(:command) { tmpfile('foo') } + + it "should fail if the command doesn't exist" do + expect { provider.run(command) }.to raise_error(ArgumentError, "Could not find command '#{command}'") + end + + it "should fail if the command isn't a file" do + FileUtils.mkdir(command) + FileUtils.chmod(0755, command) + + expect { provider.run(command) }.to raise_error(ArgumentError, "'#{command}' is a directory, not a file") + end + + it "should fail if the command isn't executable" do + FileUtils.touch(command) + + expect { provider.run(command) }.to raise_error(ArgumentError, "'#{command}' is not executable") + end + end + + describe "when the command is a relative path" do + it "should execute the command if it finds it in the path and is executable" do + command = make_exe + provider.resource[:path] = [File.dirname(command)] + filename = File.basename(command) + + Puppet::Util.expects(:execute).with { |cmdline, arguments| (cmdline == [filename]) && (arguments.is_a? Hash) } + + provider.run(filename) end - describe "#validatecmd" do - it "should fail if no path is specified and the command is not fully qualified" do - lambda { @provider.validatecmd("foo") }.should raise_error( - Puppet::Error, - "'foo' is not qualified and no path was specified. Please qualify the command or specify a path." - ) - end - - it "should pass if a path is given" do - @provider.resource[:path] = ['/bogus/bin'] - @provider.validatecmd("../foo") - end - - it "should pass if command is fully qualifed" do - @provider.resource[:path] = ['/bogus/bin'] - @provider.validatecmd("/bin/blah/foo") - end + it "should fail if the command isn't in the path" do + resource[:path] = ["/fake/path"] + + expect { provider.run('foo') }.to raise_error(ArgumentError, "Could not find command 'foo'") end - describe "#run" do - it "should fail if no path is specified and command does not exist" do - lambda { @provider.run("foo") }.should raise_error(ArgumentError, "Could not find command 'foo'") - end - - it "should fail if the command isn't in the path" do - @provider.resource[:path] = ['/bogus/bin'] - lambda { @provider.run("foo") }.should raise_error(ArgumentError, "Could not find command 'foo'") - end - - it "should fail if the command isn't executable" do - @provider.resource[:path] = ['/bogus/bin'] - File.stubs(:exists?).with("foo").returns(true) - - lambda { @provider.run("foo") }.should raise_error(ArgumentError, "'foo' is not executable") - end - - it "should not be able to execute shell builtins" do - @provider.resource[:path] = ['/bin'] - lambda { @provider.run("cd ..") }.should raise_error(ArgumentError, "Could not find command 'cd'") - end - - it "should execute the command if the command given includes arguments or subcommands" do - @provider.resource[:path] = ['/bogus/bin'] - File.stubs(:exists?).returns(false) - File.stubs(:exists?).with("foo").returns(true) - File.stubs(:executable?).with("foo").returns(true) - - Puppet::Util.expects(:execute).with() { |command, arguments| (command == ['foo bar --sillyarg=true --blah']) && (arguments.is_a? Hash) } - @provider.run("foo bar --sillyarg=true --blah") - end - - it "should fail if quoted command doesn't exist" do - @provider.resource[:path] = ['/bogus/bin'] - File.stubs(:exists?).returns(false) - File.stubs(:exists?).with("foo").returns(true) - File.stubs(:executable?).with("foo").returns(true) - - lambda { @provider.run('"foo bar --sillyarg=true --blah"') }.should raise_error(ArgumentError, "Could not find command 'foo bar --sillyarg=true --blah'") - end - - it "should execute the command if it finds it in the path and is executable" do - @provider.resource[:path] = ['/bogus/bin'] - File.stubs(:exists?).with("foo").returns(true) - File.stubs(:executable?).with("foo").returns(true) - Puppet::Util.expects(:execute).with() { |command, arguments| (command == ['foo']) && (arguments.is_a? Hash) } - - @provider.run("foo") - end - - if feature == "microsoft_windows" - [".exe", ".ps1", ".bat", ".com", ""].each do |extension| - it "should check file extension #{extension} when it can't find the executable" do - @provider.resource[:path] = ['/bogus/bin'] - File.stubs(:exists?).returns(false) - File.stubs(:exists?).with("/bogus/bin/foo#{extension}").returns(true) - File.stubs(:executable?).with("foo").returns(true) - Puppet::Util.expects(:execute).with() { |command, arguments| (command == ['foo']) && (arguments.is_a? Hash) } - - @provider.run("foo") - end - end - end - - it "should warn if you're overriding something in environment" do - @provider.resource[:environment] = ['WHATEVER=/something/else', 'WHATEVER=/foo'] - File.stubs(:exists?).returns(false) - File.stubs(:exists?).with("foo").returns(true) - File.stubs(:executable?).with("foo").returns(true) - - Puppet::Util.expects(:execute).with() { |command, arguments| (command == ['foo']) && (arguments.is_a? Hash) } - @provider.run("foo") - @logs.map {|l| "#{l.level}: #{l.message}" }.should == ["warning: Overriding environment setting 'WHATEVER' with '/foo'"] - end + it "should fail if the command is in the path but not executable" do + command = tmpfile('foo') + FileUtils.touch(command) + resource[:path] = [File.dirname(command)] + filename = File.basename(command) + + expect { provider.run(filename) }.to raise_error(ArgumentError, "Could not find command '#{filename}'") end end + + it "should not be able to execute shell builtins" do + provider.resource[:path] = ['/bin'] + expect { provider.run("cd ..") }.to raise_error(ArgumentError, "Could not find command 'cd'") + end + + it "should execute the command if the command given includes arguments or subcommands" do + provider.resource[:path] = ['/bogus/bin'] + command = make_exe + + Puppet::Util.expects(:execute).with { |cmdline, arguments| (cmdline == ["#{command} bar --sillyarg=true --blah"]) && (arguments.is_a? Hash) } + provider.run("#{command} bar --sillyarg=true --blah") + end + + it "should fail if quoted command doesn't exist" do + provider.resource[:path] = ['/bogus/bin'] + command = "/foo bar --sillyarg=true --blah" + + expect { provider.run(%Q["#{command}"]) }.to raise_error(ArgumentError, "Could not find command '#{command}'") + end + + it "should warn if you're overriding something in environment" do + provider.resource[:environment] = ['WHATEVER=/something/else', 'WHATEVER=/foo'] + command = make_exe + + Puppet::Util.expects(:execute).with { |cmdline, arguments| (cmdline== [command]) && (arguments.is_a? Hash) } + provider.run(command) + @logs.map {|l| "#{l.level}: #{l.message}" }.should == ["warning: Overriding environment setting 'WHATEVER' with '/foo'"] + end end end |