diff options
| author | Matt Robinson <matt@puppetlabs.com> | 2011-04-14 11:55:08 -0700 |
|---|---|---|
| committer | Matt Robinson <matt@puppetlabs.com> | 2011-04-14 11:55:08 -0700 |
| commit | d88b3763cea9e116c8abf45ca2aa4ec80fa20349 (patch) | |
| tree | e99852d0e36cdb8bcfacc49fb85c00dfbb844ec5 /lib/puppet/provider/package | |
| parent | 97e9e5f223cb7baefd52456e2324c592fe415dca (diff) | |
| parent | 174e87a9b150a06a4ff9d696a6008fc08b05568b (diff) | |
| download | puppet-d88b3763cea9e116c8abf45ca2aa4ec80fa20349.tar.gz puppet-d88b3763cea9e116c8abf45ca2aa4ec80fa20349.tar.xz puppet-d88b3763cea9e116c8abf45ca2aa4ec80fa20349.zip | |
Merge branch 'feature/master/4258-pkgutil' into 2.7.x
* feature/master/4258-pkgutil: (29 commits)
(#4258) Fix pkgutil spec test to have the correct provider
(#4258) Remove superfluous command check that called pkgutil
(#4258) Fix fd leak opening pkgutil config files
(#4258) Permit variations of -nv in both pkgutil.conf files
(#4258) Stop file and config checks from breaking spec
(#4258) Check wgetopts in pkgutil.conf
(#4258) Fix hash duplication affecting canonical provider instance
(#4258) Use pkgutil -a to reliably determine package common names/aliases
(#4258) Update pkgutil spec for recent impl changes
(#4258) pkgutil: bug fix: if shortname is not equal to package name
(#4258) pkgutil provider: better handling of short package names
(#4258) pkgutil provider: misc enhancements
Add spec tests for pkgutil package provider
* Fix exception on parse failure of pkgutil output * Fix exception when querying latest version for unknown package
Fixing indentation
Removing blastwave references and unused PAGER
Changing indentation to 2-spaces as per 2.6+ style
Single package queries made more robust when dealing with pkgutil noise
Fixing wget verbose regex
These regular expressions will not match anything. pkgutil doesn't output anything that can be matched.
...
Diffstat (limited to 'lib/puppet/provider/package')
| -rwxr-xr-x | lib/puppet/provider/package/pkgutil.rb | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/lib/puppet/provider/package/pkgutil.rb b/lib/puppet/provider/package/pkgutil.rb new file mode 100755 index 000000000..a1d844f73 --- /dev/null +++ b/lib/puppet/provider/package/pkgutil.rb @@ -0,0 +1,175 @@ +# Packaging using Peter Bonivart's pkgutil program. +Puppet::Type.type(:package).provide :pkgutil, :parent => :sun, :source => :sun do + desc "Package management using Peter Bonivart's ``pkgutil`` command on Solaris." + + pkgutil_bin = "pkgutil" + if FileTest.executable?("/opt/csw/bin/pkgutil") + pkgutil_bin = "/opt/csw/bin/pkgutil" + end + + confine :operatingsystem => :solaris + + commands :pkguti => pkgutil_bin + + def self.healthcheck() + unless FileTest.exists?("/var/opt/csw/pkgutil/admin") + Puppet.notice "It is highly recommended you create '/var/opt/csw/pkgutil/admin'." + Puppet.notice "See /var/opt/csw/pkgutil" + end + + correct_wgetopts = false + [ "/opt/csw/etc/pkgutil.conf", "/etc/opt/csw/pkgutil.conf" ].each do |confpath| + File.open(confpath) do |conf| + conf.each {|line| correct_wgetopts = true if line =~ /^\s*wgetopts\s*=.*(-nv|-q|--no-verbose|--quiet)/ } + end + end + if ! correct_wgetopts + Puppet.notice "It is highly recommended that you set 'wgetopts=-nv' in your pkgutil.conf." + end + end + + def self.instances(hash = {}) + healthcheck + + # Use the available pkg list (-a) to work out aliases + aliases = {} + availlist.each do |pkg| + aliases[pkg[:name]] = pkg[:alias] + end + + # The -c pkglist lists installed packages + pkginsts = [] + pkglist(hash).each do |pkg| + pkg.delete(:avail) + pkginsts << new(pkg) + + # Create a second instance with the alias if it's different + pkgalias = aliases[pkg[:name]] + if pkgalias and pkg[:name] != pkgalias + apkg = pkg.dup + apkg[:name] = pkgalias + pkginsts << new(apkg) + end + end + + pkginsts + end + + # Turns a pkgutil -a listing into hashes with the common alias, full + # package name and available version + def self.availlist + output = pkguti ["-a"] + + list = output.split("\n").collect do |line| + next if line =~ /^common\s+package/ # header of package list + next if noise?(line) + + if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ + { :alias => $1, :name => $2, :avail => $3 } + else + Puppet.warning "Cannot match %s" % line + end + end.reject { |h| h.nil? } + end + + # Turn our pkgutil -c listing into a bunch of hashes. + # Supports :justme => packagename, which uses the optimised --single arg + def self.pkglist(hash) + command = ["-c"] + + if hash[:justme] + # The --single option speeds up the execution, because it queries + # the package managament system for one package only. + command << "--single" + command << hash[:justme] + end + + output = pkguti(command).split("\n") + + if output[-1] == "Not in catalog" + Puppet.warning "Package not in pkgutil catalog: %s" % hash[:justme] + return nil + end + + list = output.collect do |line| + next if line =~ /installed\s+catalog/ # header of package list + next if noise?(line) + + pkgsplit(line) + end.reject { |h| h.nil? } + + if hash[:justme] + # Single queries may have been for an alias so return the name requested + if list.any? + list[-1][:name] = hash[:justme] + return list[-1] + end + else + list.reject! { |h| h[:ensure] == :absent } + return list + end + end + + # Identify common types of pkgutil noise as it downloads catalogs etc + def self.noise?(line) + true if line =~ /^#/ + true if line =~ /^Checking integrity / # use_gpg + true if line =~ /^gpg: / # gpg verification + true if line =~ /^=+> / # catalog fetch + true if line =~ /\d+:\d+:\d+ URL:/ # wget without -q + false + end + + # Split the different lines into hashes. + def self.pkgsplit(line) + if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ + hash = {} + hash[:name] = $1 + hash[:ensure] = if $2 == "notinst" + :absent + else + $2 + end + hash[:avail] = $3 + + if hash[:avail] =~ /^SAME\s*$/ + hash[:avail] = hash[:ensure] + end + + # Use the name method, so it works with subclasses. + hash[:provider] = self.name + + return hash + else + Puppet.warning "Cannot match %s" % line + return nil + end + end + + def install + pkguti "-y", "-i", @resource[:name] + end + + # Retrieve the version from the current package file. + def latest + hash = self.class.pkglist(:justme => @resource[:name]) + hash[:avail] if hash + end + + def query + if hash = self.class.pkglist(:justme => @resource[:name]) + hash + else + {:ensure => :absent} + end + end + + def update + pkguti "-y", "-u", @resource[:name] + end + + def uninstall + pkguti "-y", "-r", @resource[:name] + end +end + |
