diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-01-04 23:51:41 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-01-04 23:51:41 +0000 |
commit | 42c13e27535c868d6b70ba806554197ce3b833dc (patch) | |
tree | a747ef1d76d7b67f31464f4d200482404662b48d | |
parent | 6e10004e67b6d6f964c65edc27e8d2b350ba0175 (diff) | |
download | puppet-42c13e27535c868d6b70ba806554197ce3b833dc.tar.gz puppet-42c13e27535c868d6b70ba806554197ce3b833dc.tar.xz puppet-42c13e27535c868d6b70ba806554197ce3b833dc.zip |
Adding a timeout to execs. This is not really a sufficient solution, since it needs to be added throughout the system, but this is a good start. The default timeout is 5 minutes.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2047 980ebf18-57e1-0310-9a29-db15c13687c0
-rwxr-xr-x | lib/puppet/type/exec.rb | 45 | ||||
-rwxr-xr-x | test/types/exec.rb | 13 |
2 files changed, 54 insertions, 4 deletions
diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb index 44903f40c..1be9c030c 100755 --- a/lib/puppet/type/exec.rb +++ b/lib/puppet/type/exec.rb @@ -1,6 +1,7 @@ module Puppet newtype(:exec) do include Puppet::Util::Execution + require 'timeout' @doc = "Executes external commands. It is critical that all commands executed using this mechanism can be run multiple times without @@ -134,7 +135,11 @@ module Puppet event = :executed_command - @output, status = @parent.run(self.parent[:command]) + begin + @output, status = @parent.run(self.parent[:command]) + rescue Timeout::Error + self.fail "Command exceeded timeout" % value.inspect + end loglevel = @parent[:loglevel] if status.exitstatus.to_s != self.should.to_s @@ -281,6 +286,26 @@ module Puppet end end end + + newparam(:timeout) do + desc "The maximum time the command should take. If the command takes + longer than the timeout, the command is considered to have failed + and will be stopped. Use any negative number to disable the timeout." + + munge do |value| + value = value.shift if value.is_a?(Array) + if value.is_a?(String) + unless value =~ /^[-\d.]+$/ + raise ArgumentError, "The timeout must be a number." + end + Float(value) + else + value + end + end + + defaultto 300 + end newcheck(:refreshonly) do desc "The command should only be run as a @@ -377,7 +402,12 @@ module Puppet # Return true if the command does not return 0. def check(value) - output, status = @parent.run(value, true) + begin + output, status = @parent.run(value, true) + rescue Timeout::Error + err "Check %s exceeded timeout" % value.inspect + return false + end return status.exitstatus != 0 end @@ -408,7 +438,12 @@ module Puppet # Return true if the command returns 0. def check(value) - output, status = @parent.run(value, true) + begin + output, status = @parent.run(value, true) + rescue Timeout::Error + err "Check %s exceeded timeout" % value.inspect + return false + end return status.exitstatus == 0 end @@ -542,7 +577,9 @@ module Puppet end withenv env do - output, status = Puppet::SUIDManager.run_and_capture([command], self[:user], self[:group]) + Timeout::timeout(self[:timeout]) do + output, status = Puppet::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 diff --git a/test/types/exec.rb b/test/types/exec.rb index fd304e7d1..0c5ee0258 100755 --- a/test/types/exec.rb +++ b/test/types/exec.rb @@ -603,6 +603,19 @@ and stuff" } assert_equal("A B\n", output) end + + def test_timeout + exec = Puppet::Type.type(:exec).create(:command => "sleep 1", :path => ENV["PATH"], :timeout => "0.2") + time = Time.now + + assert_raise(Timeout::Error) { + exec.run("sleep 1") + } + Puppet.info "%s seconds, vs a timeout of %s" % [Time.now.to_f - time.to_f, exec[:timeout]] + + + assert_apply(exec) + end end # $Id$ |