diff --git a/lib/puppet/provider/package/zypper.rb b/lib/puppet/provider/package/zypper.rb index ddfd34084..fc73b411d 100644 --- a/lib/puppet/provider/package/zypper.rb +++ b/lib/puppet/provider/package/zypper.rb @@ -1,90 +1,100 @@ Puppet::Type.type(:package).provide :zypper, :parent => :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 a string (e.g. '--flag'), a hash (e.g. {'--flag' => 'value'}), or an array where each element is either a string or a hash." has_feature :versionable, :install_options, :virtual_packages commands :zypper => "/usr/bin/zypper" confine :operatingsystem => [:suse, :sles, :sled, :opensuse] #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 # 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 wanted = "#{wanted}-#{should}" end #This has been tested with following zypper versions - #SLE 10.2: 0.6.104 - #SLE 11.0: 1.0.8 - #OpenSuse 10.2: 0.6.13 - #OpenSuse 11.2: 1.2.8 + #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 - options = [quiet, :install] + 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 << :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 << '--name' unless @resource.allow_virtual? || should - options += install_options if resource[:install_options] + 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 #{self.name}" ) end end # What's the latest package version available? def latest #zypper can only get a list of *all* available packages? output = zypper "list-updates" if output =~ /#{Regexp.escape @resource[:name]}\s*\|.*?\|\s*([^\s\|]+)/ return $1 else # zypper didn't find updates, pretend the current # version is the latest return @property_hash[:ensure] end end def update # zypper install can be used for update, too self.install end end diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb index 2c5fff50b..019243157 100755 --- a/spec/unit/provider/package/zypper_spec.rb +++ b/spec/unit/provider/package/zypper_spec.rb @@ -1,186 +1,197 @@ #! /usr/bin/env ruby require 'spec_helper' provider_class = Puppet::Type.type(:package).provider(:zypper) describe provider_class do before(:each) do # Create a mock resource @resource = stub 'resource' # A catch all; no parameters set @resource.stubs(:[]).returns(nil) # But set name and source @resource.stubs(:[]).with(:name).returns "mypackage" @resource.stubs(:[]).with(:ensure).returns :installed @resource.stubs(:command).with(:zypper).returns "/usr/bin/zypper" @provider = provider_class.new(@resource) end it "should have an install method" do @provider = provider_class.new @provider.should respond_to(:install) end it "should have an uninstall method" do @provider = provider_class.new @provider.should respond_to(:uninstall) end it "should have an update method" do @provider = provider_class.new @provider.should respond_to(:update) end it "should have a latest method" do @provider = provider_class.new @provider.should respond_to(:latest) end it "should have a install_options method" do @provider = provider_class.new @provider.should respond_to(:install_options) end describe "when installing with zypper version >= 1.0" do it "should use a command-line with versioned package'" do @resource.stubs(:should).with(:ensure).returns "1.2.3-4.5.6" @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "1.2.8" @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', 'mypackage-1.2.3-4.5.6') @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" @provider.install end it "should use a command-line without versioned package" do @resource.stubs(:should).with(:ensure).returns :latest @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "1.2.8" @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--name', 'mypackage') @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" @provider.install end end describe "when installing with zypper version = 0.6.104" do it "should use a command-line with versioned package'" do @resource.stubs(:should).with(:ensure).returns "1.2.3-4.5.6" @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "0.6.104" @provider.expects(:zypper).with('--terse', :install, '--auto-agree-with-licenses', '--no-confirm', 'mypackage-1.2.3-4.5.6') @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" @provider.install end it "should use a command-line without versioned package" do @resource.stubs(:should).with(:ensure).returns :latest @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "0.6.104" - @provider.expects(:zypper).with('--terse', :install, '--auto-agree-with-licenses', '--no-confirm', '--name', 'mypackage') + @provider.expects(:zypper).with('--terse', :install, '--auto-agree-with-licenses', '--no-confirm', 'mypackage') @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" @provider.install end end describe "when installing with zypper version = 0.6.13" do it "should use a command-line with versioned package'" do @resource.stubs(:should).with(:ensure).returns "1.2.3-4.5.6" @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "0.6.13" @provider.expects(:zypper).with('--terse', :install, '--no-confirm', 'mypackage-1.2.3-4.5.6') @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" @provider.install end it "should use a command-line without versioned package" do @resource.stubs(:should).with(:ensure).returns :latest @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "0.6.13" - @provider.expects(:zypper).with('--terse', :install, '--no-confirm', '--name', 'mypackage') + @provider.expects(:zypper).with('--terse', :install, '--no-confirm', 'mypackage') @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" @provider.install end end describe "when updating" do it "should call install method of instance" do @provider.expects(:install) @provider.update end end describe "when getting latest version" do it "should return a version string with valid list-updates data from SLES11sp1" do fake_data = File.read(my_fixture('zypper-list-updates-SLES11sp1.out')) @resource.stubs(:[]).with(:name).returns "at" @provider.expects(:zypper).with("list-updates").returns fake_data @provider.latest.should == "3.1.8-1069.18.2" end end - it "should install a virtual package" do - @resource.stubs(:should).with(:ensure).returns :installed - @resource.stubs(:allow_virtual?).returns true - @provider.stubs(:zypper_version).returns "0.6.13" - @provider.expects(:zypper).with('--terse', :install, '--no-confirm', 'mypackage') - @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" - @provider.install + describe "should install a virtual package" do + it "when zypper version = 0.6.13" do + @resource.stubs(:should).with(:ensure).returns :installed + @resource.stubs(:allow_virtual?).returns true + @provider.stubs(:zypper_version).returns "0.6.13" + @provider.expects(:zypper).with('--terse', :install, '--no-confirm', 'mypackage') + @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" + @provider.install + end + + it "when zypper version >= 1.0.0" do + @resource.stubs(:should).with(:ensure).returns :installed + @resource.stubs(:allow_virtual?).returns true + @provider.stubs(:zypper_version).returns "1.2.8" + @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', 'mypackage') + @provider.expects(:query).returns "mypackage 0 1.2.3 4.5.6 x86_64" + @provider.install + end end describe "when installing with zypper install options" do it "should install the package without checking keys" do @resource.stubs(:[]).with(:name).returns "php5" @resource.stubs(:[]).with(:install_options).returns ['--no-gpg-check', {'-p' => '/vagrant/files/localrepo/'}] @resource.stubs(:should).with(:ensure).returns "5.4.10-4.5.6" @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns "1.2.8" - @provider.expects(:zypper).with('--quiet', :install, - '--auto-agree-with-licenses', '--no-confirm', '--no-gpg-check', '-p=/vagrant/files/localrepo/', 'php5-5.4.10-4.5.6') + @provider.expects(:zypper).with('--quiet', '--no-gpg-check', :install, + '--auto-agree-with-licenses', '--no-confirm', '-p=/vagrant/files/localrepo/', 'php5-5.4.10-4.5.6') @provider.expects(:query).returns "php5 0 5.4.10 4.5.6 x86_64" @provider.install end it "should install package with hash install options" do @resource.stubs(:[]).with(:name).returns 'vim' @resource.stubs(:[]).with(:install_options).returns([{ '--a' => 'foo', '--b' => '"quoted bar"' }]) @resource.stubs(:should).with(:ensure).returns :present @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns '1.2.8' - @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--name', '--a=foo', '--b="quoted bar"', 'vim') + @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--a=foo', '--b="quoted bar"', '--name', 'vim') @provider.expects(:query).returns 'package vim is not installed' @provider.install end it "should install package with array install options" do @resource.stubs(:[]).with(:name).returns 'vim' @resource.stubs(:[]).with(:install_options).returns([['--a', '--b', '--c']]) @resource.stubs(:should).with(:ensure).returns :present @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns '1.2.8' - @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--name', '--a', '--b', '--c', 'vim') + @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--a', '--b', '--c', '--name', 'vim') @provider.expects(:query).returns 'package vim is not installed' @provider.install end it "should install package with string install options" do @resource.stubs(:[]).with(:name).returns 'vim' @resource.stubs(:[]).with(:install_options).returns(['--a --b --c']) @resource.stubs(:should).with(:ensure).returns :present @resource.stubs(:allow_virtual?).returns false @provider.stubs(:zypper_version).returns '1.2.8' - @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--name', '--a --b --c', 'vim') + @provider.expects(:zypper).with('--quiet', :install, '--auto-agree-with-licenses', '--no-confirm', '--a --b --c', '--name', 'vim') @provider.expects(:query).returns 'package vim is not installed' @provider.install end end end