[PATCH/puppet 1/1] Fixes #1223 Add Zypper support for SuSE machines

99 views
Skip to first unread message

Andrew Forgue

unread,
Nov 27, 2009, 7:02:42 PM11/27/09
to puppe...@googlegroups.com
Zypper is the replacement for `rug' from earlier SuSE releases. Zypper
is backward compatible with the rug command and supports the same
commands that rug does.

Technically all that needed to be changed is :rug => "/usr/bin/zypper".
However, I'd expect rug to eventually be removed so this just depends on
the RPM provider.

Signed-off-by: Andrew Forgue <andrew...@gmail.com>
---
lib/puppet/provider/package/zypper.rb | 52 +++++++++++++++++++++
spec/unit/provider/package/zypper.rb | 81 +++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 0 deletions(-)
create mode 100644 lib/puppet/provider/package/zypper.rb
create mode 100644 spec/unit/provider/package/zypper.rb

diff --git a/lib/puppet/provider/package/zypper.rb b/lib/puppet/provider/package/zypper.rb
new file mode 100644
index 0000000..3a5f49c
--- /dev/null
+++ b/lib/puppet/provider/package/zypper.rb
@@ -0,0 +1,52 @@
+Puppet::Type.type(:package).provide :zypper, :parent => :rpm do
+ desc "Support for SuSE ``zypper`` package manager. Found in SLES10sp2+ and SLES11"
+
+ has_feature :versionable
+
+ commands :zypper => "/usr/bin/zypper"
+ commands :rpm => "rpm"
+
+ confine :operatingsystem => [:suse, :sles]
+
+ # 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
+ # pass
+ else
+ # Add the package version
+ wanted += "-%s" % should
+ end
+ output = zypper "--quiet", :install, "-y", wanted
+
+ unless self.query
+ raise Puppet::ExecutionFailure.new(
+ "Could not find package %s" % 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
+ # rug didn't find updates, pretend the current
+ # version is the latest
+ return @property_hash[:ensure]
+ end
+ end
+
+ def update
+ # rug install can be used for update, too
+ self.install
+ end
+end
diff --git a/spec/unit/provider/package/zypper.rb b/spec/unit/provider/package/zypper.rb
new file mode 100644
index 0000000..a611503
--- /dev/null
+++ b/spec/unit/provider/package/zypper.rb
@@ -0,0 +1,81 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../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 a latest 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
+
+ describe "when installing" do
+ it "should use a command-line with versioned package'" do
+ @resource.stubs(:should).with(:ensure).returns "1.2.3-4.5.6"
+ @provider.expects(:zypper).with('--quiet', :install, '-y', '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
+ @provider.expects(:zypper).with('--quiet', :install, '-y', '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" do
+
+ fake_data = "Loading repository data...
+Reading installed packages...
+S | Repository | Name | Version | Arch
+--+----------------+-----------------------+-----------------+-------
+v | SLES11-Updates | cups | 1.1.1 | x86_64
+v | SLES11-Updates | mypackage | 1.3.9h-8.20.1 | x86_64"
+
+ @provider.expects(:zypper).with("list-updates").returns fake_data
+ @provider.latest.should == "1.3.9h-8.20.1"
+ end
+ end
+
+ end
--
1.6.3.3

jb

unread,
Dec 28, 2009, 3:26:33 PM12/28/09
to Puppet Developers
install options to zypper should include '-l' (aka --auto-agree-with-
licenses) else install will hang with some packages (java comes to
mind).


On Nov 27, 4:02 pm, Andrew Forgue <andrew.for...@gmail.com> wrote:
> Zypper is the replacement for `rug' from earlier SuSE releases.  Zypper
> is backward compatible with the rug command and supports the same
> commands that rug does.
>
> Technically all that needed to be changed is :rug => "/usr/bin/zypper".
> However, I'd expect rug to eventually be removed so this just depends on
> the RPM provider.
>

> Signed-off-by: Andrew Forgue <andrew.for...@gmail.com>

Peter

unread,
Feb 4, 2010, 2:45:23 AM2/4/10
to Puppet Developers
is there a possibility to integrate the function to install package-
groups (Patterns) ?

zypper install -t pattern <package-group-name>

How sure is the integration of zypper in version 0.25.5 ?

Andrew Forgue

unread,
Feb 4, 2010, 4:08:46 PM2/4/10
to Puppet Developers

Andrew Forgue

unread,
Feb 4, 2010, 4:16:50 PM2/4/10
to Puppet Developers

Interesting, I'm not sure how that would work. You can install a
pattern simply by adding the '-t pattern', but when you try to remove
it, it says 'Uninstallation of a pattern is currently not defined and
implemented.' (SLES11) And when trying to upgrade it, even when you
supply the -t pattern, it tries to upgrade the package (appears to be
yet-another-zypper-bug). Novell seems to be rife with those.

In any case, it's simple to implement for installation, but I don't
have confidence that upgrading or removing a pattern would work at
all.

Zypper in 0.25.x is non-existent until this patch (Bug #1223) is
applied, but you can take my lib/puppet/provider/package/zypper.rb
file from my branch (mentioned in a previous post) and use it as a
plugin in your environment and it should work fine with provider =>
zypper in your manifests.

Andrew

christian

unread,
Feb 26, 2010, 5:19:35 AM2/26/10
to Puppet Developers
I did some testing with your plugin on OpenSuse 11.1 and I’d like to
offer some suggestions:

1. You should consider adding the zypper option "--force-resolution"
to line 25 like:
output = zypper "--quiet", :install, "-l", "-y", "--force-
resolution" , wanted

Otherwise i ran into some problems during the installation of some
packages, e.g. replacing postifx with sendmail gave me:

Problem: postfix-2.5.5-6.8.x86_64 conflicts with sendmail provided by
sendmail-8.14.3-50.9.i586
Solution 1: deinstallation of
postfix-2.5.5-6.8.x86_64
Solution 2: do not ask to install a solvable providing
sendmail

Choose from above solutions by number or cancel [1/2/C]: c

As you can see zypper chose to cancel the installation, but I actually
wanted to install that package so I added the „--force-resolution“
option to your code and zypper chose solution 1.

2. I don’t know if it’s a general puppet problem, false configuration
or caused by your plugin…If a client receives the plugin for the first
time, everything works just fine. But if I change anything in my
manifests and a puppet-client runs again I always get this error:
„err: Could not run Puppet configuration client: Invalid package
provider 'zypper' at /etc/puppet/modules/webserver/manifests/
webserver.pp:8“

In order to get the client working again, I have to add some random
characters to the zypper.rb, so the puppet-master thinks that there
were some changes to the plugin and updates the file on the client.

Christian

Andrew Forgue

unread,
Mar 1, 2010, 4:17:56 PM3/1/10
to Puppet Developers

On Feb 26, 5:19 am, christian <christ...@cust.in> wrote:
> I did some testing with your plugin on OpenSuse 11.1 and I’d like to
> offer some suggestions:
>
> 1. You should consider adding the zypper option "--force-resolution"
> to line 25 like:
> output = zypper "--quiet", :install, "-l", "-y", "--force-
> resolution" , wanted
>
> Otherwise i ran into some problems during the installation of some
> packages, e.g. replacing postifx with sendmail gave me:
>
> Problem: postfix-2.5.5-6.8.x86_64 conflicts with sendmail provided by
> sendmail-8.14.3-50.9.i586
>  Solution 1: deinstallation of
> postfix-2.5.5-6.8.x86_64
>  Solution 2: do not ask to install a solvable providing
> sendmail
>
> Choose from above solutions by number or cancel [1/2/C]: c
>
> As you can see zypper chose to cancel the installation, but I actually
> wanted to install that package so I added the „--force-resolution“
> option to your code and zypper chose solution 1.

Interesting -- perhaps the better solution would be to do a

package { "postfix": ensure => absent, before => Package["sendmail"] }
package { "sendmail": ensure => present }

At least then you know what puppet will do. I have no issue adding --
force-resolution, I just don't know if it would cause any issues with
uninstalling packages that may conflict -- for instance:

package { ["postfix", "sendmail"]: ensure =>latest }

Would cause issues with --force-resolution and I'm not sure how puppet
*should* handle that. I think someone on the core team should provide
input.

> 2. I don’t know if it’s a general puppet problem, false configuration
> or caused by your plugin…If a client receives the plugin for the first
> time, everything works just fine. But if I change anything in my
> manifests and a puppet-client runs again I always get this error:
> „err: Could not run Puppet configuration client: Invalid package
> provider 'zypper' at /etc/puppet/modules/webserver/manifests/
> webserver.pp:8“

I don't see this behavior. What I am doing is putting it in modules/
plugins/lib/puppet/provider/package/zypper.rb and having pluginsync =
true in my client's puppetd.conf and making sure modulepath is set
properly.

> In order to get the client working again, I have to add some random
> characters to the zypper.rb, so the puppet-master thinks that there
> were some changes to the plugin and updates the file on the client.

Yeah that's definitely strange to me. Can you try installing a
package with specific version? (I.e. ensure => "2.1.0") or
something... ) I've seen an issue where it will say package not found,
however if you cut and paste the exact line, it somehow finds it. Can
you reproduce it?

Thanks,
Andrew

christian

unread,
Mar 2, 2010, 3:28:30 AM3/2/10
to Puppet Developers
I was able to solve problem 2 earlier, but the mailinglist obviously
didn't accept my mail somehow...
It was false configuration on my side ;) I got a hint on my problem
from this discussion: http://groups.google.com/group/puppet-dev/browse_thread/thread/a5f810f31f31e35

I placed the plugin under /etc/puppet/modules/custom/lib/puppet/
provider/zypper.rb....where it should have been under /etc/puppet/
modules/custom/lib/puppet/provider/package/zypper.rb. The
documentation is a bit unclear at this point...maybe there should be a
list with possible provider types and their respective directories.


> Interesting -- perhaps the better solution would be to do a
>
> package { "postfix": ensure => absent, before => Package["sendmail"] }
> package { "sendmail": ensure => present }

Well, I tried that and got following error:

puppetd[2579]: (//allgemein::sendmail/Package[postfix]/ensure) change
from 2.5.5-6.8 to absent failed: Execution of '/bin/rpm -e
postfix-2.5.5-6.8.x86_64' returned 1: error: Failed
dependencies: smtp_daemon is needed by (installed)
cron-4.1-194.32.x86_64 smtp_daemon is needed by (installed)
mailx-12.2-141.9.x86_64

As far as I can see puppet tries to uninstall a package by using rpm
and fails...
I tried uninstalling postfix manually with "zypper rm postfix" and it
worked. So maybe you could add the "rm -y" option of zypper? :)
I would contribute the code on my own...but I have absolutely no clue
about ruby.

christian

Jesse A Wolfe

unread,
Mar 24, 2010, 5:17:20 PM3/24/10
to puppe...@googlegroups.com
I'd like to recommend this patch to go into the upcoming 0.25.5 release.
It looks like a typo has crept into your github branch, though:
+    commands :rug => "/usr/bin/zypper"
And the code below is calling "zypper" as a method - I suspect that doesn't work (and it doesn't match your old mailing-list patch, either)
It's unfortunate that the way we use mocks in provider specs can hide this sort of error.

~Jesse

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To post to this group, send email to puppe...@googlegroups.com.
To unsubscribe from this group, send email to puppet-dev+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.


Reply all
Reply to author
Forward
0 new messages