flapjack 1.0.0rc2 → 1.0.0rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -3
- data/CHANGELOG.md +5 -0
- data/features/notification_rules.feature +2 -3
- data/features/rollup.feature +18 -0
- data/features/steps/events_steps.rb +8 -8
- data/features/support/env.rb +26 -30
- data/lib/flapjack/data/notification.rb +3 -1
- data/lib/flapjack/gateways/jsonapi/check_presenter.rb +6 -6
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +3 -1
- data/lib/flapjack/gateways/web.rb +8 -6
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +24 -12
- data/spec/spec_helper.rb +9 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d91c5e561fafc64a7698f898d1c02b6f00386c97
|
4
|
+
data.tar.gz: c7c4e4ba3e84c4a59ff09964fc67278c12b2fb04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6efd501448115a5a97a23df6ece95b2f53bf2b4a01d4fe268c1ae851bdb850aaa5d242497f2c5e4871f5b945076151081ae7df33b6eb15fe6e01f06d99a8cda0
|
7
|
+
data.tar.gz: d11a32ab75ad2cbcf7b9f9d432cd6f5dfd2da498b127a2c653291f55cf08b7f7eafbc9da9894510b94bbde7d9edcc5ac9ede703761c612563d5e32b2851dabad
|
data/.travis.yml
CHANGED
@@ -14,11 +14,15 @@ before_install:
|
|
14
14
|
- gem install bundler
|
15
15
|
script: bundle exec rspec spec && bundle exec cucumber features
|
16
16
|
notifications:
|
17
|
-
irc:
|
17
|
+
irc:
|
18
|
+
channels:
|
19
|
+
- 'irc.freenode.net#flapjack'
|
20
|
+
template:
|
21
|
+
- '%{message} %{repository}#%{build_number} (%{branch} - %{commit} : %{author})'
|
18
22
|
hipchat:
|
19
23
|
template:
|
20
|
-
|
21
|
-
|
24
|
+
- '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}
|
25
|
+
(<a href="%{build_url}">Details</a>/<a href="%{compare_url}">Change view</a>)'
|
22
26
|
format: html
|
23
27
|
rooms:
|
24
28
|
secure: ajMolTKDuprYJ9Fadcjb3evh80MyJSgjW4hl4OWnEHyrjQLnsO0hbAvSrKRFUzorMoi58L8XZXd01gMgRqRxMvwqfoHLv4njw8px4X9+F/hySPZj3aMAFM1HuoTmHqeP+Rl+1Ssg+Kss6N4JkgNS81s+tkRnnoHG1n/EhfH6PkE=
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
## Flapjack Changelog
|
2
2
|
|
3
|
+
# 1.0.0rc3 - 2014-07-24
|
4
|
+
- Bug: fix jsonapi methods for report checks/methods, maintenance reports, outage reports (@ali-graham)
|
5
|
+
- Bug: improve tests around notification rules and rollup, tweak rollup behaviour on recovery (@ali-graham)
|
6
|
+
- Bug: fix handling of base_url config warnings in web gateway #560 (@jessereynolds)
|
7
|
+
|
3
8
|
# 1.0.0rc2 - 2014-07-17
|
4
9
|
- Feature: jsonapi GET /checks badab0d (@ali-graham)
|
5
10
|
- Feature: Add HTTP broker, one-off event submitter, general Go support #553 (@auxesis)
|
@@ -96,7 +96,6 @@ Feature: Notification rules on a per contact basis
|
|
96
96
|
When a critical event is received
|
97
97
|
Then 3 email alerts should be queued for malak@example.com
|
98
98
|
When the time is February 1 2013 18:01
|
99
|
-
Then all alert dropping keys for user c1 should have expired
|
100
99
|
When a critical event is received
|
101
100
|
Then 3 email alerts should be queued for malak@example.com
|
102
101
|
|
@@ -210,7 +209,7 @@ Feature: Notification rules on a per contact basis
|
|
210
209
|
When 10 minutes passes
|
211
210
|
And a critical event is received
|
212
211
|
Then 1 email alert should be queued for malak@example.com
|
213
|
-
When
|
212
|
+
When 6 minutes passes
|
214
213
|
And a critical event is received
|
215
214
|
Then 2 email alerts should be queued for malak@example.com
|
216
215
|
|
@@ -226,7 +225,7 @@ Feature: Notification rules on a per contact basis
|
|
226
225
|
When 10 minutes passes
|
227
226
|
And an unknown event is received
|
228
227
|
Then 1 email alert should be queued for malak@example.com
|
229
|
-
When
|
228
|
+
When 6 minutes passes
|
230
229
|
And an unknown event is received
|
231
230
|
Then 2 email alerts should be queued for malak@example.com
|
232
231
|
|
data/features/rollup.feature
CHANGED
@@ -214,3 +214,21 @@ Feature: Rollup on a per contact, per media basis
|
|
214
214
|
Then 2 sms alerts of type problem and rollup none should be queued for +61400000001
|
215
215
|
And 3 sms alerts should be queued for +61400000001
|
216
216
|
|
217
|
+
@time
|
218
|
+
Scenario: Multiple notifications should not occur when in rollup
|
219
|
+
Given check 'ping' for entity 'foo' is in an ok state
|
220
|
+
And check 'ping' for entity 'baz' is in an ok state
|
221
|
+
When a critical event is received for check 'ping' on entity 'foo'
|
222
|
+
And a critical event is received for check 'ping' on entity 'baz'
|
223
|
+
And 1 minute passes
|
224
|
+
And a critical event is received for check 'ping' on entity 'foo'
|
225
|
+
And a critical event is received for check 'ping' on entity 'baz'
|
226
|
+
And 1 minute passes
|
227
|
+
And a critical event is received for check 'ping' on entity 'foo'
|
228
|
+
Then 1 email alert of type problem and rollup problem should be queued for malak@example.com
|
229
|
+
And 19 minutes passes
|
230
|
+
And a critical event is received for check 'ping' on entity 'baz'
|
231
|
+
Then 2 email alerts of type problem and rollup problem should be queued for malak@example.com
|
232
|
+
And 1 minute passes
|
233
|
+
And a critical event is received for check 'ping' on entity 'baz'
|
234
|
+
Then 2 email alerts of type problem and rollup problem should be queued for malak@example.com
|
@@ -395,7 +395,7 @@ Given /^user (\S+) has the following notification rules:$/ do |contact_id, rules
|
|
395
395
|
end
|
396
396
|
|
397
397
|
Then /^all alert dropping keys for user (\S+) should have expired$/ do |contact_id|
|
398
|
-
expect(@redis.keys("drop_alerts_for_contact:#{contact_id}
|
398
|
+
expect(@redis.keys("drop_alerts_for_contact:#{contact_id}:*")).to be_empty
|
399
399
|
end
|
400
400
|
|
401
401
|
Then /^(\w+) (\w+) alert(?:s)?(?: of)?(?: type (\w+))?(?: and)?(?: rollup (\w+))? should be queued for (.*)$/ do |num_queued, media, notification_type, rollup, address|
|
@@ -408,13 +408,13 @@ Then /^(\w+) (\w+) alert(?:s)?(?: of)?(?: type (\w+))?(?: and)?(?: rollup (\w+))
|
|
408
408
|
queue = Resque.peek("#{media}_notifications", 0, 30)
|
409
409
|
queued_length = queue.find_all {|n|
|
410
410
|
type_ok = notification_type ? ( n['args'].first['notification_type'] == notification_type ) : true
|
411
|
-
rollup_ok =
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
411
|
+
rollup_ok = case rollup
|
412
|
+
when 'none'
|
413
|
+
n['args'].first['rollup'].nil?
|
414
|
+
when nil, n['args'].first['rollup']
|
415
|
+
true
|
416
|
+
else
|
417
|
+
false
|
418
418
|
end
|
419
419
|
type_ok && rollup_ok && ( n['args'].first['address'] == address )
|
420
420
|
}.length
|
data/features/support/env.rb
CHANGED
@@ -68,27 +68,31 @@ end
|
|
68
68
|
|
69
69
|
class RedisDelorean
|
70
70
|
|
71
|
-
|
71
|
+
ShiftTTLsScript = <<SHIFT_TTLS
|
72
72
|
local keys = redis.call('keys', KEYS[1])
|
73
|
-
local
|
74
|
-
local
|
75
|
-
local counter = 0
|
73
|
+
local ttl_decrease = tonumber(ARGV[1])
|
74
|
+
local deleted = 0
|
76
75
|
|
77
76
|
for i,k in ipairs(keys) do
|
78
77
|
local key_ttl = redis.call('ttl', k)
|
79
78
|
|
80
79
|
-- key does not have timeout if < 0
|
81
|
-
if
|
82
|
-
|
83
|
-
|
80
|
+
if key_ttl >= 0 then
|
81
|
+
local diff = key_ttl - ttl_decrease
|
82
|
+
if diff <= 0 then
|
83
|
+
redis.call('del', k)
|
84
|
+
deleted = deleted + 1
|
85
|
+
else
|
86
|
+
redis.call('expire', k, diff)
|
87
|
+
end
|
84
88
|
end
|
85
89
|
end
|
86
|
-
return
|
87
|
-
|
90
|
+
return deleted
|
91
|
+
SHIFT_TTLS
|
88
92
|
|
89
93
|
def self.before_all(options = {})
|
90
94
|
redis = options[:redis]
|
91
|
-
@
|
95
|
+
@shift_ttls_sha = redis.script(:load, ShiftTTLsScript)
|
92
96
|
end
|
93
97
|
|
94
98
|
def self.before_each(options = {})
|
@@ -96,28 +100,20 @@ EXPIRE_AS_IF_AT
|
|
96
100
|
end
|
97
101
|
|
98
102
|
def self.time_travel_to(dest_time)
|
99
|
-
#puts "travelling to #{Time.now.in_time_zone}, real time is #{Time.now_without_delorean.in_time_zone}"
|
100
103
|
old_maybe_fake_time = Time.now.in_time_zone
|
101
|
-
|
102
104
|
Delorean.time_travel_to(dest_time)
|
103
|
-
#puts "
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
real_time = Time.now_without_delorean.to_i
|
116
|
-
#puts "delta #{delta}, expire before real time #{Time.at(real_time + delta)}"
|
117
|
-
|
118
|
-
result = @redis.evalsha(@expire_as_if_at_sha, ['*'],
|
119
|
-
[real_time, real_time + delta])
|
120
|
-
#puts "Expired #{result} key#{(result == 1) ? '' : 's'}"
|
105
|
+
# puts "real time is #{Time.now_without_delorean.in_time_zone}"
|
106
|
+
# puts "old assumed time is #{old_maybe_fake_time}"
|
107
|
+
# puts "new assumed time is #{Time.now.in_time_zone}"
|
108
|
+
|
109
|
+
# keys_prior = @redis.keys('*')
|
110
|
+
|
111
|
+
del = @redis.evalsha(@shift_ttls_sha, ['*'],
|
112
|
+
[(dest_time - old_maybe_fake_time).to_i])
|
113
|
+
|
114
|
+
# keys_after = @redis.keys('*')
|
115
|
+
|
116
|
+
# puts "Expired #{del} key#{(del == 1) ? '' : 's'}, #{(keys_prior - keys_after).inspect}"
|
121
117
|
end
|
122
118
|
|
123
119
|
end
|
@@ -224,6 +224,7 @@ module Flapjack
|
|
224
224
|
unless ['pagerduty'].include?(media)
|
225
225
|
alerting_checks = contact.count_alerting_checks_for_media(media)
|
226
226
|
rollup_threshold = contact.rollup_threshold_for_media(media)
|
227
|
+
|
227
228
|
case
|
228
229
|
when rollup_threshold.nil?
|
229
230
|
# back away slowly
|
@@ -231,8 +232,9 @@ module Flapjack
|
|
231
232
|
next ret if contact.drop_rollup_notifications_for_media?(media)
|
232
233
|
contact.update_sent_rollup_alert_keys_for_media(media, :delete => ok?)
|
233
234
|
rollup_type = 'problem'
|
234
|
-
when (alerting_checks + cleaned >= rollup_threshold
|
235
|
+
when (alerting_checks + cleaned) >= rollup_threshold
|
235
236
|
# alerting checks was just cleaned such that it is now below the rollup threshold
|
237
|
+
contact.update_sent_rollup_alert_keys_for_media(media, :delete => true)
|
236
238
|
rollup_type = 'recovery'
|
237
239
|
end
|
238
240
|
logger.debug "rollup decisions: #{@event_id} #{@state} #{media} #{address} rollup_type: #{rollup_type}"
|
@@ -81,7 +81,7 @@ module Flapjack
|
|
81
81
|
}
|
82
82
|
end
|
83
83
|
|
84
|
-
result
|
84
|
+
{:outages => result}
|
85
85
|
end
|
86
86
|
|
87
87
|
def unscheduled_maintenance(start_time, end_time)
|
@@ -96,7 +96,7 @@ module Flapjack
|
|
96
96
|
pu[:end_time] >= start_time
|
97
97
|
}
|
98
98
|
|
99
|
-
start_in_unsched + unsched_maintenance
|
99
|
+
{:unscheduled_maintenances => (start_in_unsched + unsched_maintenance)}
|
100
100
|
end
|
101
101
|
|
102
102
|
def scheduled_maintenance(start_time, end_time)
|
@@ -111,7 +111,7 @@ module Flapjack
|
|
111
111
|
ps[:end_time] >= start_time
|
112
112
|
}
|
113
113
|
|
114
|
-
start_in_sched + sched_maintenance
|
114
|
+
{:scheduled_maintenances => (start_in_sched + sched_maintenance)}
|
115
115
|
end
|
116
116
|
|
117
117
|
# TODO test whether the below overlapping logic is prone to off-by-one
|
@@ -120,9 +120,7 @@ module Flapjack
|
|
120
120
|
#
|
121
121
|
# TODO test performance with larger data sets
|
122
122
|
def downtime(start_time, end_time)
|
123
|
-
|
124
|
-
|
125
|
-
outs = outage(start_time, end_time)
|
123
|
+
outs = outage(start_time, end_time)[:outages]
|
126
124
|
|
127
125
|
total_secs = {}
|
128
126
|
percentages = {}
|
@@ -139,6 +137,8 @@ module Flapjack
|
|
139
137
|
# We then create two new outage periods to cover the time around
|
140
138
|
# the scheduled maintenance period, and remove the original.
|
141
139
|
|
140
|
+
sched_maintenances = scheduled_maintenance(start_time, end_time)[:scheduled_maintenances]
|
141
|
+
|
142
142
|
sched_maintenances.each do |sm|
|
143
143
|
|
144
144
|
split_outs = []
|
@@ -27,7 +27,9 @@ module Flapjack
|
|
27
27
|
end
|
28
28
|
|
29
29
|
checks = if event_ids.nil?
|
30
|
-
Flapjack::Data::EntityCheck.find_all(:redis => redis)
|
30
|
+
Flapjack::Data::EntityCheck.find_all(:redis => redis).collect {|check_name|
|
31
|
+
find_entity_check_by_name(*check_name.split(':', 2))
|
32
|
+
}
|
31
33
|
elsif !event_ids.empty?
|
32
34
|
event_ids.collect {|event_id| find_entity_check_by_name(*event_id.split(':', 2)) }
|
33
35
|
else
|
@@ -68,12 +68,14 @@ module Flapjack
|
|
68
68
|
end
|
69
69
|
|
70
70
|
@base_url = @config['base_url']
|
71
|
-
|
72
|
-
@base_url
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
unless @base_url
|
72
|
+
@logger.info "base_url is not configured, setting to '/'"
|
73
|
+
@base_url = '/'
|
74
|
+
end
|
75
|
+
|
76
|
+
unless @base_url.match(/^.*\/$/)
|
77
|
+
@logger.warn "base_url must end with a trailing '/', setting to '#{@base_url}/'"
|
78
|
+
@base_url = "#{@base_url}/"
|
77
79
|
end
|
78
80
|
|
79
81
|
# constants won't be exposed to eRb scope
|
data/lib/flapjack/version.rb
CHANGED
@@ -47,8 +47,10 @@ describe 'Flapjack::Gateways::JSONAPI::CheckPresenter' do
|
|
47
47
|
ecp = Flapjack::Gateways::JSONAPI::CheckPresenter.new(entity_check)
|
48
48
|
outages = ecp.outage(time - (5 * 60 * 60), time - (2 * 60 * 60))
|
49
49
|
expect(outages).not_to be_nil
|
50
|
-
expect(outages).to
|
51
|
-
expect(outages
|
50
|
+
expect(outages).to be_a(Hash)
|
51
|
+
expect(outages).to have_key(:outages)
|
52
|
+
expect(outages[:outages]).to be_an(Array)
|
53
|
+
expect(outages[:outages].size).to eq(4)
|
52
54
|
|
53
55
|
# TODO check the data in those hashes
|
54
56
|
end
|
@@ -63,8 +65,10 @@ describe 'Flapjack::Gateways::JSONAPI::CheckPresenter' do
|
|
63
65
|
ecp = Flapjack::Gateways::JSONAPI::CheckPresenter.new(entity_check)
|
64
66
|
outages = ecp.outage(nil, nil)
|
65
67
|
expect(outages).not_to be_nil
|
66
|
-
expect(outages).to
|
67
|
-
expect(outages
|
68
|
+
expect(outages).to be_a(Hash)
|
69
|
+
expect(outages).to have_key(:outages)
|
70
|
+
expect(outages[:outages]).to be_an(Array)
|
71
|
+
expect(outages[:outages].size).to eq(4)
|
68
72
|
|
69
73
|
# TODO check the data in those hashes
|
70
74
|
end
|
@@ -82,8 +86,10 @@ describe 'Flapjack::Gateways::JSONAPI::CheckPresenter' do
|
|
82
86
|
ecp = Flapjack::Gateways::JSONAPI::CheckPresenter.new(entity_check)
|
83
87
|
outages = ecp.outage(nil, nil)
|
84
88
|
expect(outages).not_to be_nil
|
85
|
-
expect(outages).to
|
86
|
-
expect(outages
|
89
|
+
expect(outages).to be_a(Hash)
|
90
|
+
expect(outages).to have_key(:outages)
|
91
|
+
expect(outages[:outages]).to be_an(Array)
|
92
|
+
expect(outages[:outages].size).to eq(3)
|
87
93
|
end
|
88
94
|
|
89
95
|
it "returns a (small) outage hash for a single state change" do
|
@@ -95,8 +101,10 @@ describe 'Flapjack::Gateways::JSONAPI::CheckPresenter' do
|
|
95
101
|
ecp = Flapjack::Gateways::JSONAPI::CheckPresenter.new(entity_check)
|
96
102
|
outages = ecp.outage(nil, nil)
|
97
103
|
expect(outages).not_to be_nil
|
98
|
-
expect(outages).to
|
99
|
-
expect(outages
|
104
|
+
expect(outages).to be_a(Hash)
|
105
|
+
expect(outages).to have_key(:outages)
|
106
|
+
expect(outages[:outages]).to be_an(Array)
|
107
|
+
expect(outages[:outages].size).to eq(1)
|
100
108
|
end
|
101
109
|
|
102
110
|
it "a list of unscheduled maintenances for an entity check" do
|
@@ -109,8 +117,10 @@ describe 'Flapjack::Gateways::JSONAPI::CheckPresenter' do
|
|
109
117
|
ecp = Flapjack::Gateways::JSONAPI::CheckPresenter.new(entity_check)
|
110
118
|
unsched_maint = ecp.unscheduled_maintenance(time - (12 * 60 * 60), time)
|
111
119
|
|
112
|
-
expect(unsched_maint).to
|
113
|
-
expect(unsched_maint
|
120
|
+
expect(unsched_maint).to be_a(Hash)
|
121
|
+
expect(unsched_maint).to have_key(:unscheduled_maintenances)
|
122
|
+
expect(unsched_maint[:unscheduled_maintenances]).to be_an(Array)
|
123
|
+
expect(unsched_maint[:unscheduled_maintenances].size).to eq(4)
|
114
124
|
|
115
125
|
# TODO check the data in those hashes
|
116
126
|
end
|
@@ -125,8 +135,10 @@ describe 'Flapjack::Gateways::JSONAPI::CheckPresenter' do
|
|
125
135
|
ecp = Flapjack::Gateways::JSONAPI::CheckPresenter.new(entity_check)
|
126
136
|
sched_maint = ecp.scheduled_maintenance(time - (12 * 60 * 60), time)
|
127
137
|
|
128
|
-
expect(sched_maint).to
|
129
|
-
expect(sched_maint
|
138
|
+
expect(sched_maint).to be_a(Hash)
|
139
|
+
expect(sched_maint).to have_key(:scheduled_maintenances)
|
140
|
+
expect(sched_maint[:scheduled_maintenances]).to be_an(Array)
|
141
|
+
expect(sched_maint[:scheduled_maintenances].size).to eq(4)
|
130
142
|
|
131
143
|
# TODO check the data in those hashes
|
132
144
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
if ENV['COVERAGE']
|
2
2
|
require 'simplecov'
|
3
|
-
|
4
3
|
SimpleCov.start do
|
5
4
|
add_filter '/spec/'
|
6
5
|
end
|
6
|
+
SimpleCov.at_exit do
|
7
|
+
Oj.default_options = { :mode => :compat }
|
8
|
+
SimpleCov.result.format!
|
9
|
+
end
|
7
10
|
end
|
8
11
|
|
9
12
|
$testing = true
|
@@ -16,16 +19,17 @@ ENV['RACK_ENV'] = ENV["FLAPJACK_ENV"]
|
|
16
19
|
require 'bundler'
|
17
20
|
Bundler.require(:default, :test)
|
18
21
|
|
22
|
+
require 'oj'
|
23
|
+
Oj.default_options = { :indent => 0, :mode => :strict }
|
24
|
+
Oj.mimic_JSON
|
25
|
+
require 'active_support/json'
|
26
|
+
|
19
27
|
require 'webmock/rspec'
|
20
28
|
WebMock.disable_net_connect!
|
21
29
|
|
22
30
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
23
31
|
require 'flapjack/configuration'
|
24
32
|
|
25
|
-
require 'oj'
|
26
|
-
Oj.mimic_JSON
|
27
|
-
Oj.default_options = { :indent => 0, :mode => :strict }
|
28
|
-
require 'active_support/json'
|
29
33
|
|
30
34
|
# Requires supporting files with custom matchers and macros, etc,
|
31
35
|
# in ./support/ and its subdirectories.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flapjack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.0rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lindsay Holmwood
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-07-
|
13
|
+
date: 2014-07-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: dante
|