diff options
| author | Matt Robinson <matt@puppetlabs.com> | 2011-03-22 15:46:26 -0700 |
|---|---|---|
| committer | Matt Robinson <matt@puppetlabs.com> | 2011-03-22 15:46:26 -0700 |
| commit | 8542160479538fe6575475c2dccf5d4696fa3e5d (patch) | |
| tree | a2d09b68de0e7101116062d44e622d76b0abd1f8 /lib/puppet | |
| parent | 6bf5b7fea8ef4d04809e78eef84029a0773d4747 (diff) | |
| parent | 0170cebba039378597fdf9f0086339c2766df408 (diff) | |
| download | puppet-8542160479538fe6575475c2dccf5d4696fa3e5d.tar.gz puppet-8542160479538fe6575475c2dccf5d4696fa3e5d.tar.xz puppet-8542160479538fe6575475c2dccf5d4696fa3e5d.zip | |
Merge branch 'feature/next/6257-pip_package_provider' into next
* feature/next/6257-pip_package_provider:
(#6527) Fix uninstall problem and refactor
(#6527) Added pip package provider.
Diffstat (limited to 'lib/puppet')
| -rw-r--r-- | lib/puppet/provider/package/pip.rb | 109 |
1 files changed, 109 insertions, 0 deletions
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 |
