flapjack 1.6.0rc2 → 1.6.0rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/flapjack/data/entity_check.rb +4 -1
- data/lib/flapjack/data/notification_rule.rb +17 -15
- data/lib/flapjack/gateways/aws_sns.rb +4 -6
- data/lib/flapjack/gateways/aws_sns/alert.text.erb +1 -1
- data/lib/flapjack/gateways/email/rollup.html.erb +3 -0
- data/lib/flapjack/notifier.rb +2 -1
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/notification_rule_spec.rb +46 -4
- data/spec/lib/flapjack/gateways/aws_sns_spec.rb +6 -4
- 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: 5a219d75b1878de449c0a2735258b2962516b75b
|
4
|
+
data.tar.gz: 66d8c984b4204482680ffeaa711f540ab60c4297
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb07615b716a155706165d2bec88ec020df60602ef75e45ae8c5911aca3032dc1e1b3198d7a9e972614ea166cc04adfc43d6fe3e94739594e74ad159d43c9912
|
7
|
+
data.tar.gz: 877f7c37d41c7068799a26012463f254b15c3bd1698ee66eca186f09a4ad317de6f9bf0cbfb446620f586bff2d088a8a9b68cf5c6e817207affd20ed10543d0d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
## Flapjack Changelog
|
2
2
|
|
3
|
+
# 1.6.0rc3 - 2015-06-15
|
4
|
+
- Chore/Bug?: SNS gateway improvements (@ali-graham)
|
5
|
+
- Feature: add summary to rollup alerts #869 (@necula-01)
|
6
|
+
- Bug: Fix notification rule regex matches #871 (@necula-01)
|
7
|
+
|
3
8
|
# 1.6.0rc2 - 2015-05-14
|
4
9
|
- Bug: Fix SNS query encoding and subject length #867 (@ali-graham, @xcxsxvx)
|
5
10
|
- Chore: improve debug logging in pagerduty when looking for acks e44abd5 (@jessereynolds)
|
@@ -933,7 +933,10 @@ module Flapjack
|
|
933
933
|
if @ack_hash.nil?
|
934
934
|
sha1 = Digest::SHA1.new
|
935
935
|
@ack_hash = Digest.hexencode(sha1.digest(@key))[0..7].downcase
|
936
|
-
@redis.
|
936
|
+
@redis.multi do |r|
|
937
|
+
r.hset("checks_by_hash", @ack_hash, @key)
|
938
|
+
r.hset("check_hashes_by_id", @key, @ack_hash)
|
939
|
+
end
|
937
940
|
end
|
938
941
|
@ack_hash
|
939
942
|
end
|
@@ -121,37 +121,39 @@ module Flapjack
|
|
121
121
|
Flapjack.dump_json(json_data)
|
122
122
|
end
|
123
123
|
|
124
|
-
#
|
124
|
+
# If the rule has any entities, then one of them must match the event's entity
|
125
125
|
def match_entity?(event_id)
|
126
|
-
return
|
127
|
-
|
126
|
+
return true unless @entities && @entities.length > 0
|
127
|
+
event_entity = event_id.split(':').first
|
128
|
+
@entities.include?(event_entity)
|
128
129
|
end
|
129
130
|
|
130
|
-
#
|
131
|
+
# If the rule has any regex_entities, then all of them must match the
|
132
|
+
# event's entity
|
131
133
|
def match_regex_entities?(event_id)
|
132
|
-
return
|
133
|
-
|
134
|
+
return true unless @regex_entities && @regex_entities.length > 0
|
135
|
+
event_entity = event_id.split(':').first
|
134
136
|
matches = 0
|
135
137
|
@regex_entities.each do |regex_entity|
|
136
|
-
matches += 1 if /#{regex_entity}/ ===
|
138
|
+
matches += 1 if /#{regex_entity}/ === event_entity
|
137
139
|
end
|
138
140
|
matches >= @regex_entities.length
|
139
141
|
end
|
140
142
|
|
141
|
-
# tags
|
143
|
+
# If the rule has any tags, then they must all be present in the
|
144
|
+
# event's tags
|
142
145
|
def match_tags?(event_tags)
|
143
|
-
return
|
146
|
+
return true unless @tags && @tags.length > 0
|
144
147
|
@tags.subset?(event_tags)
|
145
148
|
end
|
146
149
|
|
147
|
-
# regex_tags match
|
150
|
+
# If the rule has any regex_tags, then they must all match at least
|
151
|
+
# one of the event's tags
|
148
152
|
def match_regex_tags?(event_tags)
|
149
|
-
return
|
153
|
+
return true unless @regex_tags && @regex_tags.length > 0
|
150
154
|
matches = 0
|
151
|
-
|
152
|
-
|
153
|
-
matches += 1 if /#{regex_tag}/ === event_tag
|
154
|
-
end
|
155
|
+
@regex_tags.each do |regex_tag|
|
156
|
+
matches += 1 if event_tags.any? { |event_tag| /#{regex_tag}/ === event_tag }
|
155
157
|
end
|
156
158
|
matches >= @regex_tags.length
|
157
159
|
end
|
@@ -60,7 +60,7 @@ module Flapjack
|
|
60
60
|
endpoint = "http://#{hostname}/"
|
61
61
|
access_key = @config["access_key"]
|
62
62
|
secret_key = @config["secret_key"]
|
63
|
-
timestamp =
|
63
|
+
timestamp = Time.at(alert.time).strftime('%Y-%m-%dT%H:%M:%SZ')
|
64
64
|
|
65
65
|
address = alert.address
|
66
66
|
notification_id = alert.notification_id
|
@@ -118,7 +118,7 @@ module Flapjack
|
|
118
118
|
'SignatureVersion' => 2,
|
119
119
|
'SignatureMethod' => 'HmacSHA256',
|
120
120
|
'Timestamp' => timestamp,
|
121
|
-
'AWSAccessKeyId' => access_key}
|
121
|
+
'AWSAccessKeyId' => access_key.upcase}
|
122
122
|
|
123
123
|
string_to_sign = self.class.string_to_sign('POST', hostname, "/", query)
|
124
124
|
|
@@ -145,7 +145,7 @@ module Flapjack
|
|
145
145
|
end
|
146
146
|
|
147
147
|
def self.get_signature(secret_key, string_to_sign)
|
148
|
-
signature = OpenSSL::HMAC.digest('sha256', secret_key, string_to_sign)
|
148
|
+
signature = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret_key, string_to_sign)
|
149
149
|
|
150
150
|
Base64.encode64(signature).strip
|
151
151
|
end
|
@@ -153,10 +153,8 @@ module Flapjack
|
|
153
153
|
def self.string_to_sign(method, host, uri, query)
|
154
154
|
@safe_re ||= Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
|
155
155
|
|
156
|
-
# we should possibly escape the keys as well, but they are less
|
157
|
-
# likely to have problematic characters
|
158
156
|
encoded_query = query.keys.sort.collect {|key|
|
159
|
-
"#{key}=#{URI.escape(query[key].to_s, @safe_re)}"
|
157
|
+
"#{URI.escape(key, @safe_re)}=#{URI.escape(query[key].to_s, @safe_re)}"
|
160
158
|
}.join("&")
|
161
159
|
|
162
160
|
[method.upcase,
|
@@ -22,16 +22,19 @@
|
|
22
22
|
<th>Entity</th>
|
23
23
|
<th>State</th>
|
24
24
|
<th>Duration</th>
|
25
|
+
<th>Summary</th>
|
25
26
|
</tr>
|
26
27
|
<% @alert.rollup_alerts.sort_by {|entity_check, details| details['duration'] }.each do |rollup_alert| -%>
|
27
28
|
<% r_entity, r_check = rollup_alert[0].split(':', 2) -%>
|
28
29
|
<% state = rollup_alert[1]['state'] -%>
|
29
30
|
<% duration = (ChronicDuration.output(rollup_alert[1]['duration'], :keep_zero => true) || '0 secs') -%>
|
31
|
+
<% summary = rollup_alert[1]['summary'] -%>
|
30
32
|
<tr>
|
31
33
|
<td><%= r_check %></td>
|
32
34
|
<td><%= r_entity %></td>
|
33
35
|
<td><%= ['ok'].include?(state) ? state.upcase : state.titleize %></td>
|
34
36
|
<td><%= duration %></td>
|
37
|
+
<td><%= summary %></td>
|
35
38
|
</tr>
|
36
39
|
<% end %>
|
37
40
|
</tbody>
|
data/lib/flapjack/notifier.rb
CHANGED
data/lib/flapjack/version.rb
CHANGED
@@ -16,7 +16,23 @@ describe Flapjack::Data::NotificationRule, :redis => true do
|
|
16
16
|
{:contact_id => '23',
|
17
17
|
:tags => ["database","physical"],
|
18
18
|
:regex_tags => [],
|
19
|
-
:entities => ["foo-app-01.example.com"],
|
19
|
+
:entities => ["foo-app-01.example.com", "foo-app-10.example.com"],
|
20
|
+
:regex_entities => [],
|
21
|
+
:time_restrictions => [ weekdays_8_18 ],
|
22
|
+
:unknown_media => [],
|
23
|
+
:warning_media => ["email"],
|
24
|
+
:critical_media => ["sms", "email"],
|
25
|
+
:unknown_blackhole => false,
|
26
|
+
:warning_blackhole => false,
|
27
|
+
:critical_blackhole => false
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
let(:empty_rule_data) {
|
32
|
+
{:contact_id => '23',
|
33
|
+
:tags => [],
|
34
|
+
:regex_tags => [],
|
35
|
+
:entities => [],
|
20
36
|
:regex_entities => [],
|
21
37
|
:time_restrictions => [ weekdays_8_18 ],
|
22
38
|
:unknown_media => [],
|
@@ -33,7 +49,7 @@ describe Flapjack::Data::NotificationRule, :redis => true do
|
|
33
49
|
:tags => [],
|
34
50
|
:regex_tags => ["^data.*$","^(physical|bare_metal)$"],
|
35
51
|
:entities => [],
|
36
|
-
:regex_entities => [
|
52
|
+
:regex_entities => ['^foo-\S{3}-\d{2}.example.com$','.*abc.*'],
|
37
53
|
:time_restrictions => [ weekdays_8_18 ],
|
38
54
|
:unknown_media => [],
|
39
55
|
:warning_media => ["email"],
|
@@ -52,6 +68,10 @@ describe Flapjack::Data::NotificationRule, :redis => true do
|
|
52
68
|
Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
|
53
69
|
}
|
54
70
|
|
71
|
+
let(:existing_empty_rule) {
|
72
|
+
Flapjack::Data::NotificationRule.add(empty_rule_data, :redis => @redis)
|
73
|
+
}
|
74
|
+
|
55
75
|
let(:existing_regex_rule) {
|
56
76
|
Flapjack::Data::NotificationRule.add(regex_rule_data, :redis => @redis)
|
57
77
|
}
|
@@ -100,25 +120,47 @@ describe Flapjack::Data::NotificationRule, :redis => true do
|
|
100
120
|
rule = existing_rule
|
101
121
|
|
102
122
|
expect(rule.match_entity?('foo-app-01.example.com')).to be true
|
123
|
+
expect(rule.match_entity?('foo-app-10.example.com')).to be true
|
103
124
|
expect(rule.match_entity?('foo-app-02.example.com')).to be false
|
125
|
+
|
126
|
+
expect(existing_empty_rule.match_entity?('anything.example.com')).to be true
|
127
|
+
end
|
128
|
+
|
129
|
+
it "checks whether entity names match a regex" do
|
130
|
+
rule = existing_regex_rule
|
131
|
+
|
132
|
+
expect(rule.match_regex_entities?('foo-abc-01.example.com')).to be true
|
133
|
+
expect(rule.match_regex_entities?('foo-abc-99.example.com')).to be true
|
134
|
+
expect(rule.match_regex_entities?('foo-app-01.example.com')).to be false # does not match second regexp_entities
|
135
|
+
expect(rule.match_regex_entities?('foo-abc.example.com')).to be false
|
136
|
+
expect(rule.match_regex_entities?('bar-abc-01.example.com')).to be false
|
137
|
+
|
138
|
+
expect(existing_empty_rule.match_regex_entities?('anything.example.com')).to be true
|
104
139
|
end
|
105
140
|
|
106
|
-
it "checks whether
|
141
|
+
it "checks whether event tags match" do
|
107
142
|
rule = existing_rule
|
108
143
|
|
109
144
|
expect(rule.match_tags?(['database', 'physical'].to_set)).to be true
|
110
145
|
expect(rule.match_tags?(['database', 'physical', 'beetroot'].to_set)).to be true
|
111
146
|
expect(rule.match_tags?(['database'].to_set)).to be false
|
112
147
|
expect(rule.match_tags?(['virtual'].to_set)).to be false
|
148
|
+
expect(rule.match_tags?([].to_set)).to be false
|
149
|
+
|
150
|
+
expect(existing_empty_rule.match_regex_entities?(['virtual'].to_set)).to be true
|
113
151
|
end
|
114
152
|
|
115
|
-
it "checks whether
|
153
|
+
it "checks whether event tags match a regex" do
|
116
154
|
rule = existing_regex_rule
|
117
155
|
|
118
156
|
expect(rule.match_regex_tags?(['database', 'physical'].to_set)).to be true
|
119
157
|
expect(rule.match_regex_tags?(['database', 'physical', 'beetroot'].to_set)).to be true
|
120
158
|
expect(rule.match_regex_tags?(['database'].to_set)).to be false
|
159
|
+
expect(rule.match_regex_tags?(['database.physical'].to_set)).to be false # does not match second regex_tags
|
160
|
+
expect(rule.match_regex_tags?(['data1', 'data2'].to_set)).to be false # does not match second regex_tags
|
121
161
|
expect(rule.match_regex_tags?(['virtual'].to_set)).to be false
|
162
|
+
|
163
|
+
expect(existing_empty_rule.match_regex_entities?(['virtual'].to_set)).to be true
|
122
164
|
end
|
123
165
|
|
124
166
|
it "checks if blackhole settings for a rule match a severity level" do
|
@@ -9,7 +9,7 @@ describe Flapjack::Gateways::AwsSns, :logger => true do
|
|
9
9
|
|
10
10
|
let(:time) { Time.new(2013, 10, 31, 13, 45) }
|
11
11
|
|
12
|
-
let(:time_str) { Time.at(time).strftime('
|
12
|
+
let(:time_str) { Time.at(time.to_i).strftime('%Y-%m-%dT%H:%M:%SZ') }
|
13
13
|
|
14
14
|
let(:config) { {'region' => 'us-east-1',
|
15
15
|
'access_key' => 'AKIAIOSFODNN7EXAMPLE',
|
@@ -39,7 +39,9 @@ describe Flapjack::Gateways::AwsSns, :logger => true do
|
|
39
39
|
'AWSAccessKeyId' => config['access_key'],
|
40
40
|
'TopicArn' => message['address'],
|
41
41
|
'SignatureVersion' => '2',
|
42
|
-
'SignatureMethod' => 'HmacSHA256'
|
42
|
+
'SignatureMethod' => 'HmacSHA256',
|
43
|
+
'Signature' => 'gxoUQ8qUYBQbqgf3XmbiSPZ8qTJZ9WyC81EKc67FY0g=',
|
44
|
+
'Timestamp' => time_str})).
|
43
45
|
to_return(:status => 200)
|
44
46
|
|
45
47
|
EM.synchrony do
|
@@ -98,7 +100,7 @@ describe Flapjack::Gateways::AwsSns, :logger => true do
|
|
98
100
|
|
99
101
|
let(:query) { {'TopicArn' => 'HelloWorld',
|
100
102
|
'Action' => 'Publish',
|
101
|
-
'Message' => 'Hello World'} }
|
103
|
+
'Message' => 'Hello ~ World'} }
|
102
104
|
|
103
105
|
let(:string_to_sign) { Flapjack::Gateways::AwsSns.string_to_sign(method, host, uri, query) }
|
104
106
|
|
@@ -117,7 +119,7 @@ describe Flapjack::Gateways::AwsSns, :logger => true do
|
|
117
119
|
end
|
118
120
|
|
119
121
|
it 'should put the encoded, sorted query-string on the fourth line' do
|
120
|
-
expect(lines[3]).to eq("Action=Publish&Message=Hello%20World&TopicArn=HelloWorld")
|
122
|
+
expect(lines[3]).to eq("Action=Publish&Message=Hello%20~%20World&TopicArn=HelloWorld")
|
121
123
|
end
|
122
124
|
|
123
125
|
end
|
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.6.
|
4
|
+
version: 1.6.0rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lindsay Holmwood
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-
|
14
|
+
date: 2015-06-15 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: dante
|