Populate instances with both the real package name ("CSWsvn") and the alias name ("subversion") from separate "pkgutil -a" call.
Fixed cases where pkgutil noise was parsed as aliased package names and also breaking "not in catalog" detection. Updated pkgutil_spec test to show various edge cases. Signed-off-by: Dominic Cleal <dcl...@redhat.com> --- lib/puppet/provider/package/pkgutil.rb | 86 ++++++++++++++++++++------- spec/unit/provider/package/pkgutil_spec.rb | 60 +++++++++++++++++-- 2 files changed, 117 insertions(+), 29 deletions(-) diff --git a/lib/puppet/provider/package/pkgutil.rb b/lib/puppet/provider/package/pkgutil.rb index 3a23796..350cacc 100755 --- a/lib/puppet/provider/package/pkgutil.rb +++ b/lib/puppet/provider/package/pkgutil.rb @@ -23,10 +23,45 @@ Puppet::Type.type(:package).provide :pkgutil, :parent => :sun, :source => :sun d end def self.instances(hash = {}) - pkglist(hash).collect do |bhash| - bhash.delete(:avail) - new(bhash) + # Use the available pkg list (-a) to work out aliases + aliases = {} + availlist.each do |pkg| + aliases[pkg[:name]] = pkg[:alias] end + + # The -c pkglist lists installed packages + pkginsts = [] + pkglist(hash).each do |pkg| + pkg.delete(:avail) + pkginsts << new(pkg) + + # Create a second instance with the alias if it's different + pkgalias = aliases[pkg[:name]] + if pkgalias and pkg[:name] != pkgalias + apkg = Hash.new(pkg) + apkg[:name] = pkgalias + pkginsts << new(apkg) + end + end + + pkginsts + end + + # Turns a pkgutil -a listing into hashes with the common alias, full + # package name and available version + def self.availlist + output = pkguti ["-a"] + + list = output.split("\n").collect do |line| + next if line =~ /^common\s+package/ # header of package list + next if noise?(line) + + if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ + { :alias => $1, :name => $2, :avail => $3 } + else + Puppet.warning "Cannot match %s" % line + end + end.reject { |h| h.nil? } end # Turn our pkgutil -c listing into a bunch of hashes. @@ -41,36 +76,45 @@ Puppet::Type.type(:package).provide :pkgutil, :parent => :sun, :source => :sun d command << hash[:justme] end - output = pkguti command + output = pkguti(command).split("\n") - list = output.split("\n").collect do |line| - next if line =~ /^#/ + if output[-1] == "Not in catalog" + Puppet.warning "Package not in pkgutil catalog: %s" % hash[:justme] + return nil + end + + list = output.collect do |line| next if line =~ /installed\s+catalog/ # header of package list - next if line =~ /^Checking integrity / # use_gpg - next if line =~ /^gpg: / # gpg verification - next if line =~ /^=+> / # catalog fetch - next if line =~ /\d+:\d+:\d+ URL:/ # wget without -q + next if noise?(line) - pkgsplit(line, hash[:justme]) + pkgsplit(line) end.reject { |h| h.nil? } if hash[:justme] - # Ensure we picked up the package line, not any pkgutil noise. - list.reject! { |h| h[:name] != hash[:justme] } - return list[-1] + # Single queries may have been for an alias so return the name requested + if list.any? + list[-1][:name] = hash[:justme] + return list[-1] + end else list.reject! { |h| h[:ensure] == :absent } return list end + end + # Identify common types of pkgutil noise as it downloads catalogs etc + def self.noise?(line) + true if line =~ /^#/ + true if line =~ /^Checking integrity / # use_gpg + true if line =~ /^gpg: / # gpg verification + true if line =~ /^=+> / # catalog fetch + true if line =~ /\d+:\d+:\d+ URL:/ # wget without -q + false end # Split the different lines into hashes. - def self.pkgsplit(line, justme) - if line == "Not in catalog" - Puppet.warning "Package not in pkgutil catalog: %s" % justme - return nil - elsif line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ + def self.pkgsplit(line) + if line =~ /\s*(\S+)\s+(\S+)\s+(.*)/ hash = {} hash[:name] = $1 hash[:ensure] = if $2 == "notinst" @@ -80,10 +124,6 @@ Puppet::Type.type(:package).provide :pkgutil, :parent => :sun, :source => :sun d end hash[:avail] = $3 - if justme - hash[:name] = justme - end - if hash[:avail] =~ /^SAME\s*$/ hash[:avail] = hash[:ensure] end diff --git a/spec/unit/provider/package/pkgutil_spec.rb b/spec/unit/provider/package/pkgutil_spec.rb index 01142b4..4f0e0cc 100755 --- a/spec/unit/provider/package/pkgutil_spec.rb +++ b/spec/unit/provider/package/pkgutil_spec.rb @@ -67,16 +67,15 @@ TESTpkg 1.4.5,REV=2007.11.18 SAME" end it "should handle a non-existent package" do - fake_data = "noisy output here" + fake_data = "noisy output here +Not in catalog" provider.expects(:pkguti).with(['-c', '--single', 'TESTpkg']).returns fake_data @provider.latest.should == nil end it "should warn on unknown pkgutil noise" do - provider.expects(:pkguti).returns("testingnoise") - Puppet.expects(:warning) - provider.expects(:new).never - provider.instances.should == [] + provider.expects(:pkguti).with(['-c', '--single', 'TESTpkg']).returns("testingnoise") + @provider.latest.should == nil end it "should ignore pkgutil noise/headers to find TESTpkg" do @@ -92,6 +91,14 @@ TESTpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" provider.expects(:pkguti).with(['-c', '--single', 'TESTpkg']).returns fake_data @provider.latest.should == "1.4.5,REV=2007.11.20" end + + it "should find REALpkg via an alias (TESTpkg)" do + fake_data = " +noisy output here +REALpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" + provider.expects(:pkguti).with(['-c', '--single', 'TESTpkg']).returns fake_data + @provider.query[:name].should == "TESTpkg" + end end describe "when querying current version" do @@ -108,14 +115,26 @@ TESTpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" end it "should handle a non-existent package" do - fake_data = "noisy output here" + fake_data = "noisy output here +Not in catalog" provider.expects(:pkguti).with(['-c', '--single', 'TESTpkg']).returns fake_data @provider.query[:ensure].should == :absent end end describe "when querying current instances" do + it "should warn on unknown pkgutil noise" do + provider.expects(:pkguti).with(['-a']).returns("testingnoise") + provider.expects(:pkguti).with(['-c']).returns("testingnoise") + Puppet.expects(:warning).times(2) + provider.expects(:new).never + provider.instances.should == [] + end + it "should return TESTpkg's version string" do + fake_data = "TESTpkg TESTpkg 1.4.5,REV=2007.11.20" + provider.expects(:pkguti).with(['-a']).returns fake_data + fake_data = "TESTpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" provider.expects(:pkguti).with(['-c']).returns fake_data @@ -123,6 +142,35 @@ TESTpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" provider.expects(:new).with(:ensure => "1.4.5,REV=2007.11.18", :name => "TESTpkg", :provider => :pkgutil).returns testpkg provider.instances.should == [testpkg] end + + it "should also return both TESTpkg and mypkg alias instances" do + fake_data = "mypkg TESTpkg 1.4.5,REV=2007.11.20" + provider.expects(:pkguti).with(['-a']).returns fake_data + + fake_data = "TESTpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" + provider.expects(:pkguti).with(['-c']).returns fake_data + + testpkg = mock 'pkg1' + provider.expects(:new).with(:ensure => "1.4.5,REV=2007.11.18", :name => "TESTpkg", :provider => :pkgutil).returns testpkg + + aliaspkg = mock 'pkg2' + provider.expects(:new).with(:ensure => "1.4.5,REV=2007.11.18", :name => "mypkg", :provider => :pkgutil).returns aliaspkg + + provider.instances.should == [testpkg,aliaspkg] + end + + it "shouldn't mind noise in the -a output" do + fake_data = "noisy output here" + provider.expects(:pkguti).with(['-a']).returns fake_data + + fake_data = "TESTpkg 1.4.5,REV=2007.11.18 1.4.5,REV=2007.11.20" + provider.expects(:pkguti).with(['-c']).returns fake_data + + testpkg = mock 'pkg1' + provider.expects(:new).with(:ensure => "1.4.5,REV=2007.11.18", :name => "TESTpkg", :provider => :pkgutil).returns testpkg + + provider.instances.should == [testpkg] + end end end -- 1.7.4 -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to puppet-dev@googlegroups.com. To unsubscribe from this group, send email to puppet-dev+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.