An additional change needs to be made for this to work -- a "path"
metaparameter also needs to be made, or the full path of the command will be
required for the command in the unless statement.

Regards,
-Roy

On Wed, Sep 30, 2009 at 10:42 AM, Roy Nielsen <[email protected]> wrote:

> 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