pacman.diff

Paul Boyd, 03/09/2011 02:26 am

Download (9.1 kB)

b/lib/puppet/provider/package/pacman.rb
1
require 'puppet/provider/package'
2

  
3
Puppet::Type.type(:package).provide :pacman, :parent => Puppet::Provider::Package do
4
  desc "Support for the Package Manager Utility (pacman) used in Archlinux."
5

  
6
  commands :pacman => "/usr/bin/pacman"
7
  defaultfor :operatingsystem => :archlinux
8
  confine    :operatingsystem => :archlinux
9
  has_feature :upgradeable
10

  
11
  # Install a package using 'pacman'.
12
  # Installs quietly, without confirmation or progressbar, updates package
13
  # list from servers defined in pacman.conf.
14
  def install
15
    pacman "--noconfirm", "--noprogressbar", "-Sy", @resource[:name]
16

  
17
    unless self.query
18
      raise Puppet::ExecutionFailure.new("Could not find package %s" % self.name)
19
    end
20
  end
21

  
22
  def self.listcmd
23
    [command(:pacman), " -Q"]
24
  end
25

  
26
  # Fetch the list of packages currently installed on the system.
27
  def self.instances
28
    packages = []
29
    begin
30
      execpipe(listcmd()) do |process|
31
        # pacman -Q output is 'packagename version-rel'
32
        regex = %r{^(\S+)\s(\S+)}
33
        fields = [:name, :ensure]
34
        hash = {}
35

  
36
        process.each { |line|
37
          if match = regex.match(line)
38
            fields.zip(match.captures) { |field,value|
39
              hash[field] = value
40
            }
41

  
42
            name = hash[:name]
43
            hash[:provider] = self.name
44

  
45
            packages << new(hash)
46
            hash = {}
47
          else
48
            warning("Failed to match line %s" % line)
49
          end
50
        }
51
      end
52
    rescue Puppet::ExecutionFailure
53
      return nil
54
    end
55
    packages
56
  end
57

  
58
  # Because Archlinux is a rolling release based distro, installing a package
59
  # should always result in the newest release.
60
  def update
61
    # Install in pacman can be used for update, too
62
    self.install
63
  end
64

  
65
  def latest
66
    pacman "-Sy"
67
    output = pacman "-Sp", "--print-format", "%v", @resource[:name]
68
    output.chomp
69
  end
70

  
71
  # Querys the pacman master list for information about the package.
72
  def query
73
    begin
74
      output = pacman("-Qi", @resource[:name])
75

  
76
      if output =~ /Version.*:\s(.+)/
77
        return { :ensure => $1 }
78
      end
79
    rescue Puppet::ExecutionFailure
80
      return {
81
        :ensure => :purged,
82
        :status => 'missing',
83
        :name => @resource[:name],
84
        :error => 'ok',
85
      }
86
    end
87
    nil
88
  end
89

  
90
  # Removes a package from the system.
91
  def uninstall
92
    pacman "--noconfirm", "--noprogressbar", "-R", @resource[:name]
93
  end
94
end
b/spec/unit/provider/package/pacman_spec.rb
1
#!/usr/bin/env ruby
2

  
3
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
4

  
5
provider = Puppet::Type.type(:package).provider(:pacman)
6

  
7
describe provider do
8
  before do
9
    @resource = stub 'resource'
10
    @resource.stubs(:[]).returns("package")
11
    @resource.stubs(:name).returns("name")
12
    @provider = provider.new(@resource)
13
  end
14

  
15
  describe "when installing" do
16
    before do
17
      @provider.stubs(:query).returns({
18
        :ensure => '1.0'
19
      })
20
    end
21

  
22
    it "should call pacman" do
23
      provider.
24
        expects(:execute).
25
        at_least_once.
26
        with { |args|
27
          args[0] == "/usr/bin/pacman"
28
        }.
29
        returns ""
30

  
31
      @provider.install
32
    end
33

  
34
    it "should be quiet" do
35
      provider.
36
        expects(:execute).
37
        with { |args|
38
          args[1,2] == ["--noconfirm", "--noprogressbar"]
39
        }.
40
        returns("")
41

  
42
      @provider.install
43
    end
44

  
45
    it "should install the right package" do
46
      provider.
47
        expects(:execute).
48
        with { |args|
49
          args[3,4] == ["-Sy", @resource[0]]
50
        }.
51
        returns("")
52

  
53
      @provider.install
54
    end
55

  
56
    it "should raise an ExecutionFailure if the installation failed" do
57
      provider.stubs(:execute).returns("")
58
      @provider.expects(:query).returns(nil)
59

  
60
      lambda { @provider.install }.should raise_exception(Puppet::ExecutionFailure)
61
    end
62
  end
63

  
64
  describe "when updating" do
65
    it "should call install" do
66
      @provider.expects(:install).returns("install return value")
67
      @provider.update.should == "install return value"
68
    end
69
  end
70

  
71
  describe "when uninstalling" do
72
    it "should call pacman" do
73
      provider.
74
        expects(:execute).
75
        with { |args|
76
          args[0] == "/usr/bin/pacman"
77
        }.
78
        returns ""
79

  
80
      @provider.uninstall
81
    end
82

  
83
    it "should be quiet" do
84
      provider.
85
        expects(:execute).
86
        with { |args|
87
          args[1,2] == ["--noconfirm", "--noprogressbar"]
88
        }.
89
        returns("")
90

  
91
      @provider.uninstall
92
    end
93

  
94
    it "should remove the right package" do
95
      provider.
96
        expects(:execute).
97
        with { |args|
98
          args[3,4] == ["-R", @resource[0]]
99
        }.
100
        returns("")
101

  
102
      @provider.uninstall
103
    end
104
  end
105

  
106
  describe "when querying" do
107
    it "should query pacman" do
108
      provider.
109
        expects(:execute).
110
        with(["/usr/bin/pacman", "-Qi", @resource[0]])
111
      @provider.query
112
    end
113

  
114
    it "should return the version" do
115
      query_output = <<EOF
116
Name           : package
117
Version        : 1.01.3-2
118
URL            : http://www.archlinux.org/pacman/
119
Licenses       : GPL
120
Groups         : base
121
Provides       : None
122
Depends On     : bash  libarchive>=2.7.1  libfetch>=2.25  pacman-mirrorlist
123
Optional Deps  : fakeroot: for makepkg usage as normal user
124
                 curl: for rankmirrors usage
125
Required By    : None
126
Conflicts With : None
127
Replaces       : None
128
Installed Size : 2352.00 K
129
Packager       : Dan McGee <dan@archlinux.org>
130
Architecture   : i686
131
Build Date     : Sat 22 Jan 2011 03:56:41 PM EST
132
Install Date   : Thu 27 Jan 2011 06:45:49 AM EST
133
Install Reason : Explicitly installed
134
Install Script : Yes
135
Description    : A library-based package manager with dependency support
136
EOF
137

  
138
      provider.expects(:execute).returns(query_output)
139
      @provider.query.should == {:ensure => "1.01.3-2"}
140
    end
141

  
142
    it "should return a nil if the package isn't found" do
143
      provider.expects(:execute).returns("")
144
      @provider.query.should be_nil
145
    end
146

  
147
    it "should return a hash indicating that the package is missing on error" do
148
      provider.expects(:execute).raises(Puppet::ExecutionFailure.new("ERROR!"))
149
      @provider.query.should == {
150
        :ensure => :purged,
151
        :status => 'missing',
152
        :name => @resource[0],
153
        :error => 'ok',
154
      }
155
    end
156
  end
157

  
158
  describe "when fetching a package list" do
159
    it "should query pacman" do
160
      provider.expects(:execpipe).with(["/usr/bin/pacman", ' -Q'])
161
      provider.instances
162
    end
163

  
164
    it "should return installed packages with their versions" do
165
      provider.expects(:execpipe).yields("package1 1.23-4\npackage2 2.00\n")
166
      packages = provider.instances
167

  
168
      packages.length.should == 2
169

  
170
      packages[0].properties.should == {
171
        :provider => :pacman,
172
        :ensure => '1.23-4',
173
        :name => 'package1'
174
      }
175

  
176
      packages[1].properties.should == {
177
        :provider => :pacman,
178
        :ensure => '2.00',
179
        :name => 'package2'
180
      }
181
    end
182

  
183
    it "should return nil on error" do
184
      provider.expects(:execpipe).raises(Puppet::ExecutionFailure.new("ERROR!"))
185
      provider.instances.should be_nil
186
    end
187

  
188
    it "should warn on invalid input" do
189
      provider.expects(:execpipe).yields("blah")
190
      provider.expects(:warning).with("Failed to match line blah")
191
      provider.instances.should == []
192
    end
193
  end
194

  
195
  describe "when determining the latest version" do
196
    it "should refresh package list" do
197
      refreshed = states('refreshed').starts_as('unrefreshed')
198
      provider.
199
        expects(:execute).
200
        when(refreshed.is('unrefreshed')).
201
        with(['/usr/bin/pacman', '-Sy']).
202
        then(refreshed.is('refreshed'))
203

  
204
      provider.
205
        stubs(:execute).
206
        when(refreshed.is('refreshed')).
207
        returns("")
208

  
209
      @provider.latest
210
    end
211

  
212
    it "should get query pacman for the latest version" do
213
      refreshed = states('refreshed').starts_as('unrefreshed')
214
      provider.
215
        stubs(:execute).
216
        when(refreshed.is('unrefreshed')).
217
        then(refreshed.is('refreshed'))
218

  
219
      provider.
220
        expects(:execute).
221
        when(refreshed.is('refreshed')).
222
        with(['/usr/bin/pacman', '-Sp', '--print-format', '%v', @resource[0]]).
223
        returns("")
224

  
225
      @provider.latest
226
    end
227

  
228
    it "should return the version number from pacman" do
229
      provider.
230
        expects(:execute).
231
        at_least_once().
232
        returns("1.00.2-3\n")
233

  
234
      @provider.latest.should == "1.00.2-3"
235
    end
236
  end
237
end