summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/provider/exec/posix.rb32
-rwxr-xr-xspec/unit/provider/exec/posix_spec.rb209
2 files changed, 120 insertions, 121 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/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