I think we talked through this before and I +1'd it then, so...

On Mar 26, 2010, at 3:10 PM, Nigel Kersten wrote:


Signed-off-by: Nigel Kersten <[email protected]>
---
lib/puppet/provider/package/dpkg.rb |   31 +++++++++++++++++++-
lib/puppet/type/package.rb          |   12 +++++++-
spec/unit/provider/package/dpkg.rb | 55 ++++++++++++++++++++++++++ +++++++-
3 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/lib/puppet/provider/package/dpkg.rb b/lib/puppet/ provider/package/dpkg.rb
index 06050ce..fda9e02 100755
--- a/lib/puppet/provider/package/dpkg.rb
+++ b/lib/puppet/provider/package/dpkg.rb
@@ -5,6 +5,8 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package and not ``apt``, you must specify the source of any packages you want
        to manage."

+    has_feature :holdable
+
    commands :dpkg => "/usr/bin/dpkg"
    commands :dpkg_deb => "/usr/bin/dpkg-deb"
    commands :dpkgquery => "/usr/bin/dpkg-query"
@@ -47,9 +49,12 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package

            if hash[:status] == 'not-installed'
                hash[:ensure] = :purged
-            elsif hash[:status] != "installed"
+ elsif ['config-files', 'half-installed', 'unpacked', 'half-configured'].include?(hash[:status])
                hash[:ensure] = :absent
            end
+            if hash[:desired] == 'hold'
+                hash[:ensure] = :held
+            end
        else
Puppet.warning "Failed to match dpkg-query line %s" % line.inspect
            return nil
@@ -65,6 +70,9 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package

        args = []

+        # We always unhold when installing to remove any prior hold.
+        self.unhold
+
        if @resource[:configfiles] == :keep
            args << '--force-confold'
        else
@@ -127,4 +135,25 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
    def purge
        dpkg "--purge", @resource[:name]
    end
+
+    def hold
+        self.install
+        begin
+            Tempfile.open('puppet_dpkg_set_selection') { |tmpfile|
+                tmpfile.write("#...@resource[:name]} hold\n")
+                tmpfile.flush
+ execute([:dpkg, "--set-selections"], :stdinfile => tmpfile.path.to_s)
+            }
+        end
+    end
+
+    def unhold
+        begin
+            Tempfile.open('puppet_dpkg_set_selection') { |tmpfile|
+                tmpfile.write("#...@resource[:name]} install\n")
+                tmpfile.flush
+ execute([:dpkg, "--set-selections"], :stdinfile => tmpfile.path.to_s)
+            }
+        end
+    end
end
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb
index bb3db28..99285c5 100644
--- a/lib/puppet/type/package.rb
+++ b/lib/puppet/type/package.rb
@@ -35,6 +35,12 @@ module Puppet
package database for installed version(s), and can select which out of a set of available versions of a package to
                install if asked."
+ feature :holdable, "The provider is capable of placing packages on hold + such that they are not automatically upgraded as a result of + other package dependencies unless explicit action is taken by + a user or another package. Held is considered a superset of
+                installed.",
+            :methods => [:hold]

        ensurable do
            desc "What state the package should be in.
@@ -60,6 +66,10 @@ module Puppet
                provider.purge
            end

+ newvalue(:held, :event => :package_held, :required_features => :holdable) do
+                provider.hold
+            end
+
            # Alias the 'present' value.
            aliasvalue(:installed, :present)

@@ -111,7 +121,7 @@ module Puppet
                @should.each { |should|
                    case should
                    when :present
- return true unless [:absent, :purged].include?(is) + return true unless [:absent, :purged, :held].include?(is)
                    when :latest
                        # Short-circuit packages that are not present
                        return false if is == :absent or is == :purged
diff --git a/spec/unit/provider/package/dpkg.rb b/spec/unit/provider/ package/dpkg.rb
index 0c5c9b5..7e3e8df 100755
--- a/spec/unit/provider/package/dpkg.rb
+++ b/spec/unit/provider/package/dpkg.rb
@@ -88,11 +88,30 @@ describe provider do
            @provider.query[:ensure].should == :purged
        end

- it "should consider the package absent if its status is neither 'installed' nor 'not-installed'" do - @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "foo") + it "should consider the package absent if it is marked 'config-files'" do + @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "config-files")
+            @provider.query[:ensure].should == :absent
+        end
+
+ it "should consider the package absent if it is marked 'half-installed'" do + @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "half-installed")
+            @provider.query[:ensure].should == :absent
+        end
+
+ it "should consider the package absent if it is marked 'unpacked'" do + @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "unpacked")
+            @provider.query[:ensure].should == :absent
+        end

+ it "should consider the package absent if it is marked 'half-configured'" do + @provider.expects(:dpkgquery).returns @fakeresult.sub("installed", "half-configured")
            @provider.query[:ensure].should == :absent
        end
+
+ it "should consider the package held if its state is 'hold'" do + @provider.expects(:dpkgquery).returns @fakeresult.sub("install", "hold")
+            @provider.query[:ensure].should == :held
+        end
    end

    it "should be able to install" do
@@ -130,6 +149,38 @@ describe provider do

            @provider.install
        end
+
+        it "should ensure any hold is removed" do
+            @provider.expects(:unhold).once
+            @provider.expects(:dpkg)
+            @provider.install
+        end
+    end
+
+    describe "when holding or unholding" do
+        before do
+ @tempfile = stub 'tempfile', :print => nil, :close => nil, :flush => nil, :path => "/other/file"
+          @tempfile.stubs(:write)
+          Tempfile.stubs(:new).returns @tempfile
+        end
+
+        it "should install first if holding" do
+            @provider.stubs(:execute)
+            @provider.expects(:install).once
+            @provider.hold
+        end
+
+        it "should execute dpkg --set-selections when holding" do
+            @provider.stubs(:install)
+ @provider.expects(:execute).with([:dpkg, '--set- selections'], {:stdinfile => @tempfile.path}).once
+            @provider.hold
+        end
+
+        it "should execute dpkg --set-selections when unholding" do
+            @provider.stubs(:install)
+ @provider.expects(:execute).with([:dpkg, '--set- selections'], {:stdinfile => @tempfile.path}).once
+            @provider.hold
+        end
    end

    it "should use :install to update" do
--
1.7.0.3

--
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 .



--
Always behave like a duck - keep calm and unruffled on the surface but
paddle like the devil underneath. -- Jacob Braude
---------------------------------------------------------------------
Luke Kanies  -|-   http://puppetlabs.com   -|-   +1(615)594-8199

--
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