require 'puppet/provider'
require 'puppet/util/execution'
class Puppet::Provider::Exec < Puppet::Provider
include Puppet::Util::Execution
def environment
env = {}
if (path = resource[:path])
env[:PATH] = path.join(File::PATH_SEPARATOR)
end
return env unless (envlist = resource[:environment])
envlist = [envlist] unless envlist.is_a? Array
envlist.each do |setting|
unless (match = /^(\w+)=((.|\n)*)$/.match(setting))
warning _("Cannot understand environment setting %{setting}") % { setting: setting.inspect }
next
end
var = match[1]
value = match[2]
if env.include?(var) || env.include?(var.to_sym)
warning _("Overriding environment setting '%{var}' with '%{value}'") % { var: var, value: value }
end
if value.nil? || value.empty?
msg = _("Empty environment setting '%{var}'") % {var: var}
Puppet.warn_once('undefined_variables', "empty_env_var_#{var}", msg, resource.file, resource.line)
end
env[var] = value
end
env
end
def run(command, check = false)
output = nil
sensitive = resource.parameters[:command].sensitive
checkexe(command)
debug "Executing#{check ? " check": ""} '#{sensitive ? '[redacted]' : command}'"
# Ruby 2.1 and later interrupt execution in a way that bypasses error
# handling by default. Passing Timeout::Error causes an exception to be
# raised that can be rescued inside of the block by cleanup routines.
#
# This is backwards compatible all the way to Ruby 1.8.7.
Timeout::timeout(resource[:timeout], Timeout::Error) do
cwd = resource[:cwd]
# It's ok if cwd is nil. In that case Puppet::Util::Execution.execute() simply will not attempt to
# change the working directory, which is exactly the right behavior when no cwd parameter is
# expressed on the resource. Moreover, attempting to change to the directory that is already
# the working directory can fail under some circumstances, so avoiding the directory change attempt
# is preferable to defaulting cwd to that directory.
# note that we are passing "false" for the "override_locale" parameter, which ensures that the user's
# default/system locale will be respected. Callers may override this behavior by setting locale-related
# environment variables (LANG, LC_ALL, etc.) in their 'environment' configuration.
output = Puppet::Util::Execution.execute(
command,
:failonfail => false,
:combine => true,
:cwd => cwd,
:uid => resource[:user], :gid => resource[:group],
:override_locale => false,
:custom_environment => environment(),
:sensitive => sensitive
)
end
# The shell returns 127 if the command is missing.
if output.exitstatus == 127
raise ArgumentError, output
end
# Return output twice as processstatus was returned before, but only exitstatus was ever called.
# Output has the exitstatus on it so it is returned instead. This is here twice as changing this
# would result in a change to the underlying API.
return output, output
end
def extractexe(command)
if command.is_a? Array
command.first
else
match = /^"([^"]+)"|^'([^']+)'/.match(command)
if match
# extract whichever of the two sides matched the content.
match[1] or match[2]
else
command.split(/ /)[0]
end
end
end
def validatecmd(command)
exe = extractexe(command)
# if we're not fully qualified, require a path
self.fail _("'%{exe}' is not qualified and no path was specified. Please qualify the command or specify a path.") % { exe: exe } if !absolute_path?(exe) and resource[:path].nil?
end
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez