Puppet::Type.type(:package).provide :zypper, :parent => :rpm, :source => :rpm do
desc "Support for SuSE `zypper` package manager. Found in SLES10sp2+ and SLES11.
This provider supports the `install_options` attribute, which allows command-line flags to be passed to zypper.
These options should be specified as an array where each element is either a
string or a hash."
has_feature :versionable, :install_options, :virtual_packages
commands :zypper => "/usr/bin/zypper"
defaultfor :operatingsystem => [:suse, :sles, :sled, :opensuse]
confine :operatingsystem => [:suse, :sles, :sled, :opensuse]
# @api private
# Reset the latest version hash to nil
# needed for spec tests to clear cached value
def self.reset!
@latest_versions = nil
end
def self.latest_package_version(package)
if @latest_versions.nil?
@latest_versions = list_updates
end
@latest_versions[package]
end
def self.list_updates
output = zypper 'list-updates'
avail_updates = {}
# split up columns
output.lines.each do |line|
pkg_ver = line.split(/\s*\|\s*/)
# ignore zypper headers
next unless pkg_ver[0] == 'v'
avail_updates[pkg_ver[2]] = pkg_ver[4]
end
avail_updates
end
#on zypper versions <1.0, the version option returns 1
#some versions of zypper output on stderr
def zypper_version
cmd = [self.class.command(:zypper),"--version"]
execute(cmd, { :failonfail => false, :combine => true})
end
def best_version(should)
if should.is_a?(String)
begin
should_range = Puppet::Util::Package::Version::Range.parse(should, Puppet::Util::Package::Version::Rpm)
rescue Puppet::Util::Package::Version::Range::ValidationFailure, Puppet::Util::Package::Version::Rpm::ValidationFailure
Puppet.debug("Cannot parse #{should} as a RPM version range")
return should
end
if should_range.is_a?(Puppet::Util::Package::Version::Range::Eq)
return should
end
sorted_versions = SortedSet.new
output = zypper('search', '--match-exact', '--type', 'package', '--uninstalled-only', '-s', @resource[:name])
output.lines.each do |line|
pkg_ver = line.split(/\s*\|\s*/)
next unless pkg_ver[1] == @resource[:name]
begin
rpm_version = Puppet::Util::Package::Version::Rpm.parse(pkg_ver[3])
sorted_versions << rpm_version if should_range.include?(rpm_version)
rescue Puppet::Util::Package::Version::Rpm::ValidationFailure
Puppet.debug("Cannot parse #{pkg_ver[3]} as a RPM version")
end
end
return sorted_versions.entries.last if sorted_versions.any?
Puppet.debug("No available version for package #{@resource[:name]} is included in range #{should_range}")
should
end
end
# Install a package using 'zypper'.
def install
should = @resource.should(:ensure)
self.debug "Ensuring => #{should}"
wanted = @resource[:name]
# XXX: We don't actually deal with epochs here.
case should
when true, false, Symbol
should = nil
else
# Add the package version
should = best_version(should)
wanted = "#{wanted}-#{should}"
end
#This has been tested with following zypper versions
#SLE 10.4: 0.6.201
#SLE 11.3: 1.6.307
#SLE 12.0: 1.11.14
#Assume that this will work on newer zypper versions
#extract version numbers and convert to integers
major, minor, patch = zypper_version.scan(/\d+/).map{ |x| x.to_i }
self.debug "Detected zypper version #{major}.#{minor}.#{patch}"
#zypper version < 1.0 does not support --quiet flag
if major < 1
quiet = '--terse'
else
quiet = '--quiet'
end
inst_opts = []
inst_opts = install_options if resource[:install_options]
options = []
options << quiet
options << '--no-gpg-check' unless inst_opts.delete('--no-gpg-check').nil?
options << '--no-gpg-checks' unless inst_opts.delete('--no-gpg-checks').nil?
options << :install
#zypper 0.6.13 (OpenSuSE 10.2) does not support auto agree with licenses
options << '--auto-agree-with-licenses' unless major < 1 and minor <= 6 and patch <= 13
options << '--no-confirm'
options += inst_opts unless inst_opts.empty?
# Zypper 0.6.201 doesn't recognize '--name'
# It is unclear where this functionality was introduced, but it
# is present as early as 1.0.13
options << '--name' unless major < 1 || @resource.allow_virtual? || should
options << wanted
zypper(*options)
unless self.query
raise Puppet::ExecutionFailure.new(
_("Could not find package %{name}") % { name: self.name }
)
end
end
# What's the latest package version available?
def latest
return self.class.latest_package_version(@resource[:name]) ||
# zypper didn't find updates, pretend the current
# version is the latest
@property_hash[:ensure]
end
def update
# zypper install can be used for update, too
self.install
end
def uninstall
#extract version numbers and convert to integers
major, minor, _ = zypper_version.scan(/\d+/).map{ |x| x.to_i }
if major < 1
super
else
options = [:remove, '--no-confirm']
if major == 1 && minor < 6
options << '--force-resolution'
end
options << @resource[:name]
zypper(*options)
end
end
def insync?(is)
return false if [:purged, :absent].include?(is)
should = @resource[:ensure]
if should.is_a?(String)
begin
should_version = Puppet::Util::Package::Version::Range.parse(should, Puppet::Util::Package::Version::Rpm)
if should_version.is_a?(RPM_VERSION_RANGE::Eq)
return super
end
rescue Puppet::Util::Package::Version::Range::ValidationFailure, Puppet::Util::Package::Version::Rpm::ValidationFailure
Puppet.debug("Cannot parse #{should} as a RPM version range")
return super
end
begin
is_version = Puppet::Util::Package::Version::Rpm.parse(is)
should_version.include?(is_version)
rescue Puppet::Util::Package::Version::Rpm::ValidationFailure
Puppet.debug("Cannot parse #{is} as a RPM version")
end
end
end
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez