Hello,

A co-worker of mine wanted to see if we could submit a patch to
include the unless statement from the exec type in the package type -
with the primary purpose of checking if a specific process is running
before installing a package.  Something like:

package { \"puppet.pkg.dmg\":
   path => "/usr/bin:/usr/sbin:/bin",
   unless => "ps -acx | grep puppet 2>/dev/null"
}

People might also want to use this "unless" test for other executed
commands as well.

Regards,
-Roy

PS: A possible patch for the 0.25 code below:

--- a/lib/puppet/type/package.rb        2009-09-29 14:17:09.000000000
-0600
+++ b/lib/puppet/type/package.rb        2009-09-29 14:17:23.000000000
-0600
@@ -277,6 +277,43 @@
            newvalues(:true, :false)
        end

+        newcheck(:unless) do
+            desc "If this parameter is set, then this ``package``
will install unless
+                the command returns 0 .  For example::
+                   +                    package { \"puppet.pkg.dmg\":
+                        path => \"/usr/bin:/usr/sbin:/bin\",
+                        unless => \"ps -acx | grep puppet 2>/dev/null
\"
+                    }
+
+                This would install the puppet.pkg.dmg package unless
a process
+                containing the ``puppet`` string is found in the
process list.
+
+                Note that this command follows the same rules as the
exec command,
+                which is to say that it must be fully qualified if
the path is not set.
+                "
+
+            validate do |cmds|
+                cmds = [cmds] unless cmds.is_a? Array
+
+                cmds.each do |cmd|
+                    @resource.validatecmd(cmd)
+                end
+            end
+
+            # Return true if the command does not return 0.
+            def check(value)
+                begin
+                    output, status = @resource.run(value, true)
+                rescue Timeout::Error
+                    err "Check %s exceeded timeout" % value.inspect
+                    return false
+                end
+
+                return status.exitstatus != 0
+            end
+        end
+
        autorequire(:file) do
            autos = []
            [:responsefile, :adminfile].each { |param|
@@ -315,6 +352,114 @@
                props
            end
        end
+
+        def checkexe(cmd)
+            if cmd =~ /^\//
+                exe = cmd.split(/ /)[0]
+                unless FileTest.exists?(exe)
+                    raise ArgumentError, "Could not find executable
%s" % exe
+                end
+                unless FileTest.executable?(exe)
+                    raise ArgumentError,
+                        "%s is not executable" % exe
+                end
+            elsif path = self[:path]
+                exe = cmd.split(/ /)[0]
+                withenv :PATH => self[:path].join(":") do
+                    path = %{which #{exe}}.chomp
+                    if path == ""
+                        raise ArgumentError,
+                            "Could not find command '%s'" % exe
+                    end
+                end
+            else
+                raise ArgumentError,
+                    "%s is somehow not qualified with no search path"
%
+                        self[:command]
+            end
+        end
+
+        def run(command, check = false)
+            output = nil
+            status = nil
+
+            dir = nil
+
+            checkexe(command)
+
+            if dir = self[:cwd]
+                unless File.directory?(dir)
+                    if check
+                        dir = nil
+                    else
+                        self.fail "Working directory '%s' does not
exist" % dir
+                    end
+                end
+            end
+
+            dir ||= Dir.pwd
+
+            if check
+                debug "Executing check '#{command}'"
+            else
+                debug "Executing '#{command}'"
+            end
+            begin
+                # Do our chdir
+                Dir.chdir(dir) do
+                    environment = {}
+
+                    if self[:path]
+                        environment[:PATH] = self[:path].join(":")
+                    end
+
+                    if envlist = self[:environment]
+                        envlist = [envlist] unless envlist.is_a?
Array
+                        envlist.each do |setting|
+                            if setting =~ /^(\w+)=((.|\n)+)$/
+                                name = $1
+                                value = $2
+                                if environment.include? name
+                                    warning(
+                                    "Overriding environment setting
'%s' with '%s'" %
+                                        [name, value]
+                                    )
+                                end
+                                environment[name] = value
+                            else
+                                warning "Cannot understand
environment setting %s" % setting.inspect
+                            end
+                        end
+                    end
+
+                    withenv environment do
+                        Timeout::timeout(self[:timeout]) do
+                            output, status =
Puppet::Util::SUIDManager.run_and_capture(
+                                [command], self[:user], self[:group]
+                            )
+                        end
+                        # The shell returns 127 if the command is
missing.
+                        if status.exitstatus == 127
+                            raise ArgumentError, output
+                        end
+                    end
+                end
+            rescue Errno::ENOENT => detail
+                self.fail detail.to_s
+            end
+
+            return output, status
+        end
+
+        def validatecmd(cmd)
+            # if we're not fully qualified, require a path
+            if cmd !~ /^\//
+                if self[:path].nil?
+                    self.fail "'%s' is both unqualifed and specified
no search path" % cmd
+                end
+            end
+        end
+
    end # Puppet::Type.type(:package)
end

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