diff --git a/.gitignore b/.gitignore index 39840db..28603dd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ mkmf.log #Intellij files *.iml *.idea + +vendor/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 7375c72..0162661 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins/community/blob/master/HOW_WE_CHANGELOG.md) ## [Unreleased] +### Added +- `check-http.rb`: Add options to set `--open-timeout` and `--read-timeout` for Net:HTTP. Additionally rescue `Net::OpenTimeout` and `Net::ReadTimeout` exception classes (@johanek) +- `check-http.rb`: exposed `--dns-timeout` for Ruby DNS Resolver. (@johanek) + +### Changed +- `check-http.rb`: switched to using rubies DNS resolver to allow catching DNS failures when Net::HTTP establishes connection. (@johanek) ## [4.0.0] - 2018-12-17 ### Breaking Changes diff --git a/bin/check-http.rb b/bin/check-http.rb index 0533c3b..b63abcb 100755 --- a/bin/check-http.rb +++ b/bin/check-http.rb @@ -59,6 +59,7 @@ require 'net/http' require 'net/https' require 'digest' +require 'resolv-replace' # # Check HTTP @@ -165,9 +166,27 @@ class CheckHttp < Sensu::Plugin::Check::CLI short: '-t SECS', long: '--timeout SECS', proc: proc(&:to_i), - description: 'Set the timeout', + description: 'Set the total execution timeout in seconds', default: 15 + option :open_timeout, + long: '--open-timeout SECS', + proc: proc(&:to_i), + description: 'Number of seconds to wait for the connection to open', + default: 15 + + option :read_timeout, + long: '--read-timeout SECS', + proc: proc(&:to_i), + description: 'Number of seconds to wait for one block to be read', + default: 15 + + option :dns_timeout, + long: '--dns-timeout SECS', + proc: proc(&:to_f), + description: 'Number of seconds to allow for DNS resolution. Accepts decimal number.', + default: 0.8 + option :redirectok, short: '-r', boolean: true, @@ -250,10 +269,20 @@ def run config[:port] ||= config[:ssl] ? 443 : 80 end + # Use Ruby DNS Resolver and set DNS resolution timeout to dns_timeout value + hosts_resolver = Resolv::Hosts.new + dns_resolver = Resolv::DNS.new + dns_resolver.timeouts = config[:dns_timeout] + Resolv::DefaultResolver.replace_resolvers([hosts_resolver, dns_resolver]) + begin Timeout.timeout(config[:timeout]) do acquire_resource end + rescue Net::OpenTimeout + critical 'Request timed out opening connection' + rescue Net::ReadTimeout + critical 'Request timed out reading data' rescue Timeout::Error critical 'Request timed out' rescue StandardError => e @@ -279,8 +308,8 @@ def acquire_resource else http = Net::HTTP.new(config[:host], config[:port]) end - http.read_timeout = config[:timeout] - http.open_timeout = config[:timeout] + http.read_timeout = config[:read_timeout] + http.open_timeout = config[:open_timeout] http.ssl_timeout = config[:timeout] http.continue_timeout = config[:timeout] http.keep_alive_timeout = config[:timeout] diff --git a/test/integration/helpers/serverspec/check-http-shared_spec.rb b/test/integration/helpers/serverspec/check-http-shared_spec.rb index 32bd93a..78ce371 100644 --- a/test/integration/helpers/serverspec/check-http-shared_spec.rb +++ b/test/integration/helpers/serverspec/check-http-shared_spec.rb @@ -6,7 +6,7 @@ gem_path = '/usr/local/bin' check_name = 'check-http.rb' check = "#{gem_path}/#{check_name}" -domain = 'localhost' +domain = '127.0.0.1' describe 'ruby environment' do it_behaves_like 'ruby checks', check @@ -40,8 +40,14 @@ describe command("#{check} --url https://#{domain}/okay") do its(:exit_status) { should eq 2 } if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.3.0') - its(:stdout) { should match(/CheckHttp CRITICAL: Request error: Failed to open TCP connection to localhost:443/) } + its(:stdout) { should match(/CheckHttp CRITICAL: Request error: Failed to open TCP connection to 127.0.0.1:443/) } else - its(:stdout) { should match(/CheckHttp CRITICAL: Request error: Cannot assign requested address - connect\(2\) for "localhost" port 443/) } + its(:stdout) { should match(/CheckHttp CRITICAL: Request error: Cannot assign requested address - connect\(2\) for "127.0.0.1" port 443/) } end end + +# DNS timeout +describe command("#{check} --url http://blackhole.webpagetest.org/okay --dns-timeout 0.00001") do + its(:exit_status) { should eq 2 } + its(:stdout) { should match(/CheckHttp CRITICAL: Request error: Failed to open TCP connection to blackhole.webpagetest.org/) } +end