diff options
| author | Max Martin <max@puppetlabs.com> | 2011-03-23 14:43:29 -0700 |
|---|---|---|
| committer | Max Martin <max@puppetlabs.com> | 2011-03-23 14:43:29 -0700 |
| commit | 4196699f5fbb90ceecbb709c8502622eaad39062 (patch) | |
| tree | adb06f307051368e9fe9a23c3338fe7511eb8adf /lib/puppet/provider | |
| parent | 7e71840e29cb09c772668a51ada3cab1e319e50f (diff) | |
| parent | 66d0b16c8a0a55dd79b1b0f0e639f107e552d9ab (diff) | |
| download | puppet-4196699f5fbb90ceecbb709c8502622eaad39062.tar.gz puppet-4196699f5fbb90ceecbb709c8502622eaad39062.tar.xz puppet-4196699f5fbb90ceecbb709c8502622eaad39062.zip | |
Merge branch 'next'
* next: (34 commits)
(#6820) Fix File class lookup in the file type for Ruby 1.9
(#6820) Fix nagios parser to use proper hash syntax for Ruby 1.9
(#6820) Fix Invalid multibyte character
(#6820) Fix RDOC parser to work with Ruby 1.9
(#6820) Fix invalid next that should be a return
(#2782) Fix constant_defined?
(#6527) Fix pip tests
(#6527) Fix uninstall problem and refactor
(#6527) Added pip package provider.
maint: Change code for finding spec_helper to work with Ruby 1.9
Fix error "invalid multibyte char (US-ASCII)" under Ruby 1.9
Fixed #6562 - Minor kick documentation fix
(#6566) Replace tabs with spaces
(#6566) Fix ruby 1.9 incompatible case statement
Fixed #6566 Replace ftools with filetuils in rake gem task
(#6555) Fix another ruby 1.9 incompatible case statement
Fixed #6555 - Fixed two more when then colon issues
Fixed #6555 - Ruby 1.9.x returning Invalid next (SyntaxError)
Fixed #6555 - Ruby 1.9.x warning: class variable access from toplevel
(#6658) Propagate ENC connection errors to the agent
...
Diffstat (limited to 'lib/puppet/provider')
| -rw-r--r-- | lib/puppet/provider/exec/posix.rb | 112 | ||||
| -rw-r--r-- | lib/puppet/provider/exec/shell.rb | 17 | ||||
| -rw-r--r-- | lib/puppet/provider/package/pip.rb | 109 | ||||
| -rw-r--r-- | lib/puppet/provider/service/daemontools.rb | 2 | ||||
| -rw-r--r-- | lib/puppet/provider/service/launchd.rb | 2 |
5 files changed, 240 insertions, 2 deletions
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 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 diff --git a/lib/puppet/provider/package/pip.rb b/lib/puppet/provider/package/pip.rb new file mode 100644 index 000000000..5abbc135a --- /dev/null +++ b/lib/puppet/provider/package/pip.rb @@ -0,0 +1,109 @@ +# Puppet package provider for Python's `pip` package management frontend. +# <http://pip.openplans.org/> + +require 'puppet/provider/package' +require 'xmlrpc/client' + +Puppet::Type.type(:package).provide :pip, + :parent => ::Puppet::Provider::Package do + + desc "Python packages via `pip`." + + has_feature :installable, :uninstallable, :upgradeable, :versionable + + # Parse lines of output from `pip freeze`, which are structured as + # _package_==_version_. + def self.parse(line) + if line.chomp =~ /^([^=]+)==([^=]+)$/ + {:ensure => $2, :name => $1, :provider => name} + else + nil + end + end + + # Return an array of structured information about every installed package + # that's managed by `pip` or an empty array if `pip` is not available. + def self.instances + packages = [] + pip_cmd = which('pip') or return [] + execpipe "#{pip_cmd} freeze" do |process| + process.collect do |line| + next unless options = parse(line) + packages << new(options) + end + end + packages + end + + # Return structured information about a particular package or `nil` if + # it is not installed or `pip` itself is not available. + def query + self.class.instances.each do |provider_pip| + return provider_pip.properties if @resource[:name] == provider_pip.name + end + return nil + end + + # Ask the PyPI API for the latest version number. There is no local + # cache of PyPI's package list so this operation will always have to + # ask the web service. + def latest + client = XMLRPC::Client.new2("http://pypi.python.org/pypi") + client.http_header_extra = {"Content-Type" => "text/xml"} + result = client.call("package_releases", @resource[:name]) + result.first + end + + # Install a package. The ensure parameter may specify installed, + # latest, a version number, or, in conjunction with the source + # parameter, an SCM revision. In that case, the source parameter + # gives the fully-qualified URL to the repository. + def install + args = %w{install -q} + if @resource[:source] + args << "-e" + if String === @resource[:ensure] + args << "#{@resource[:source]}@#{@resource[:ensure]}#egg=#{ + @resource[:name]}" + else + args << "#{@resource[:source]}#egg=#{@resource[:name]}" + end + else + case @resource[:ensure] + when String + args << "#{@resource[:name]}==#{@resource[:ensure]}" + when :latest + args << "--upgrade" << @resource[:name] + else + args << @resource[:name] + end + end + lazy_pip *args + end + + # Uninstall a package. Uninstall won't work reliably on Debian/Ubuntu + # unless this issue gets fixed. + # <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=562544> + def uninstall + lazy_pip "uninstall", "-y", "-q", @resource[:name] + end + + def update + install + end + + # Execute a `pip` command. If Puppet doesn't yet know how to do so, + # try to teach it and if even that fails, raise the error. + private + def lazy_pip(*args) + pip *args + rescue NoMethodError => e + if pathname = which('pip') + self.class.commands :pip => pathname + pip *args + else + raise e + end + end + +end diff --git a/lib/puppet/provider/service/daemontools.rb b/lib/puppet/provider/service/daemontools.rb index bbb962a71..f5a073329 100644 --- a/lib/puppet/provider/service/daemontools.rb +++ b/lib/puppet/provider/service/daemontools.rb @@ -67,7 +67,7 @@ Puppet::Type.type(:service).provide :daemontools, :parent => :base do path = self.defpath unless FileTest.directory?(path) Puppet.notice "Service path #{path} does not exist" - next + return end # reject entries that aren't either a directory diff --git a/lib/puppet/provider/service/launchd.rb b/lib/puppet/provider/service/launchd.rb index 07c549a8b..9d813bd5a 100644 --- a/lib/puppet/provider/service/launchd.rb +++ b/lib/puppet/provider/service/launchd.rb @@ -211,7 +211,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do job_path, job_plist = plist_from_label(resource[:name]) job_plist_disabled = job_plist["Disabled"] if job_plist.has_key?("Disabled") - if self.class.get_macosx_version_major == "10.6": + if self.class.get_macosx_version_major == "10.6" if FileTest.file?(Launchd_Overrides) and overrides = self.class.read_plist(Launchd_Overrides) if overrides.has_key?(resource[:name]) overrides_disabled = overrides[resource[:name]]["Disabled"] if overrides[resource[:name]].has_key?("Disabled") |
