diff options
-rw-r--r-- | lib/puppet/provider/package/pkg.rb | 114 | ||||
-rw-r--r-- | spec/unit/provider/package/pkg.rb | 63 |
2 files changed, 177 insertions, 0 deletions
diff --git a/lib/puppet/provider/package/pkg.rb b/lib/puppet/provider/package/pkg.rb new file mode 100644 index 000000000..978042d42 --- /dev/null +++ b/lib/puppet/provider/package/pkg.rb @@ -0,0 +1,114 @@ +require 'puppet/provider/package' + +Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package do + desc "OpenSolaris image packaging system. See pkg(5) for more information" + + commands :pkg => "/usr/bin/pkg" + + confine :operatingsystem => :solaris + + #defaultfor [:operatingsystem => :solaris, :kernelrelease => "5.11"] + + def self.instances + packages = [] + + cmd = "#{command(:pkg)} list -H" + execpipe(cmd) do |process| + hash = {} + + # now turn each returned line into a package object + process.each { |line| + if hash = parse_line(line) + packages << new(hash) + end + } + end + + packages + end + + REGEX = %r{^(\S+)\s+(\S+)\s+(\S+)\s+} + FIELDS = [:name, :version, :status] + + def self.parse_line(line) + hash = {} + if match = REGEX.match(line) + + FIELDS.zip(match.captures) { |field,value| + hash[field] = value + } + + hash[:provider] = self.name + hash[:error] = "ok" + + if hash[:status] == "installed" + hash[:ensure] = :present + else + hash[:ensure] = :absent + end + else + Puppet.warning "Failed to match 'pkg list' line %s" % line.inspect + return nil + end + + return hash + end + + # return the version of the package + # TODO deal with multiple publishers + def latest + version = nil + pkg(:list, "-Ha", @resource[:name]).split("\n").each do |line| + v = line.split[2] + case v + when "known" + return v + when "installed" + version = v + else + Puppet.warn "unknown package state for %s: %s" % + [@resource[:name], v] + end + end + version + end + + # install the package + def install + pkg :install, @resource[:name] + end + + # uninstall the package + def uninstall + pkg :uninstall, '-r', @resource[:name] + end + + # update the package to the latest version available + def update + self.install + end + + # list a specific package + def query + begin + output = pkg(:list, "-H", @resource[:name]) + rescue Puppet::ExecutionFailure + # pkg returns 1 if the package is not found. + return {:ensure => :absent, :status => 'missing', + :name => @resource[:name], :error => 'ok'} + end + + hash = self.class.parse_line(output) || + {:ensure => :absent, :status => 'missing', + :name => @resource[:name], :error => 'ok'} + + if hash[:error] != "ok" + raise Puppet::Error.new( + "Package %s, version %s is in error state: %s" % + [hash[:name], hash[:version], hash[:error]]) + end + + return hash + end + +end diff --git a/spec/unit/provider/package/pkg.rb b/spec/unit/provider/package/pkg.rb new file mode 100644 index 000000000..6001c7b7a --- /dev/null +++ b/spec/unit/provider/package/pkg.rb @@ -0,0 +1,63 @@ +#!/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(:pkg) + +describe provider do + before do + @resource = stub 'resource', :[] => "dummy" + @provider = provider.new(@resource) + + @fakeresult = "install ok installed dummy 1.0\n" + end + + def self.it_should_respond_to(*actions) + actions.each do |action| + it "should respond to :#{action}" do + @provider.should respond_to(action) + end + end + end + + it_should_respond_to :install, :uninstall, :update, :query, :latest + + it "should be versionable" do + provider.should_not be_versionable + end + + it "should use :install to update" do + @provider.expects(:install) + @provider.update + end + + it "should parse a line correctly" do + result = provider.parse_line("dummy 1.0@1.0-1.0 installed ----") + result.should == {:name => "dummy", :version => "1.0@1.0-1.0", + :ensure => :present, :status => "installed", + :provider => :pkg, :error => "ok"} + end + + it "should fail to parse an incorrect line" do + result = provider.parse_line("foo") + result.should be_nil + end + + it "should list package correctly" do + @provider.expects(:pkg).with(:list, "-H", "dummy").returns "1" + @provider.query.should == {:status=>"missing", :ensure=>:absent, + :name=>"dummy", :error=>"ok"} + end + + it "should fail to list a package when it can't parse the output line" do + @provider.expects(:pkg).with(:list, "-H", "dummy").returns "failed" + @provider.query.should == {} + #== {:status=>"missing", :ensure=>:absent, :name=>"dummy", :error=>"ok"} + end + + it "should fail to list a missing package" do + @provider.expects(:pkg).with(:list, "-H", "dummy").returns "dummy 1.0@1.0-1.0 installed ----" + lambda { @provider.query }.should raise_error(Puppet::Error) + #== {:status=>"missing", :ensure=>:absent, :name=>"dummy", :error=>"ok"} + end +end |