flapjack 0.7.27 → 0.7.28
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/bin/flapjack +22 -28
- data/bin/flapjack-nagios-receiver +5 -27
- data/bin/flapjack-populator +2 -2
- data/bin/flapper +13 -14
- data/bin/receive-events +3 -20
- data/bin/simulate-failed-check +3 -20
- data/etc/flapjack_config.yaml.example +119 -86
- data/features/cli.feature +69 -0
- data/features/events.feature +15 -0
- data/features/packaging-lintian.feature +4 -6
- data/features/rollup.feature +198 -0
- data/features/steps/cli_steps.rb +81 -0
- data/features/steps/events_steps.rb +26 -16
- data/features/steps/notifications_steps.rb +2 -2
- data/features/steps/packaging-lintian_steps.rb +2 -2
- data/features/support/daemons.rb +113 -0
- data/features/support/env.rb +26 -4
- data/lib/flapjack/configuration.rb +2 -0
- data/lib/flapjack/data/contact.rb +76 -5
- data/lib/flapjack/data/entity_check.rb +16 -0
- data/lib/flapjack/data/message.rb +11 -8
- data/lib/flapjack/data/notification.rb +31 -3
- data/lib/flapjack/data/notification_rule.rb +1 -1
- data/lib/flapjack/filters/delays.rb +1 -5
- data/lib/flapjack/gateways/api/contact_methods.rb +12 -6
- data/lib/flapjack/gateways/email.rb +35 -26
- data/lib/flapjack/gateways/email/alert.html.erb +4 -4
- data/lib/flapjack/gateways/email/alert.text.erb +2 -2
- data/lib/flapjack/gateways/email/alert_subject.text.erb +14 -0
- data/lib/flapjack/gateways/email/rollup.html.erb +48 -0
- data/lib/flapjack/gateways/email/rollup.text.erb +20 -0
- data/lib/flapjack/gateways/email/rollup_subject.text.erb +19 -0
- data/lib/flapjack/gateways/jabber.rb +97 -47
- data/lib/flapjack/gateways/sms_messagenet.rb +26 -24
- data/lib/flapjack/gateways/sms_messagenet/alert.text.erb +15 -0
- data/lib/flapjack/gateways/sms_messagenet/rollup.text.erb +34 -0
- data/lib/flapjack/gateways/web/views/contact.html.erb +16 -8
- data/lib/flapjack/notifier.rb +17 -4
- data/lib/flapjack/processor.rb +1 -1
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +19 -19
- data/spec/lib/flapjack/data/contact_spec.rb +100 -25
- data/spec/lib/flapjack/data/event_spec.rb +1 -1
- data/spec/lib/flapjack/data/message_spec.rb +1 -1
- data/spec/lib/flapjack/data/notification_spec.rb +11 -3
- data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +36 -17
- data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +38 -38
- data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +15 -15
- data/spec/lib/flapjack/gateways/email_spec.rb +4 -4
- data/spec/lib/flapjack/gateways/jabber_spec.rb +13 -14
- data/spec/lib/flapjack/gateways/oobetet_spec.rb +2 -2
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +5 -5
- data/spec/lib/flapjack/gateways/sms_messagenet.spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +2 -2
- data/spec/lib/flapjack/gateways/web_spec.rb +4 -4
- data/spec/lib/flapjack/logger_spec.rb +3 -3
- data/spec/lib/flapjack/pikelet_spec.rb +10 -10
- data/spec/lib/flapjack/processor_spec.rb +4 -4
- data/spec/lib/flapjack/redis_pool_spec.rb +1 -1
- metadata +70 -5
- checksums.yaml +0 -15
@@ -94,7 +94,11 @@ module Flapjack
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def ok?
|
97
|
-
['ok', 'up'].include?(@state)
|
97
|
+
@state && ['ok', 'up'].include?(@state.downcase)
|
98
|
+
end
|
99
|
+
|
100
|
+
def acknowledgement?
|
101
|
+
@state && ['acknowledgement'].include?(@state.downcase)
|
98
102
|
end
|
99
103
|
|
100
104
|
def contents
|
@@ -190,9 +194,33 @@ module Flapjack
|
|
190
194
|
|
191
195
|
logger.debug "media_to_use: #{media_to_use}"
|
192
196
|
|
193
|
-
|
197
|
+
# here begins rollup madness
|
198
|
+
media_to_use.each_pair.inject([]) { |ret, (media, address)|
|
199
|
+
rollup_type = nil
|
200
|
+
|
201
|
+
contact.add_alerting_check_for_media(media, @event_id) unless ok? || acknowledgement?
|
202
|
+
|
203
|
+
# expunge checks in (un)scheduled maintenance from the alerting set
|
204
|
+
cleaned = contact.clean_alerting_checks_for_media(media)
|
205
|
+
logger.debug("cleaned alerting checks for #{media}: #{cleaned}")
|
206
|
+
|
207
|
+
alerting_checks = contact.count_alerting_checks_for_media(media)
|
208
|
+
rollup_threshold = contact.rollup_threshold_for_media(media)
|
209
|
+
case
|
210
|
+
when rollup_threshold.nil?
|
211
|
+
# back away slowly
|
212
|
+
when alerting_checks >= rollup_threshold
|
213
|
+
next ret if contact.drop_rollup_notifications_for_media?(media)
|
214
|
+
contact.update_sent_rollup_alert_keys_for_media(media, :delete => ok?)
|
215
|
+
rollup_type = 'problem'
|
216
|
+
when (alerting_checks + cleaned >= rollup_threshold)
|
217
|
+
# alerting checks was just cleaned such that it is now below the rollup threshold
|
218
|
+
rollup_type = 'recovery'
|
219
|
+
end
|
220
|
+
logger.debug "rollup decisions: #{@event_id} #{@state} #{media} #{address} rollup_type: #{rollup_type}"
|
221
|
+
|
194
222
|
m = Flapjack::Data::Message.for_contact(contact,
|
195
|
-
:medium =>
|
223
|
+
:medium => media, :address => address, :rollup => rollup_type)
|
196
224
|
ret << m
|
197
225
|
ret
|
198
226
|
}
|
@@ -145,7 +145,7 @@ module Flapjack
|
|
145
145
|
:contact_id => rule_data[:contact_id].to_s,
|
146
146
|
:entities => Oj.dump(rule_data[:entities]),
|
147
147
|
:tags => Oj.dump(tag_data),
|
148
|
-
:time_restrictions => Oj.dump(rule_data[:time_restrictions]),
|
148
|
+
:time_restrictions => Oj.dump(rule_data[:time_restrictions], :mode => :compat),
|
149
149
|
:unknown_media => Oj.dump(rule_data[:unknown_media]),
|
150
150
|
:warning_media => Oj.dump(rule_data[:warning_media]),
|
151
151
|
:critical_media => Oj.dump(rule_data[:critical_media]),
|
@@ -36,12 +36,8 @@ module Flapjack
|
|
36
36
|
end
|
37
37
|
|
38
38
|
last_problem_alert = entity_check.last_notification_for_state(:problem)[:timestamp]
|
39
|
-
last_warning_alert = entity_check.last_notification_for_state(:warning)[:timestamp]
|
40
|
-
last_critical_alert = entity_check.last_notification_for_state(:critical)[:timestamp]
|
41
39
|
last_change = entity_check.last_change
|
42
|
-
|
43
|
-
last_alert_state = last_notification[:type]
|
44
|
-
last_alert_timestamp = last_notification[:timestamp]
|
40
|
+
last_alert_state = entity_check.last_notification[:type]
|
45
41
|
|
46
42
|
current_time = Time.now.to_i
|
47
43
|
current_state_duration = current_time - last_change
|
@@ -197,9 +197,11 @@ module Flapjack
|
|
197
197
|
|
198
198
|
media = contact.media
|
199
199
|
media_intervals = contact.media_intervals
|
200
|
+
media_rollup_thresholds = contact.media_rollup_thresholds
|
200
201
|
media_addr_int = hashify(*media.keys) {|k|
|
201
|
-
[k, {'address'
|
202
|
-
'interval'
|
202
|
+
[k, {'address' => media[k],
|
203
|
+
'interval' => media_intervals[k],
|
204
|
+
'rollup_threshold' => media_rollup_thresholds[k] }]
|
203
205
|
}
|
204
206
|
media_addr_int.to_json
|
205
207
|
end
|
@@ -218,8 +220,10 @@ module Flapjack
|
|
218
220
|
if interval.nil?
|
219
221
|
halt err(403, "no #{params[:id]} interval for contact '#{params[:contact_id]}'")
|
220
222
|
end
|
221
|
-
|
222
|
-
|
223
|
+
rollup_threshold = contact.media_rollup_thresholds[params[:id]]
|
224
|
+
{'address' => media,
|
225
|
+
'interval' => interval,
|
226
|
+
'rollup_threshold' => rollup_threshold }.to_json
|
223
227
|
end
|
224
228
|
|
225
229
|
# Creates or updates a media of a contact
|
@@ -237,9 +241,11 @@ module Flapjack
|
|
237
241
|
|
238
242
|
contact.set_address_for_media(params[:id], params[:address])
|
239
243
|
contact.set_interval_for_media(params[:id], params[:interval])
|
244
|
+
contact.set_rollup_threshold_for_media(params[:id], params[:rollup_threshold])
|
240
245
|
|
241
|
-
{'address'
|
242
|
-
'interval'
|
246
|
+
{'address' => contact.media[params[:id]],
|
247
|
+
'interval' => contact.media_intervals[params[:id]],
|
248
|
+
'rollup_threshold' => contact.media_rollup_thresholds[params[:id]]}.to_json
|
243
249
|
end
|
244
250
|
|
245
251
|
# delete a media of a contact
|
@@ -4,6 +4,7 @@ require 'mail'
|
|
4
4
|
require 'erb'
|
5
5
|
require 'socket'
|
6
6
|
require 'chronic_duration'
|
7
|
+
require 'active_support/inflector'
|
7
8
|
|
8
9
|
require 'em-synchrony'
|
9
10
|
require 'em/protocols/smtpclient'
|
@@ -26,6 +27,7 @@ module Flapjack
|
|
26
27
|
@logger.debug("new email gateway pikelet with the following options: #{@config.inspect}")
|
27
28
|
@smtp_config = @config.delete('smtp_config')
|
28
29
|
@sent = 0
|
30
|
+
@fqdn = `/bin/hostname -f`.chomp
|
29
31
|
end
|
30
32
|
|
31
33
|
# TODO refactor to remove complexity
|
@@ -34,12 +36,17 @@ module Flapjack
|
|
34
36
|
deliver( notification )
|
35
37
|
end
|
36
38
|
|
39
|
+
# sets a bunch of class instance variables for each email
|
37
40
|
def prepare(notification)
|
38
41
|
@logger.debug "Woo, got a notification to send out: #{notification.inspect}"
|
39
42
|
|
40
43
|
# The instance variables are referenced by the templates, which
|
41
44
|
# share the current binding context
|
42
45
|
@notification_type = notification['notification_type']
|
46
|
+
@notification_id = notification['id'] || SecureRandom.uuid
|
47
|
+
@rollup = notification['rollup']
|
48
|
+
@rollup_alerts = notification['rollup_alerts']
|
49
|
+
@rollup_threshold = notification['rollup_threshold']
|
43
50
|
@contact_first_name = notification['contact_first_name']
|
44
51
|
@contact_last_name = notification['contact_last_name']
|
45
52
|
@state = notification['state']
|
@@ -57,17 +64,6 @@ module Flapjack
|
|
57
64
|
@in_unscheduled_maintenance = entity_check.in_scheduled_maintenance?
|
58
65
|
@in_scheduled_maintenance = entity_check.in_unscheduled_maintenance?
|
59
66
|
|
60
|
-
headline_map = {'problem' => 'Problem: ',
|
61
|
-
'recovery' => 'Recovery: ',
|
62
|
-
'acknowledgement' => 'Acknowledgement: ',
|
63
|
-
'test' => 'Test Notification: ',
|
64
|
-
'unknown' => ''
|
65
|
-
}
|
66
|
-
|
67
|
-
headline = headline_map[@notification_type] || ''
|
68
|
-
|
69
|
-
@subject = "#{headline}'#{@check}' on #{@entity_name}"
|
70
|
-
@subject += " is #{@state.upcase}" unless ['acknowledgement', 'test'].include?(@notification_type)
|
71
67
|
rescue => e
|
72
68
|
@logger.error "Error preparing email to #{m_to}: #{e.class}: #{e.message}"
|
73
69
|
@logger.error e.backtrace.join("\n")
|
@@ -87,23 +83,19 @@ module Flapjack
|
|
87
83
|
end
|
88
84
|
end
|
89
85
|
|
90
|
-
|
91
|
-
m_from = "flapjack@#{fqdn}"
|
86
|
+
m_from = "flapjack@#{@fqdn}"
|
92
87
|
@logger.debug("flapjack_mailer: set from to #{m_from}")
|
93
88
|
m_reply_to = m_from
|
94
89
|
m_to = notification['address']
|
95
90
|
|
96
|
-
@logger.debug("sending Flapjack::Notification::Email " +
|
97
|
-
"#{notification['id']} to: #{m_to} subject: #{@subject}")
|
98
91
|
|
99
|
-
mail = prepare_email(:
|
100
|
-
:
|
101
|
-
:to => m_to)
|
92
|
+
mail = prepare_email(:from => m_from,
|
93
|
+
:to => m_to)
|
102
94
|
|
103
95
|
smtp_args = {:from => m_from,
|
104
96
|
:to => m_to,
|
105
97
|
:content => "#{mail.to_s}\r\n.\r\n",
|
106
|
-
:domain => fqdn,
|
98
|
+
:domain => @fqdn,
|
107
99
|
:host => host || 'localhost',
|
108
100
|
:port => port || 25,
|
109
101
|
:starttls => starttls}
|
@@ -132,20 +124,37 @@ module Flapjack
|
|
132
124
|
private
|
133
125
|
|
134
126
|
def prepare_email(opts = {})
|
127
|
+
from = opts[:from]
|
128
|
+
to = opts[:to]
|
129
|
+
message_id = "<#{@notification_id}@#{@fqdn}>"
|
130
|
+
|
131
|
+
message_type = case
|
132
|
+
when @rollup
|
133
|
+
'rollup'
|
134
|
+
else
|
135
|
+
'alert'
|
136
|
+
end
|
137
|
+
|
138
|
+
subject_template = ERB.new(File.read(File.dirname(__FILE__) +
|
139
|
+
"/email/#{message_type}_subject.text.erb"), nil, '-')
|
135
140
|
|
136
141
|
text_template = ERB.new(File.read(File.dirname(__FILE__) +
|
137
|
-
|
142
|
+
"/email/#{message_type}.text.erb"), nil, '-')
|
138
143
|
|
139
144
|
html_template = ERB.new(File.read(File.dirname(__FILE__) +
|
140
|
-
|
145
|
+
"/email/#{message_type}.html.erb"), nil, '-')
|
146
|
+
|
147
|
+
bnd = binding
|
148
|
+
subject = subject_template.result(bnd).chomp
|
141
149
|
|
142
|
-
|
150
|
+
@logger.debug("preparing email to: #{to}, subject: #{subject}, message-id: #{message_id}")
|
143
151
|
|
144
152
|
mail = Mail.new do
|
145
|
-
from
|
146
|
-
to
|
147
|
-
subject
|
148
|
-
reply_to
|
153
|
+
from from
|
154
|
+
to to
|
155
|
+
subject subject
|
156
|
+
reply_to from
|
157
|
+
message_id message_id
|
149
158
|
|
150
159
|
text_part do
|
151
160
|
body text_template.result(bnd)
|
@@ -29,7 +29,7 @@
|
|
29
29
|
|
30
30
|
<tr>
|
31
31
|
<td><strong>State</strong></td>
|
32
|
-
<td><%= @state.upcase %></td>
|
32
|
+
<td><%= ['ok'].include?(@state) ? @state.upcase : @state.titleize %></td>
|
33
33
|
</tr>
|
34
34
|
|
35
35
|
<tr>
|
@@ -61,7 +61,7 @@
|
|
61
61
|
<% if @last_state %>
|
62
62
|
<tr>
|
63
63
|
<td><strong>Previous State</strong></td>
|
64
|
-
<td><%= @last_state.upcase %></td>
|
64
|
+
<td><%= ['ok'].include?(@last_state) ? @last_state.upcase : @last_state.titleize %></td>
|
65
65
|
</tr>
|
66
66
|
<% end %>
|
67
67
|
|
@@ -75,5 +75,5 @@
|
|
75
75
|
</tbody>
|
76
76
|
</table>
|
77
77
|
|
78
|
-
<p>Cheers
|
79
|
-
|
78
|
+
<p>Cheers,<br/>
|
79
|
+
Flapjack</p>
|
@@ -4,7 +4,7 @@ Monitoring has detected the following:
|
|
4
4
|
|
5
5
|
Entity: <%= @entity_name %>
|
6
6
|
Check: <%= @check %>
|
7
|
-
State: <%= @state.upcase %>
|
7
|
+
State: <%= ['ok'].include?(@state) ? @state.upcase : @state.titleize %>
|
8
8
|
Summary: <%= @summary %>
|
9
9
|
<% if @details -%>
|
10
10
|
Details: <%= @details %>
|
@@ -16,7 +16,7 @@ Time: <%= Time.at(@time.to_i).to_s %>
|
|
16
16
|
Duration: <%= ChronicDuration.output(@duration) %>
|
17
17
|
<% end -%>
|
18
18
|
<% if @last_state -%>
|
19
|
-
Previous State: <%= @last_state.upcase %>
|
19
|
+
Previous State: <%= ['ok'].include?(@last_state) ? @last_state.upcase : @last_state.titleize %>
|
20
20
|
<% end -%>
|
21
21
|
<% if @last_summary -%>
|
22
22
|
Previous Summary: <%= @last_summary %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% case @notification_type -%>
|
2
|
+
<% when "problem" -%>
|
3
|
+
<%= "Problem: " -%>
|
4
|
+
<% when "recovery" -%>
|
5
|
+
<%= "Recovery: " -%>
|
6
|
+
<% when "acknowledgement" -%>
|
7
|
+
<%= "Acknowledgement: " -%>
|
8
|
+
<% when "test" -%>
|
9
|
+
<%= "Test notification: " -%>
|
10
|
+
<% end -%>
|
11
|
+
'<%= @check %>' on <%= @entity_name -%>
|
12
|
+
<% if ! ['acknowledgement', 'test'].include?(@notification_type) -%>
|
13
|
+
is <%= ['ok'].include?(@state) ? @state.upcase : @state.titleize -%>
|
14
|
+
<% end -%>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<style type="text/css" media="screen">
|
2
|
+
#container {
|
3
|
+
text-transform: uppercase;
|
4
|
+
}
|
5
|
+
table {
|
6
|
+
border-collapse: collapse;
|
7
|
+
}
|
8
|
+
table, th, td {
|
9
|
+
border: 1px solid #666;
|
10
|
+
padding: 4px;
|
11
|
+
}
|
12
|
+
</style>
|
13
|
+
|
14
|
+
<p>Hi <%= @contact_first_name %></p>
|
15
|
+
|
16
|
+
<p>You have <%= @rollup_alerts.length %> alerting check<%= @rollup_alerts.length == 1 ? '' : 's' %> as follows:</p>
|
17
|
+
|
18
|
+
<table>
|
19
|
+
<tbody>
|
20
|
+
<tr>
|
21
|
+
<th>Check</th>
|
22
|
+
<th>Entity</th>
|
23
|
+
<th>State</th>
|
24
|
+
<th>Duration</th>
|
25
|
+
</tr>
|
26
|
+
<% @rollup_alerts.sort_by {|entity_check, details| details['duration'] }.each do |rollup_alert| -%>
|
27
|
+
<% r_entity, r_check = rollup_alert[0].split(':', 2) -%>
|
28
|
+
<% state = rollup_alert[1]['state'] -%>
|
29
|
+
<% duration = ChronicDuration.output(rollup_alert[1]['duration']) -%>
|
30
|
+
<tr>
|
31
|
+
<td><%= r_check %></td>
|
32
|
+
<td><%= r_entity %></td>
|
33
|
+
<td><%= ['ok'].include?(state) ? state.upcase : state.titleize %></td>
|
34
|
+
<td><%= duration %></td>
|
35
|
+
</tr>
|
36
|
+
<% end %>
|
37
|
+
</tbody>
|
38
|
+
</table>
|
39
|
+
|
40
|
+
<% if @rollup.downcase == 'recovery' %>
|
41
|
+
<p>As your email summary threshold is <%= @rollup_threshold %>, we're taking your email alerts out of summary mode now. You'll now be emailed individually for each alerting check.</p>
|
42
|
+
<% else %>
|
43
|
+
<p>Your email alerts are being summarised as your email summary threshold is set to <%= @rollup_threshold %>. You'll receive summary emails like this one until your number of alerting checks falls below <%= @rollup_threshold %>.</p>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<p>Cheers,<br/>
|
47
|
+
Flapjack</p>
|
48
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Hi <%= @contact_first_name %>
|
2
|
+
|
3
|
+
You have <%= @rollup_alerts.length %> alerting check<%= @rollup_alerts.length == 1 ? '' : 's' %> as follows:
|
4
|
+
|
5
|
+
<% @rollup_alerts.sort_by {|entity_check, details| details['duration'] }.each do |rollup_alert| -%>
|
6
|
+
<% r_entity, r_check = rollup_alert[0].split(':', 2) -%>
|
7
|
+
<% state = rollup_alert[1]['state'] -%>
|
8
|
+
<% duration = ChronicDuration.output(rollup_alert[1]['duration']) -%>
|
9
|
+
* <%= r_check %> on <%= r_entity %> is <%= ['ok'].include?(state) ? state.upcase : state.titleize %> (<%= duration %>)
|
10
|
+
<% end -%>
|
11
|
+
|
12
|
+
<% if @rollup.downcase == 'recovery' -%>
|
13
|
+
As your email summary threshold is <%= @rollup_threshold %>, we're taking your email alerts out of summary mode now. You'll now be emailed individually for each alerting check.
|
14
|
+
<% else -%>
|
15
|
+
Your email alerts are being summarised as your email summary threshold is set to <%= @rollup_threshold %>. You'll receive summary emails like this one until your number of alerting checks falls below <%= @rollup_threshold %>.
|
16
|
+
<% end -%>
|
17
|
+
|
18
|
+
Cheers,
|
19
|
+
Flapjack
|
20
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<%
|
2
|
+
state_counts = @rollup_alerts.inject({}) do |memo, alert|
|
3
|
+
puts "alert: #{alert.inspect}"
|
4
|
+
memo[alert[1]['state']] = (memo[alert[1]['state']] || 0) + 1
|
5
|
+
memo
|
6
|
+
end
|
7
|
+
states_summary = ['critical', 'warning', 'unknown'].inject([]) do |memo, state|
|
8
|
+
next memo unless state_counts[state]
|
9
|
+
memo << "#{state.titleize}: #{state_counts[state]}"
|
10
|
+
memo
|
11
|
+
end.join(', ')
|
12
|
+
-%>
|
13
|
+
<% case @rollup -%>
|
14
|
+
<% when "problem" -%>
|
15
|
+
<%= "Problem summary: " -%>
|
16
|
+
<% when "recovery" -%>
|
17
|
+
<%= "Problem summaries finishing: " -%>
|
18
|
+
<% end -%>
|
19
|
+
<%= states_summary -%>
|
@@ -127,6 +127,38 @@ module Flapjack
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
def get_check_details(entity_check)
|
131
|
+
sched = entity_check.current_maintenance(:scheduled => true)
|
132
|
+
unsched = entity_check.current_maintenance(:unscheduled => true)
|
133
|
+
out = ''
|
134
|
+
|
135
|
+
if sched.nil? && unsched.nil?
|
136
|
+
out += "Not in scheduled or unscheduled maintenance.\n"
|
137
|
+
else
|
138
|
+
if sched.nil?
|
139
|
+
out += "Not in scheduled maintenance.\n"
|
140
|
+
else
|
141
|
+
start = Time.at(sched[:start_time])
|
142
|
+
finish = Time.at(sched[:start_time] + sched[:duration])
|
143
|
+
remain = time_period_in_words( (finish - current_time).ceil )
|
144
|
+
# TODO a simpler time format?
|
145
|
+
out += "In scheduled maintenance: #{start} -> #{finish} (#{remain} remaining)\n"
|
146
|
+
end
|
147
|
+
|
148
|
+
if unsched.nil?
|
149
|
+
out += "Not in unscheduled maintenance.\n"
|
150
|
+
else
|
151
|
+
start = Time.at(unsched[:start_time])
|
152
|
+
finish = Time.at(unsched[:start_time] + unsched[:duration])
|
153
|
+
remain = time_period_in_words( (finish - current_time).ceil )
|
154
|
+
# TODO a simpler time format?
|
155
|
+
out += "In unscheduled maintenance: #{start} -> #{finish} (#{remain} remaining)\n"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
out
|
160
|
+
end
|
161
|
+
|
130
162
|
def interpreter(command_raw)
|
131
163
|
msg = nil
|
132
164
|
action = nil
|
@@ -190,12 +222,13 @@ module Flapjack
|
|
190
222
|
|
191
223
|
when /^help$/i
|
192
224
|
msg = "commands: \n" +
|
193
|
-
" ACKID <id> <comment> [duration: <time spec>]
|
194
|
-
" find entities matching /pattern
|
195
|
-
"
|
196
|
-
"
|
197
|
-
"
|
198
|
-
"
|
225
|
+
" ACKID <id> <comment> [duration: <time spec>]\n" +
|
226
|
+
" find entities matching /pattern/\n" +
|
227
|
+
" find checks[ matching /pattern/] on (<entity>|entities matching /pattern/)\n" +
|
228
|
+
" test notifications for <entity>[:<check>]\n" +
|
229
|
+
" tell me about <entity>[:<check>]\n" +
|
230
|
+
" identify\n" +
|
231
|
+
" help\n"
|
199
232
|
|
200
233
|
when /^identify$/i
|
201
234
|
t = Process.times
|
@@ -230,43 +263,6 @@ module Flapjack
|
|
230
263
|
|
231
264
|
current_time = Time.now
|
232
265
|
|
233
|
-
get_details = proc {|entity_check|
|
234
|
-
sched = entity_check.current_maintenance(:scheduled => true)
|
235
|
-
unsched = entity_check.current_maintenance(:unscheduled => true)
|
236
|
-
out = ''
|
237
|
-
|
238
|
-
if check_name.nil?
|
239
|
-
check = entity_check.check
|
240
|
-
out += "---\n#{entity_name}:#{check}\n"
|
241
|
-
end
|
242
|
-
|
243
|
-
if sched.nil? && unsched.nil?
|
244
|
-
out += "Not in scheduled or unscheduled maintenance.\n"
|
245
|
-
else
|
246
|
-
if sched.nil?
|
247
|
-
out += "Not in scheduled maintenance.\n"
|
248
|
-
else
|
249
|
-
start = Time.at(sched[:start_time])
|
250
|
-
finish = Time.at(sched[:start_time] + sched[:duration])
|
251
|
-
remain = time_period_in_words( (finish - current_time).ceil )
|
252
|
-
# TODO a simpler time format?
|
253
|
-
out += "In scheduled maintenance: #{start} -> #{finish} (#{remain} remaining)\n"
|
254
|
-
end
|
255
|
-
|
256
|
-
if unsched.nil?
|
257
|
-
out += "Not in unscheduled maintenance.\n"
|
258
|
-
else
|
259
|
-
start = Time.at(unsched[:start_time])
|
260
|
-
finish = Time.at(unsched[:start_time] + unsched[:duration])
|
261
|
-
remain = time_period_in_words( (finish - current_time).ceil )
|
262
|
-
# TODO a simpler time format?
|
263
|
-
out += "In unscheduled maintenance: #{start} -> #{finish} (#{remain} remaining)\n"
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
out
|
268
|
-
}
|
269
|
-
|
270
266
|
check_names = check_name.nil? ? entity.check_list.sort : [check_name]
|
271
267
|
|
272
268
|
if check_names.empty?
|
@@ -275,15 +271,69 @@ module Flapjack
|
|
275
271
|
check_names.each do |check|
|
276
272
|
entity_check = Flapjack::Data::EntityCheck.for_entity(entity, check, :redis => @redis)
|
277
273
|
next if entity_check.nil?
|
278
|
-
msg +=
|
274
|
+
msg += "---\n#{entity_name}:#{check}\n" if check_name.nil?
|
275
|
+
msg += get_check_details(entity_check)
|
279
276
|
end
|
280
277
|
end
|
281
278
|
else
|
282
279
|
msg = "hmmm, I can't see #{entity_name} in my systems"
|
283
280
|
end
|
284
281
|
|
285
|
-
when /^(find )?entities matching\s+\/(
|
286
|
-
|
282
|
+
when /^(?:find )?checks(?:\s+matching\s+\/(.+)\/)?\s+on\s+(?:entities matching\s+\/(.+)\/|([a-z0-9\-\.]+))/i
|
283
|
+
check_pattern = $1 ? $1.chomp.strip : nil
|
284
|
+
entity_pattern = $2 ? $2.chomp.strip : nil
|
285
|
+
entity_name = $3
|
286
|
+
|
287
|
+
entity_names = if entity_name
|
288
|
+
[entity_name]
|
289
|
+
elsif entity_pattern
|
290
|
+
Flapjack::Data::Entity.find_all_name_matching(entity_pattern, :redis => @redis)
|
291
|
+
else
|
292
|
+
[]
|
293
|
+
end
|
294
|
+
|
295
|
+
msg = ""
|
296
|
+
|
297
|
+
# hash with entity => check_list, filtered by pattern if required
|
298
|
+
entities = entity_names.map {|name|
|
299
|
+
Flapjack::Data::Entity.find_by_name(name, :redis => @redis)
|
300
|
+
}.compact.inject({}) {|memo, entity|
|
301
|
+
memo[entity] = entity.check_list.select {|check_name|
|
302
|
+
!check_pattern || (check_name =~ /#{check_pattern}/i)
|
303
|
+
}
|
304
|
+
memo
|
305
|
+
}
|
306
|
+
|
307
|
+
report_entities = proc {|ents|
|
308
|
+
ents.inject('') do |memo, (entity, check_list)|
|
309
|
+
if check_list.empty?
|
310
|
+
memo += "Entity: #{entity.name} has no checks\n"
|
311
|
+
else
|
312
|
+
memo += "Entity: #{entity.name}\nChecks: #{check_list.join(', ')}\n"
|
313
|
+
end
|
314
|
+
memo += "----\n"
|
315
|
+
memo
|
316
|
+
end
|
317
|
+
}
|
318
|
+
|
319
|
+
case
|
320
|
+
when entity_pattern
|
321
|
+
if entities.empty?
|
322
|
+
msg = "found no entities matching /#{entity_pattern}/"
|
323
|
+
else
|
324
|
+
msg = "found #{entities.size} entities matching /#{entity_pattern}/ ... \n" +
|
325
|
+
report_entities.call(entities)
|
326
|
+
end
|
327
|
+
when entity_name
|
328
|
+
if entities.empty?
|
329
|
+
msg = "found no entity for '#{entity_name}'"
|
330
|
+
else
|
331
|
+
msg = report_entities.call(entities)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
when /^(?:find )?entities matching\s+\/(.+)\//i
|
336
|
+
pattern = $1.chomp.strip
|
287
337
|
entity_list = Flapjack::Data::Entity.find_all_name_matching(pattern, :redis => @redis)
|
288
338
|
|
289
339
|
if entity_list
|
@@ -295,7 +345,7 @@ module Flapjack
|
|
295
345
|
when number_found == 0
|
296
346
|
msg = "found no entities matching /#{pattern}/"
|
297
347
|
when number_found == 1
|
298
|
-
msg = "found
|
348
|
+
msg = "found 1 entity matching /#{pattern}/ ... \n"
|
299
349
|
when number_found > max_showable
|
300
350
|
msg = "showing first #{max_showable} of #{number_found} entities found matching /#{pattern}/\n"
|
301
351
|
else
|