diff --git a/lib/puppet/provider/package/yum.rb b/lib/puppet/provider/package/yum.rb old mode 100755 new mode 100644 index c66c46c7e..f072779b9 --- a/lib/puppet/provider/package/yum.rb +++ b/lib/puppet/provider/package/yum.rb @@ -1,107 +1,106 @@ require 'puppet/util/package' Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do desc "Support via `yum`." has_feature :versionable commands :yum => "yum", :rpm => "rpm", :python => "python" YUMHELPER = File::join(File::dirname(__FILE__), "yumhelper.py") attr_accessor :latest_info if command('rpm') confine :true => begin rpm('--version') rescue Puppet::ExecutionFailure false else true end end defaultfor :operatingsystem => [:fedora, :centos, :redhat] def self.prefetch(packages) raise Puppet::Error, "The yum provider can only be used as root" if Process.euid != 0 super return unless packages.detect { |name, package| package.should(:ensure) == :latest } # collect our 'latest' info updates = {} python(YUMHELPER).each_line do |l| l.chomp! next if l.empty? if l[0,4] == "_pkg" hash = nevra_to_hash(l[5..-1]) [hash[:name], "#{hash[:name]}.#{hash[:arch]}"].each do |n| updates[n] ||= [] updates[n] << hash end end end # Add our 'latest' info to the providers. packages.each do |name, package| if info = updates[package[:name]] package.provider.latest_info = info[0] end end end def install should = @resource.should(:ensure) self.debug "Ensuring => #{should}" wanted = @resource[:name] operation = :install - # XXX: We don't actually deal with epochs here. case should when true, false, Symbol # pass should = nil else # Add the package version wanted += "-#{should}" is = self.query if is && Puppet::Util::Package.versioncmp(should, is[:ensure]) < 0 self.debug "Downgrading package #{@resource[:name]} from version #{is[:ensure]} to #{should}" operation = :downgrade end end output = yum "-d", "0", "-e", "0", "-y", operation, wanted is = self.query raise Puppet::Error, "Could not find package #{self.name}" unless is # FIXME: Should we raise an exception even if should == :latest # and yum updated us to a version other than @param_hash[:ensure] ? raise Puppet::Error, "Failed to update to version #{should}, got version #{is[:ensure]} instead" if should && should != is[:ensure] end # What's the latest package version available? def latest upd = latest_info unless upd.nil? # FIXME: there could be more than one update for a package # because of multiarch - return "#{upd[:version]}-#{upd[:release]}" + return "#{upd[:epoch]}:#{upd[:version]}-#{upd[:release]}" else # Yum didn't find updates, pretend the current # version is the latest raise Puppet::DevError, "Tried to get latest on a missing package" if properties[:ensure] == :absent return properties[:ensure] end end def update # Install in yum can be used for update, too self.install end def purge yum "-y", :erase, @resource[:name] end end diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb index 601c24009..5148ac079 100755 --- a/spec/unit/provider/package/yum_spec.rb +++ b/spec/unit/provider/package/yum_spec.rb @@ -1,66 +1,110 @@ #!/usr/bin/env rspec require 'spec_helper' provider = Puppet::Type.type(:package).provider(:yum) describe provider do before do # Create a mock resource @resource = stub 'resource' @resource.stubs(:[]).with(:name).returns 'mypackage' @provider = provider.new(@resource) @provider.stubs(:resource).returns @resource @provider.stubs(:yum).returns 'yum' @provider.stubs(:rpm).returns 'rpm' @provider.stubs(:get).with(:name).returns 'mypackage' @provider.stubs(:get).with(:version).returns '1' @provider.stubs(:get).with(:release).returns '1' @provider.stubs(:get).with(:arch).returns 'i386' end # provider should repond to the following methods [:install, :latest, :update, :purge].each do |method| it "should have a(n) #{method}" do @provider.should respond_to(method) end end describe 'when installing' do it 'should call yum install for :installed' do @resource.stubs(:should).with(:ensure).returns :installed @provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage') @provider.install end + it 'should use :install to update' do @provider.expects(:install) @provider.update end + it 'should be able to set version' do @resource.stubs(:should).with(:ensure).returns '1.2' @provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage-1.2') @provider.stubs(:query).returns :ensure => '1.2' @provider.install end + it 'should be able to downgrade' do @resource.stubs(:should).with(:ensure).returns '1.0' @provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :downgrade, 'mypackage-1.0') @provider.stubs(:query).returns(:ensure => '1.2').then.returns(:ensure => '1.0') @provider.install end end describe 'when uninstalling' do it 'should use erase to purge' do @provider.expects(:yum).with('-y', :erase, 'mypackage') @provider.purge end + it 'should use rpm to uninstall' do @provider.expects(:rpm).with('-e', 'mypackage-1-1.i386') @provider.uninstall end end it 'should be versionable' do provider.should be_versionable end -end + describe '#latest' do + describe 'when latest_info is nil' do + before :each do + @provider.stubs(:latest_info).returns(nil) + end + + it 'raises if ensure is absent and latest_info is nil' do + @provider.stubs(:properties).returns({:ensure => :absent}) + + expect { @provider.latest }.to raise_error( + Puppet::DevError, + 'Tried to get latest on a missing package' + ) + end + + it 'returns the ensure value if the package is not already installed' do + @provider.stubs(:properties).returns({:ensure => '3.4.5'}) + + @provider.latest.should == '3.4.5' + end + end + + describe 'when latest_info is populated' do + before :each do + @provider.stubs(:latest_info).returns({ + :name => 'mypackage', + :epoch => '1', + :version => '2.3.4', + :release => '5', + :arch => 'i686', + :provider => :yum, + :ensure => '2.3.4-5' + }) + end + + it 'includes the epoch in the version string' do + @provider.latest.should == '1:2.3.4-5' + end + end + end +end