From fa0cfc60ccf43fcf9b4339b63b748b5f177c1e75 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 15 Mar 2011 11:50:29 -0700 Subject: (#4884) Break the exec type out to have a posix provider This is in preparation for allowing other new providers to handle exec commands differently. Reviewed-by: Max Martin and Matt Robinson --- lib/puppet/provider/exec/posix.rb | 112 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 lib/puppet/provider/exec/posix.rb (limited to 'lib/puppet/provider/exec') diff --git a/lib/puppet/provider/exec/posix.rb b/lib/puppet/provider/exec/posix.rb new file mode 100644 index 000000000..92dbd8c98 --- /dev/null +++ b/lib/puppet/provider/exec/posix.rb @@ -0,0 +1,112 @@ +Puppet::Type.type(:exec).provide :posix do + include Puppet::Util::Execution + + confine :feature => :posix + defaultfor :feature => :posix + + desc "Execute external binaries directly, on POSIX systems. +This does not pass through a shell, or perform any interpolation, but +only directly calls the command with the arguments given." + + def run(command, check = false) + output = nil + status = nil + dir = nil + + checkexe(command) + + if dir = resource[:cwd] + unless File.directory?(dir) + if check + dir = nil + else + self.fail "Working directory '#{dir}' does not exist" + end + end + end + + dir ||= Dir.pwd + + debug "Executing#{check ? " check": ""} '#{command}'" + begin + # Do our chdir + Dir.chdir(dir) do + environment = {} + + environment[:PATH] = resource[:path].join(":") if resource[:path] + + if envlist = resource[:environment] + envlist = [envlist] unless envlist.is_a? Array + envlist.each do |setting| + if setting =~ /^(\w+)=((.|\n)+)$/ + env_name = $1 + value = $2 + if environment.include?(env_name) || environment.include?(env_name.to_sym) + warning "Overriding environment setting '#{env_name}' with '#{value}'" + end + environment[env_name] = value + else + warning "Cannot understand environment setting #{setting.inspect}" + end + end + end + + withenv environment do + Timeout::timeout(resource[:timeout]) do + output, status = Puppet::Util::SUIDManager. + run_and_capture([command], resource[:user], resource[:group]) + end + # The shell returns 127 if the command is missing. + if status.exitstatus == 127 + raise ArgumentError, output + end + end + end + rescue Errno::ENOENT => detail + self.fail detail.to_s + end + + return output, status + end + + # Verify that we have the executable + 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 + end + end + + raise ArgumentError, "Could not find command '#{exe}'" unless File.exists?(exe) + unless File.executable?(exe) + raise ArgumentError, + "'#{exe}' is not executable" + end + end + + def extractexe(command) + # easy case: command was quoted + if command =~ /^"([^"]+)"/ + $1 + else + command.split(/ /)[0] + end + end + + def validatecmd(command) + exe = extractexe(command) + # if we're not fully qualified, require a path + self.fail "'#{command}' is not qualified and no path was specified. Please qualify the command or specify a path." if File.expand_path(exe) != exe and resource[:path].nil? + end +end -- cgit From 0d2d6f3f005ee99658ff86b79749f0ba7949beab Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 15 Mar 2011 11:52:10 -0700 Subject: (#4884) Add an shell provider for execs This makes it possible to use shell builtins when the exec is inline bash commands. Paired-with: Max Martin --- lib/puppet/provider/exec/shell.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/puppet/provider/exec/shell.rb (limited to 'lib/puppet/provider/exec') diff --git a/lib/puppet/provider/exec/shell.rb b/lib/puppet/provider/exec/shell.rb new file mode 100644 index 000000000..98f309e8f --- /dev/null +++ b/lib/puppet/provider/exec/shell.rb @@ -0,0 +1,17 @@ +Puppet::Type.type(:exec).provide :shell, :parent => :posix do + include Puppet::Util::Execution + + confine :feature => :posix + + desc "Execute external binaries directly, on POSIX systems. +passing through a shell so that shell built ins are available." + + def run(command, check = false) + command = %Q{/bin/sh -c "#{command.gsub(/"/,'\"')}"} + super(command, check) + end + + def validatecmd(command) + true + end +end -- cgit