File puppet-zypper-lu.patch of Package rubygem-puppet

From 358cabca903e019b863d654a74711581bc14b331 Mon Sep 17 00:00:00 2001
From: Theo Chatzimichos <tampakrap@gmail.com>
Date: Thu, 5 Feb 2015 22:06:08 +0100
Subject: [PATCH] (PUP-3968) Cache the `zypper list-updates` output

The zypper provider calls `zypper list-updates` in order to get a list of the
packages that have newer versions. Then it checks if the resource name matches
any of the items in the list, and then applies the newer version. The problem
with the above though is that it runs list-updates for every single package
instance, while it should be run only once, as it provides all the packages
that have newer versions available.

This commit caches the list-updates output and puts its contents in a hash, so
that each package resource will query this instead of zypper directly

Signed-off-by: Adrien Thebo <adrienthebo@somethigsinistral.net>
---
 lib/puppet/provider/package/zypper.rb     | 34 +++++++++++++++++++++++--------
 spec/unit/provider/package/zypper_spec.rb |  2 +-
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/lib/puppet/provider/package/zypper.rb b/lib/puppet/provider/package/zypper.rb
index 2fe6cdf..c74358c 100644
--- a/lib/puppet/provider/package/zypper.rb
+++ b/lib/puppet/provider/package/zypper.rb
@@ -12,6 +12,30 @@
 
   confine    :operatingsystem => [:suse, :sles, :sled, :opensuse]
 
+  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
@@ -72,16 +96,10 @@ def install
 
   # 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
+    return self.class.latest_package_version(@resource[:name]) ||
       # zypper didn't find updates, pretend the current
       # version is the latest
-      return @property_hash[:ensure]
-    end
+      @property_hash[:ensure]
   end
 
   def update
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index 3265858..73389fe 100755
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -119,7 +119,7 @@
       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
+      described_class.expects(:zypper).with("list-updates").returns fake_data
       @provider.latest.should == "3.1.8-1069.18.2"
     end
   end
openSUSE Build Service is sponsored by