This repository has been archived by the owner on Jan 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Kris Kelly <kkelly@pivotallabs.com>
- Loading branch information
Showing
5 changed files
with
148 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,4 @@ source "https://rubygems.org" | |
gem "sinatra" | ||
gem "rspec" | ||
gem "rest-client" | ||
gem "vcr" | ||
gem "webmock", "1.15" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
require "rest-client" | ||
|
||
module Decider | ||
class Pingdom | ||
PINGDOM_API_ENDPOINT = "https://api.pingdom.com/api/2.0" | ||
UPDATE_INTERVAL = 30 | ||
|
||
attr_reader :reason | ||
|
||
def initialize app_key, username, password, hostname | ||
@app_key = app_key | ||
@username = username | ||
@password = password | ||
@hostname = hostname | ||
@can_i_bump = false | ||
@reason = "No data yet" | ||
|
||
message = "Invalid argument, cannot be nil" | ||
[@app_key, @username, @password, @hostname].each {|param| raise ArgumentError, message if param.nil?} | ||
end | ||
|
||
def can_i_bump? | ||
verify_pingdom | ||
@can_i_bump | ||
end | ||
|
||
private | ||
|
||
def verify_pingdom | ||
checks = pingdom_checks | ||
return set_can_i_bump(false, "No data from pingdom") if checks.empty? | ||
failed_checks = checks.select { |c| c["status"] != "up" && c["status"] != "paused" } | ||
|
||
unless failed_checks.empty? | ||
return set_can_i_bump( | ||
false, | ||
"Pingdom failed to connect to #{failed_checks.map {|c| c["hostname"]}.join(", ")}") | ||
end | ||
|
||
return set_can_i_bump(true, nil) | ||
rescue => e | ||
return set_can_i_bump(false, "Can't connect to pingdom: #{e.message}") | ||
end | ||
|
||
def set_can_i_bump(value, reason) | ||
@can_i_bump = value | ||
@reason = reason | ||
end | ||
|
||
def pingdom_checks | ||
response = RestClient::Request.new( | ||
:method => :get, | ||
:url => "#{Pingdom::PINGDOM_API_ENDPOINT}/checks", | ||
:user => @username, | ||
:password => @password, | ||
:headers => { | ||
"App-Key" => @app_key | ||
} | ||
).execute | ||
filter_checks(JSON.parse(response.body)["checks"]) | ||
end | ||
|
||
def filter_checks(checks) | ||
checks.select { |c| c["hostname"] =~ /#{@hostname}/ } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
require "spec_helper" | ||
require "deciders/pingdom" | ||
|
||
describe Decider::Pingdom do | ||
describe "initialize" do | ||
context "invalid parameters" do | ||
|
||
it "any parameter is nil" do | ||
expect { Decider::Pingdom.new(nil, 'foo', 'bar', 'foo') }.to raise_error(ArgumentError) | ||
expect { Decider::Pingdom.new('foo', nil, 'bar', 'foo') }.to raise_error(ArgumentError) | ||
expect { Decider::Pingdom.new('foo', 'bar', nil, 'foo') }.to raise_error(ArgumentError) | ||
expect { Decider::Pingdom.new('foo', 'bar', 'baz', nil) }.to raise_error(ArgumentError) | ||
end | ||
end | ||
end | ||
|
||
describe "#can_i_bump?" do | ||
subject(:decider) { Decider::Pingdom.new('foobar', 'fake_user', 'fake_password', 'target_hostname') } | ||
|
||
context "when pingdom is unreachable" do | ||
before do | ||
stub_request(:get, "https://fake_user:fake_password@api.pingdom.com/api/2.0/checks").to_return(:status => 500) | ||
end | ||
|
||
it "says NO" do | ||
expect(decider.can_i_bump?).to be_false | ||
expect(decider.reason).to match /500 Internal Server Error/ | ||
end | ||
end | ||
|
||
context "when pingdom does not return any checks" do | ||
before do | ||
stub_request(:get, "https://fake_user:fake_password@api.pingdom.com/api/2.0/checks"). | ||
to_return(:body => JSON.dump({"checks" => []})) | ||
end | ||
|
||
it "says NO" do | ||
expect(decider.can_i_bump?).to be_false | ||
expect(decider.reason).to match /No data/ | ||
end | ||
end | ||
|
||
context "when some matching checks are DOWN" do | ||
before do | ||
stub_request(:get, "https://fake_user:fake_password@api.pingdom.com/api/2.0/checks"). | ||
to_return(:body => JSON.dump( | ||
{ | ||
"checks" => [ | ||
{"id" => 123, "status" => "down", "hostname" => "a.target_hostname"}, | ||
{"id" => 456, "status" => "up", "hostname" => "b.target_hostname"}, | ||
{"id" => 789, "status" => "down", "hostname" => "c.target_hostname"} | ||
] | ||
})) | ||
end | ||
|
||
it "says NO" do | ||
expect(decider.can_i_bump?).to be_false | ||
expect(decider.reason).to match /Pingdom failed to connect to a.target_hostname, c.target_hostname/ | ||
end | ||
end | ||
|
||
context "when all matching checks are UP" do | ||
before do | ||
stub_request(:get, "https://fake_user:fake_password@api.pingdom.com/api/2.0/checks"). | ||
to_return(:body => JSON.dump( | ||
{ | ||
"checks" => [ | ||
{"id" => 123, "status" => "down", "hostname" => "a.bar"}, | ||
{"id" => 456, "status" => "up", "hostname" => "b.target_hostname"} | ||
] | ||
})) | ||
end | ||
|
||
it "ignores checks not matching the hostname" do | ||
expect(decider.can_i_bump?).to be_true | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,10 @@ | ||
require "vcr" | ||
require "webmock/rspec" | ||
require "support/can_i_bump_runner" | ||
|
||
$:.unshift(File.expand_path("../lib", __FILE__)) | ||
|
||
RSpec.configure do |rspec_config| | ||
rspec_config.include(CanIBumpRunner) | ||
end | ||
|
||
|
||
VCR.configure do |c| | ||
c.cassette_library_dir = File.expand_path("../fixtures/vcr_cassettes", __FILE__) | ||
c.hook_into :webmock | ||
c.ignore_localhost = true | ||
c.default_cassette_options = { | ||
:serialize_with => :syck, | ||
:decode_compressed_response => true | ||
} | ||
WebMock.disable_net_connect!(:allow => /127.0.0.1/) | ||
end |