From: Paul Boyd <[email protected]>

Adds support for use Archlinux's pacman package manager in Puppet.

Originally written by Miah Johnson, with bug fixes from Thomas Hatch and
myself.

Signed-off-by: Paul Boyd <[email protected]>
---
Local-branch: feature/master/1853
 lib/puppet/provider/package/pacman.rb     |   94 ++++++++++++
 spec/unit/provider/package/pacman_spec.rb |  237 +++++++++++++++++++++++++++++
 2 files changed, 331 insertions(+), 0 deletions(-)
 create mode 100644 lib/puppet/provider/package/pacman.rb
 create mode 100644 spec/unit/provider/package/pacman_spec.rb

diff --git a/lib/puppet/provider/package/pacman.rb 
b/lib/puppet/provider/package/pacman.rb
new file mode 100644
index 0000000..6eb7dbe
--- /dev/null
+++ b/lib/puppet/provider/package/pacman.rb
@@ -0,0 +1,94 @@
+require 'puppet/provider/package'
+
+Puppet::Type.type(:package).provide :pacman, :parent => 
Puppet::Provider::Package do
+  desc "Support for the Package Manager Utility (pacman) used in Archlinux."
+
+  commands :pacman => "/usr/bin/pacman"
+  defaultfor :operatingsystem => :archlinux
+  confine    :operatingsystem => :archlinux
+  has_feature :upgradeable
+
+  # Install a package using 'pacman'.
+  # Installs quietly, without confirmation or progressbar, updates package
+  # list from servers defined in pacman.conf.
+  def install
+    pacman "--noconfirm", "--noprogressbar", "-Sy", @resource[:name]
+
+    unless self.query
+      raise Puppet::ExecutionFailure.new("Could not find package %s" % 
self.name)
+    end
+  end
+
+  def self.listcmd
+    [command(:pacman), " -Q"]
+  end
+
+  # Fetch the list of packages currently installed on the system.
+  def self.instances
+    packages = []
+    begin
+      execpipe(listcmd()) do |process|
+        # pacman -Q output is 'packagename version-rel'
+        regex = %r{^(\S+)\s(\S+)}
+        fields = [:name, :ensure]
+        hash = {}
+
+        process.each { |line|
+          if match = regex.match(line)
+            fields.zip(match.captures) { |field,value|
+              hash[field] = value
+            }
+
+            name = hash[:name]
+            hash[:provider] = self.name
+
+            packages << new(hash)
+            hash = {}
+          else
+            warning("Failed to match line %s" % line)
+          end
+        }
+      end
+    rescue Puppet::ExecutionFailure
+      return nil
+    end
+    packages
+  end
+
+  # Because Archlinux is a rolling release based distro, installing a package
+  # should always result in the newest release.
+  def update
+    # Install in pacman can be used for update, too
+    self.install
+  end
+
+  def latest
+    pacman "-Sy"
+    output = pacman "-Sp", "--print-format", "%v", @resource[:name]
+    output.chomp
+  end
+
+  # Querys the pacman master list for information about the package.
+  def query
+    begin
+      output = pacman("-Qi", @resource[:name])
+
+      if output =~ /Version.*:\s(.+)/
+        return { :ensure => $1 }
+      end
+    rescue Puppet::ExecutionFailure
+      return {
+        :ensure => :purged,
+        :status => 'missing',
+        :name => @resource[:name],
+        :error => 'ok',
+      }
+    end
+    nil
+  end
+
+  # Removes a package from the system.
+  def uninstall
+    pacman "--noconfirm", "--noprogressbar", "-R", @resource[:name]
+  end
+end
diff --git a/spec/unit/provider/package/pacman_spec.rb 
b/spec/unit/provider/package/pacman_spec.rb
new file mode 100644
index 0000000..499ccca
--- /dev/null
+++ b/spec/unit/provider/package/pacman_spec.rb
@@ -0,0 +1,237 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? 
require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+provider = Puppet::Type.type(:package).provider(:pacman)
+
+describe provider do
+  before do
+    @resource = stub 'resource'
+    @resource.stubs(:[]).returns("package")
+    @resource.stubs(:name).returns("name")
+    @provider = provider.new(@resource)
+  end
+
+  describe "when installing" do
+    before do
+      @provider.stubs(:query).returns({
+        :ensure => '1.0'
+      })
+    end
+
+    it "should call pacman" do
+      provider.
+        expects(:execute).
+        at_least_once.
+        with { |args|
+          args[0] == "/usr/bin/pacman"
+        }.
+        returns ""
+
+      @provider.install
+    end
+
+    it "should be quiet" do
+      provider.
+        expects(:execute).
+        with { |args|
+          args[1,2] == ["--noconfirm", "--noprogressbar"]
+        }.
+        returns("")
+
+      @provider.install
+    end
+
+    it "should install the right package" do
+      provider.
+        expects(:execute).
+        with { |args|
+          args[3,4] == ["-Sy", @resource[0]]
+        }.
+        returns("")
+
+      @provider.install
+    end
+
+    it "should raise an ExecutionFailure if the installation failed" do
+      provider.stubs(:execute).returns("")
+      @provider.expects(:query).returns(nil)
+
+      lambda { @provider.install }.should 
raise_exception(Puppet::ExecutionFailure)
+    end
+  end
+
+  describe "when updating" do
+    it "should call install" do
+      @provider.expects(:install).returns("install return value")
+      @provider.update.should == "install return value"
+    end
+  end
+
+  describe "when uninstalling" do
+    it "should call pacman" do
+      provider.
+        expects(:execute).
+        with { |args|
+          args[0] == "/usr/bin/pacman"
+        }.
+        returns ""
+
+      @provider.uninstall
+    end
+
+    it "should be quiet" do
+      provider.
+        expects(:execute).
+        with { |args|
+          args[1,2] == ["--noconfirm", "--noprogressbar"]
+        }.
+        returns("")
+
+      @provider.uninstall
+    end
+
+    it "should remove the right package" do
+      provider.
+        expects(:execute).
+        with { |args|
+          args[3,4] == ["-R", @resource[0]]
+        }.
+        returns("")
+
+      @provider.uninstall
+    end
+  end
+
+  describe "when querying" do
+    it "should query pacman" do
+      provider.
+        expects(:execute).
+        with(["/usr/bin/pacman", "-Qi", @resource[0]])
+      @provider.query
+    end
+
+    it "should return the version" do
+      query_output = <<EOF
+Name           : package
+Version        : 1.01.3-2
+URL            : http://www.archlinux.org/pacman/
+Licenses       : GPL
+Groups         : base
+Provides       : None
+Depends On     : bash  libarchive>=2.7.1  libfetch>=2.25  pacman-mirrorlist
+Optional Deps  : fakeroot: for makepkg usage as normal user
+                 curl: for rankmirrors usage
+Required By    : None
+Conflicts With : None
+Replaces       : None
+Installed Size : 2352.00 K
+Packager       : Dan McGee <[email protected]>
+Architecture   : i686
+Build Date     : Sat 22 Jan 2011 03:56:41 PM EST
+Install Date   : Thu 27 Jan 2011 06:45:49 AM EST
+Install Reason : Explicitly installed
+Install Script : Yes
+Description    : A library-based package manager with dependency support
+EOF
+
+      provider.expects(:execute).returns(query_output)
+      @provider.query.should == {:ensure => "1.01.3-2"}
+    end
+
+    it "should return a nil if the package isn't found" do
+      provider.expects(:execute).returns("")
+      @provider.query.should be_nil
+    end
+
+    it "should return a hash indicating that the package is missing on error" 
do
+      provider.expects(:execute).raises(Puppet::ExecutionFailure.new("ERROR!"))
+      @provider.query.should == {
+        :ensure => :purged,
+        :status => 'missing',
+        :name => @resource[0],
+        :error => 'ok',
+      }
+    end
+  end
+
+  describe "when fetching a package list" do
+    it "should query pacman" do
+      provider.expects(:execpipe).with(["/usr/bin/pacman", ' -Q'])
+      provider.instances
+    end
+
+    it "should return installed packages with their versions" do
+      provider.expects(:execpipe).yields("package1 1.23-4\npackage2 2.00\n")
+      packages = provider.instances
+
+      packages.length.should == 2
+
+      packages[0].properties.should == {
+        :provider => :pacman,
+        :ensure => '1.23-4',
+        :name => 'package1'
+      }
+
+      packages[1].properties.should == {
+        :provider => :pacman,
+        :ensure => '2.00',
+        :name => 'package2'
+      }
+    end
+
+    it "should return nil on error" do
+      
provider.expects(:execpipe).raises(Puppet::ExecutionFailure.new("ERROR!"))
+      provider.instances.should be_nil
+    end
+
+    it "should warn on invalid input" do
+      provider.expects(:execpipe).yields("blah")
+      provider.expects(:warning).with("Failed to match line blah")
+      provider.instances.should == []
+    end
+  end
+
+  describe "when determining the latest version" do
+    it "should refresh package list" do
+      refreshed = states('refreshed').starts_as('unrefreshed')
+      provider.
+        expects(:execute).
+        when(refreshed.is('unrefreshed')).
+        with(['/usr/bin/pacman', '-Sy']).
+        then(refreshed.is('refreshed'))
+
+      provider.
+        stubs(:execute).
+        when(refreshed.is('refreshed')).
+        returns("")
+
+      @provider.latest
+    end
+
+    it "should get query pacman for the latest version" do
+      refreshed = states('refreshed').starts_as('unrefreshed')
+      provider.
+        stubs(:execute).
+        when(refreshed.is('unrefreshed')).
+        then(refreshed.is('refreshed'))
+
+      provider.
+        expects(:execute).
+        when(refreshed.is('refreshed')).
+        with(['/usr/bin/pacman', '-Sp', '--print-format', '%v', @resource[0]]).
+        returns("")
+
+      @provider.latest
+    end
+
+    it "should return the version number from pacman" do
+      provider.
+        expects(:execute).
+        at_least_once().
+        returns("1.00.2-3\n")
+
+      @provider.latest.should == "1.00.2-3"
+    end
+  end
+end
-- 
1.7.4.1

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

Reply via email to