Hello,

Below is a patch to the 0.25.1 rc1 /lib/puppet/type.rb file with the code
for an "unless" metaparameter.

Unfortunately, I haven't had time (or the resources) to test it yet.

Regards,
-Roy

--- a/lib/puppet/type.rb        2009-09-29 17:21:42.000000000 -0600
+++ b/lib/puppet/type.rb        2009-09-30 10:21:14.000000000 -0600
@@ -1259,6 +1259,44 @@
         end
     end

+    newmetaparam(:unless) do
+        desc "If this parameter is set in the package type, 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
+
+
     class RelationshipMetaparam < Puppet::Parameter
         class << self
             attr_accessor :direction, :events, :callback, :subclasses
@@ -1726,6 +1764,116 @@
     end

     ###############################
+    # All of the unless code.
+
+    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
+
+    ###############################
     # All of the scheduling code.

     # Look up the schedule and set it appropriately.  This is done after

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