1
Puppet::Type.type(:exec).provide :posix do
2
include Puppet::Util::Execution
1
require 'puppet/provider/exec'
3
Puppet::Type.type(:exec).provide :posix, :parent => Puppet::Provider::Exec do
4
4
confine :feature => :posix
5
5
defaultfor :feature => :posix
7
desc "Execute external binaries directly, on POSIX systems.
8
This does not pass through a shell, or perform any interpolation, but
9
only directly calls the command with the arguments given."
11
def run(command, check = false)
18
if dir = resource[:cwd]
19
unless File.directory?(dir)
23
self.fail "Working directory '#{dir}' does not exist"
30
debug "Executing#{check ? " check": ""} '#{command}'"
36
environment[:PATH] = resource[:path].join(":") if resource[:path]
38
if envlist = resource[:environment]
39
envlist = [envlist] unless envlist.is_a? Array
40
envlist.each do |setting|
41
if setting =~ /^(\w+)=((.|\n)+)$/
44
if environment.include?(env_name) || environment.include?(env_name.to_sym)
45
warning "Overriding environment setting '#{env_name}' with '#{value}'"
47
environment[env_name] = value
49
warning "Cannot understand environment setting #{setting.inspect}"
54
withenv environment do
55
Timeout::timeout(resource[:timeout]) do
56
output, status = Puppet::Util::SUIDManager.
57
run_and_capture([command], resource[:user], resource[:group])
59
# The shell returns 127 if the command is missing.
60
if status.exitstatus == 127
61
raise ArgumentError, output
65
rescue Errno::ENOENT => detail
8
Executes external binaries directly, without passing through a shell or
9
performing any interpolation. This is a safer and more predictable way
10
to execute most commands, but prevents the use of globbing and shell
11
built-ins (including control logic like "for" and "if" statements).
72
14
# Verify that we have the executable
73
15
def checkexe(command)
74
16
exe = extractexe(command)
18
if File.expand_path(exe) == exe
20
raise ArgumentError, "Could not find command '#{exe}'"
21
elsif !File.file?(exe)
22
raise ArgumentError, "'#{exe}' is a #{File.ftype(exe)}, not a file"
23
elsif !File.executable?(exe)
24
raise ArgumentError, "'#{exe}' is not executable"
77
if Puppet.features.posix? and !File.exists?(exe)
78
withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do
79
exe = which(exe) || raise(ArgumentError,"Could not find command '#{exe}'")
81
elsif Puppet.features.microsoft_windows? and !File.exists?(exe)
82
resource[:path].each do |path|
83
[".exe", ".ps1", ".bat", ".com", ""].each do |extension|
84
file = File.join(path, exe+extension)
85
return if File.exists?(file)
30
withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do
91
raise ArgumentError, "Could not find command '#{exe}'" unless File.exists?(exe)
92
unless File.executable?(exe)
94
"'#{exe}' is not executable"
98
def extractexe(command)
99
# easy case: command was quoted
100
if command =~ /^"([^"]+)"/
103
command.split(/ /)[0]
107
def validatecmd(command)
108
exe = extractexe(command)
109
# if we're not fully qualified, require a path
110
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?
35
# 'which' will only return the command if it's executable, so we can't
36
# distinguish not found from not executable
37
raise ArgumentError, "Could not find command '#{exe}'"