Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 33 additions & 17 deletions lib/god/conditions/http_response_code.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
require 'net/http'
require 'net/https'

module God
module Conditions

# Condition Symbol :http_response_code
# Type: Poll
#
#
# Trigger based on the response from an HTTP request.
#
# Paramaters
Expand All @@ -23,6 +24,7 @@ module Conditions
# +times+ is the number of times after which to trigger (default 1)
# e.g. 3 (times in a row) or [3, 5] (three out of fives times)
# +timeout+ is the time to wait for a connection (default 60.seconds)
# +ssl+ should the connection use ssl (default false)
#
# Examples
#
Expand Down Expand Up @@ -68,52 +70,66 @@ class HttpResponseCode < PollCondition
:times, # e.g. 3 or [3, 5]
:host, # e.g. www.example.com
:port, # e.g. 8080
:ssl, # e.g. true or false
:ca_file, # e.g /path/to/pem_file for ssl verification (checkout http://curl.haxx.se/ca/cacert.pem)
:timeout, # e.g. 60.seconds
:path, # e.g. '/'
:headers # e.g. {'Host' => 'myvirtual.mydomain.com'}

def initialize
super
self.port = 80
self.path = '/'
self.headers = {}
self.times = [1, 1]
self.timeout = 60.seconds
self.ssl = false
self.ca_file = nil
end

def prepare
self.code_is = Array(self.code_is).map { |x| x.to_i } if self.code_is
self.code_is_not = Array(self.code_is_not).map { |x| x.to_i } if self.code_is_not

if self.times.kind_of?(Integer)
self.times = [self.times, self.times]
end

@timeline = Timeline.new(self.times[1])
@history = Timeline.new(self.times[1])
end

def reset
@timeline.clear
@history.clear
end

def valid?
valid = true
valid &= complain("Attribute 'host' must be specified", self) if self.host.nil?
valid &= complain("One (and only one) of attributes 'code_is' and 'code_is_not' must be specified", self) if
(self.code_is.nil? && self.code_is_not.nil?) || (self.code_is && self.code_is_not)
valid
end

def test
response = nil

connection = Net::HTTP.new(self.host, self.port)
connection.use_ssl = self.port == 443 ? true : self.ssl
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE if connection.use_ssl

Net::HTTP.start(self.host, self.port) do |http|
if connection.use_ssl && self.ca_file
pem = File.read(self.ca_file)
connection.ca_file = self.ca_file
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
end

connection.start do |http|
http.read_timeout = self.timeout
response = http.get(self.path, self.headers)
end

actual_response_code = response.code.to_i
if self.code_is && self.code_is.include?(actual_response_code)
pass(actual_response_code)
Expand All @@ -135,9 +151,9 @@ def test
rescue Exception => failure
self.code_is ? fail(failure.class.name) : pass(failure.class.name)
end

private

def pass(code)
@timeline << true
if @timeline.select { |x| x }.size >= self.times.first
Expand All @@ -148,21 +164,21 @@ def pass(code)
false
end
end

def fail(code)
@timeline << false
self.info = "http response nominal #{history(code, false)}"
false
end

def history(code, passed)
entry = code.to_s.dup
entry = '*' + entry if passed
@history << entry
'[' + @history.join(", ") + ']'
end

end

end
end
18 changes: 9 additions & 9 deletions test/test_conditions_http_response_code.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_valid_should_return_false_if_no_host_set

def test_test_should_return_false_if_code_is_is_set_to_200_but_response_is_500
c = valid_condition
Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 500)))
Net::HTTP.any_instance.expects(:start).yields(mock(:read_timeout= => nil, :get => mock(:code => 500)))
assert_equal false, c.test
end

Expand All @@ -49,13 +49,13 @@ def test_test_should_return_false_if_code_is_not_is_set_to_200_and_response_is_2
cc.code_is = nil
cc.code_is_not = [200]
end
Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200)))
Net::HTTP.any_instance.expects(:start).yields(mock(:read_timeout= => nil, :get => mock(:code => 200)))
assert_equal false, c.test
end

def test_test_should_return_true_if_code_is_is_set_to_200_and_response_is_200
c = valid_condition
Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200)))
Net::HTTP.any_instance.expects(:start).yields(mock(:read_timeout= => nil, :get => mock(:code => 200)))
assert_equal true, c.test
end

Expand All @@ -64,13 +64,13 @@ def test_test_should_return_false_if_code_is_not_is_set_to_200_but_response_is_5
cc.code_is = nil
cc.code_is_not = [200]
end
Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 500)))
Net::HTTP.any_instance.expects(:start).yields(mock(:read_timeout= => nil, :get => mock(:code => 500)))
assert_equal true, c.test
end

def test_test_should_return_false_if_code_is_is_set_to_200_but_response_times_out
c = valid_condition
Net::HTTP.expects(:start).raises(Timeout::Error, '')
Net::HTTP.any_instance.expects(:start).raises(Timeout::Error, '')
assert_equal false, c.test
end

Expand All @@ -79,13 +79,13 @@ def test_test_should_return_true_if_code_is_not_is_set_to_200_and_response_times
cc.code_is = nil
cc.code_is_not = [200]
end
Net::HTTP.expects(:start).raises(Timeout::Error, '')
Net::HTTP.any_instance.expects(:start).raises(Timeout::Error, '')
assert_equal true, c.test
end

def test_test_should_return_false_if_code_is_is_set_to_200_but_cant_connect
c = valid_condition
Net::HTTP.expects(:start).raises(Errno::ECONNREFUSED, '')
Net::HTTP.any_instance.expects(:start).raises(Errno::ECONNREFUSED, '')
assert_equal false, c.test
end

Expand All @@ -94,15 +94,15 @@ def test_test_should_return_true_if_code_is_not_is_set_to_200_and_cant_connect
cc.code_is = nil
cc.code_is_not = [200]
end
Net::HTTP.expects(:start).raises(Errno::ECONNREFUSED, '')
Net::HTTP.any_instance.expects(:start).raises(Errno::ECONNREFUSED, '')
assert_equal true, c.test
end

def test_test_should_return_true_if_code_is_is_set_to_200_and_response_is_200_twice_for_times_two_of_two
c = valid_condition do |cc|
cc.times = [2, 2]
end
Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200))).times(2)
Net::HTTP.any_instance.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200))).times(2)
assert_equal false, c.test
assert_equal true, c.test
end
Expand Down