flapjack 0.9.6 → 1.0.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +6 -0
- data/.travis.yml +20 -16
- data/CHANGELOG.md +11 -25
- data/Dockerfile +8 -0
- data/Gemfile +2 -5
- data/bin/flapjack +24 -213
- data/etc/flapjack_config.yaml.example +6 -30
- data/features/cli.feature +16 -14
- data/features/cli_flapjack-feed-events.feature +12 -13
- data/features/cli_flapjack-nagios-receiver.feature +14 -15
- data/features/cli_flapjack-populator.feature +16 -15
- data/features/cli_flapper.feature +12 -12
- data/features/cli_receive-events.feature +6 -5
- data/features/cli_simulate-failed-check.feature +7 -6
- data/features/steps/cli_steps.rb +2 -2
- data/features/support/env.rb +1 -0
- data/flapjack.gemspec +1 -0
- data/lib/flapjack/cli/flapper.rb +200 -0
- data/lib/flapjack/cli/import.rb +102 -0
- data/lib/flapjack/cli/receiver.rb +656 -0
- data/lib/flapjack/cli/server.rb +256 -0
- data/lib/flapjack/cli/simulate.rb +180 -0
- data/lib/flapjack/configuration.rb +2 -0
- data/lib/flapjack/data/entity_check.rb +5 -22
- data/lib/flapjack/data/event.rb +7 -12
- data/lib/flapjack/gateways/email.rb +4 -1
- data/lib/flapjack/gateways/jabber.rb +12 -36
- data/lib/flapjack/gateways/jsonapi/check_presenter.rb +6 -6
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +5 -3
- data/lib/flapjack/gateways/pagerduty.rb +1 -1
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
- data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
- data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
- data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
- data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
- data/lib/flapjack/gateways/web/views/check.html.erb +7 -7
- data/lib/flapjack/gateways/web/views/checks.html.erb +2 -3
- data/lib/flapjack/gateways/web/views/contact.html.erb +4 -4
- data/lib/flapjack/gateways/web/views/contacts.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/entity.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/layout.erb +10 -10
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +1 -1
- data/lib/flapjack/gateways/web.rb +36 -7
- data/lib/flapjack/pikelet.rb +0 -2
- data/lib/flapjack/processor.rb +3 -1
- data/lib/flapjack/redis_pool.rb +2 -6
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +3 -3
- data/spec/lib/flapjack/data/entity_check_spec.rb +2 -6
- data/spec/lib/flapjack/data/event_spec.rb +0 -31
- data/spec/lib/flapjack/gateways/email_spec.rb +109 -0
- data/spec/lib/flapjack/gateways/jabber_spec.rb +18 -16
- data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +12 -24
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +2 -0
- data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +2 -0
- data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +2 -0
- data/spec/lib/flapjack/gateways/web_spec.rb +194 -145
- data/spec/lib/flapjack/redis_pool_spec.rb +0 -1
- data/spec/support/profile_all_formatter.rb +44 -0
- data/spec/support/uncolored_doc_formatter.rb +9 -0
- data/tasks/benchmarks.rake +0 -4
- metadata +28 -38
- data/.ruby-version +0 -1
- data/Gemfile-ruby1.9 +0 -28
- data/Gemfile-ruby1.9.lock +0 -227
- data/bin/flapjack-feed-events +0 -124
- data/bin/flapjack-nagios-receiver +0 -246
- data/bin/flapjack-nsca-receiver +0 -246
- data/bin/flapjack-populator +0 -132
- data/bin/flapper +0 -152
- data/bin/receive-events +0 -179
- data/bin/simulate-failed-check +0 -151
- data/lib/flapjack/data/migration.rb +0 -36
- data/lib/flapjack/gateways/api/contact_methods.rb +0 -369
- data/lib/flapjack/gateways/api/entity_check_presenter.rb +0 -218
- data/lib/flapjack/gateways/api/entity_methods.rb +0 -361
- data/lib/flapjack/gateways/api/entity_presenter.rb +0 -75
- data/lib/flapjack/gateways/api/rack/json_params_parser.rb +0 -26
- data/lib/flapjack/gateways/api.rb +0 -124
- data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +0 -772
- data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +0 -211
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +0 -863
- data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +0 -108
- data/spec/lib/flapjack/gateways/api_spec.rb +0 -30
@@ -50,17 +50,9 @@ module Flapjack
|
|
50
50
|
@redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2)
|
51
51
|
|
52
52
|
@logger = opts[:logger]
|
53
|
-
@logger.debug("Jabber Initializing")
|
54
53
|
|
55
54
|
@buffer = []
|
56
55
|
@hostname = Socket.gethostname
|
57
|
-
|
58
|
-
# FIXME: i suspect the following should be in #setup so a config reload updates @identifiers
|
59
|
-
# I moved it here so the rspec passes :-/
|
60
|
-
@alias = @config['alias'] || 'flapjack'
|
61
|
-
@identifiers = ((@config['identifiers'] || []) + [@alias]).uniq
|
62
|
-
@logger.debug("I will respond to the following identifiers: #{@identifiers.join(', ')}")
|
63
|
-
|
64
56
|
super()
|
65
57
|
end
|
66
58
|
|
@@ -73,9 +65,7 @@ module Flapjack
|
|
73
65
|
end
|
74
66
|
|
75
67
|
def setup
|
76
|
-
|
77
|
-
jid += '/' + @hostname unless jid.include?('/')
|
78
|
-
@flapjack_jid = Blather::JID.new(jid)
|
68
|
+
@flapjack_jid = Blather::JID.new((@config['jabberid'] || 'flapjack') + '/' + @hostname)
|
79
69
|
|
80
70
|
super(@flapjack_jid, @config['password'], @config['server'], @config['port'].to_i)
|
81
71
|
|
@@ -90,19 +80,13 @@ module Flapjack
|
|
90
80
|
end
|
91
81
|
end
|
92
82
|
|
93
|
-
|
94
|
-
@logger.debug("identifier: #{identifier}, memo: #{memo}")
|
95
|
-
memo << {:body => /^#{identifier}[:\s]/}
|
96
|
-
memo
|
97
|
-
end
|
98
|
-
@logger.debug("body_matchers: #{body_matchers}")
|
99
|
-
register_handler :message, :groupchat?, body_matchers do |stanza|
|
83
|
+
register_handler :message, :groupchat?, :body => /^#{@config['alias']}:\s+/ do |stanza|
|
100
84
|
EventMachine::Synchrony.next_tick do
|
101
85
|
on_groupchat(stanza)
|
102
86
|
end
|
103
87
|
end
|
104
88
|
|
105
|
-
register_handler :message, :chat
|
89
|
+
register_handler :message, :chat? do |stanza|
|
106
90
|
EventMachine::Synchrony.next_tick do
|
107
91
|
on_chat(stanza)
|
108
92
|
end
|
@@ -127,11 +111,11 @@ module Flapjack
|
|
127
111
|
@logger.info("Joining room #{room}")
|
128
112
|
presence = Blather::Stanza::Presence.new
|
129
113
|
presence.from = @flapjack_jid
|
130
|
-
presence.to = Blather::JID.new("#{room}/#{@alias}")
|
114
|
+
presence.to = Blather::JID.new("#{room}/#{@config['alias']}")
|
131
115
|
presence << "<x xmlns='http://jabber.org/protocol/muc'><history maxstanzas='0'></x>"
|
132
116
|
EventMachine::Synchrony.next_tick do
|
133
117
|
write presence
|
134
|
-
say(room, "flapjack jabber gateway started at #{Time.now}, hello!
|
118
|
+
say(room, "flapjack jabber gateway started at #{Time.now}, hello!", :groupchat)
|
135
119
|
end
|
136
120
|
end
|
137
121
|
end
|
@@ -176,7 +160,7 @@ module Flapjack
|
|
176
160
|
out
|
177
161
|
end
|
178
162
|
|
179
|
-
def interpreter(command_raw,
|
163
|
+
def interpreter(command_raw,from)
|
180
164
|
msg = nil
|
181
165
|
action = nil
|
182
166
|
entity_check = nil
|
@@ -255,8 +239,7 @@ module Flapjack
|
|
255
239
|
t = Process.times
|
256
240
|
fqdn = `/bin/hostname -f`.chomp
|
257
241
|
pid = Process.pid
|
258
|
-
msg = "Flapjack #{Flapjack::VERSION} process #{pid} on #{fqdn}\n" +
|
259
|
-
"Identifiers: #{@identifiers.join(', ')}\n" +
|
242
|
+
msg = "Flapjack #{Flapjack::VERSION} process #{pid} on #{fqdn} \n" +
|
260
243
|
"Boot time: #{@boot_time}\n" +
|
261
244
|
"User CPU Time: #{t.utime}\n" +
|
262
245
|
"System CPU Time: #{t.stime}\n" +
|
@@ -554,23 +537,18 @@ module Flapjack
|
|
554
537
|
return if @should_quit
|
555
538
|
@logger.debug("groupchat message received: #{stanza.inspect}")
|
556
539
|
|
557
|
-
|
558
|
-
|
559
|
-
if stanza.body =~ /^#{identifier}:?\s*(.*)/m
|
560
|
-
the_command = $1
|
561
|
-
@logger.debug("matched identifier: #{identifier}, command: #{the_command.inspect}")
|
562
|
-
break
|
563
|
-
end
|
540
|
+
if stanza.body =~ /^#{@config['alias']}:\s+(.*)/m
|
541
|
+
command = $1
|
564
542
|
end
|
565
543
|
|
566
544
|
from = stanza.from
|
567
545
|
|
568
546
|
begin
|
569
|
-
results = interpreter(
|
547
|
+
results = interpreter(command, from.resource.to_s)
|
570
548
|
msg = results[:msg]
|
571
549
|
action = results[:action]
|
572
550
|
rescue => e
|
573
|
-
@logger.
|
551
|
+
@logger.error("Exception when interpreting command '#{command}' - #{e.class}, #{e.message}")
|
574
552
|
msg = "Oops, something went wrong processing that command (#{e.class}, #{e.message})"
|
575
553
|
end
|
576
554
|
|
@@ -593,10 +571,8 @@ module Flapjack
|
|
593
571
|
command = stanza.body
|
594
572
|
end
|
595
573
|
|
596
|
-
from = stanza.from
|
597
|
-
|
598
574
|
begin
|
599
|
-
results = interpreter(command
|
575
|
+
results = interpreter(command)
|
600
576
|
msg = results[:msg]
|
601
577
|
action = results[:action]
|
602
578
|
rescue => e
|
@@ -81,7 +81,7 @@ module Flapjack
|
|
81
81
|
}
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
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
|
-
|
99
|
+
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
|
-
|
114
|
+
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,7 +120,9 @@ module Flapjack
|
|
120
120
|
#
|
121
121
|
# TODO test performance with larger data sets
|
122
122
|
def downtime(start_time, end_time)
|
123
|
-
|
123
|
+
sched_maintenances = scheduled_maintenance(start_time, end_time)
|
124
|
+
|
125
|
+
outs = outage(start_time, end_time)
|
124
126
|
|
125
127
|
total_secs = {}
|
126
128
|
percentages = {}
|
@@ -137,8 +139,6 @@ module Flapjack
|
|
137
139
|
# We then create two new outage periods to cover the time around
|
138
140
|
# the scheduled maintenance period, and remove the original.
|
139
141
|
|
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,9 +27,11 @@ module Flapjack
|
|
27
27
|
end
|
28
28
|
|
29
29
|
checks = if event_ids.nil?
|
30
|
-
Flapjack::Data::
|
31
|
-
|
32
|
-
|
30
|
+
Flapjack::Data::Entity.all(:redis => redis).collect {|entity|
|
31
|
+
entity.check_list.collect {|check_name|
|
32
|
+
find_entity_check(entity, check_name)
|
33
|
+
}
|
34
|
+
}.flatten(2)
|
33
35
|
elsif !event_ids.empty?
|
34
36
|
event_ids.collect {|event_id| find_entity_check_by_name(*event_id.split(':', 2)) }
|
35
37
|
else
|
@@ -178,7 +178,7 @@ module Flapjack
|
|
178
178
|
def find_pagerduty_acknowledgements
|
179
179
|
@logger.debug("looking for acks in pagerduty for unack'd problems")
|
180
180
|
|
181
|
-
unacknowledged_failing_checks = Flapjack::Data::EntityCheck.unacknowledged_failing(:redis => @redis
|
181
|
+
unacknowledged_failing_checks = Flapjack::Data::EntityCheck.unacknowledged_failing(:redis => @redis)
|
182
182
|
|
183
183
|
@logger.debug "found unacknowledged failing checks as follows: " + unacknowledged_failing_checks.join(', ')
|
184
184
|
|
@@ -187,7 +187,7 @@ Backbone.JSONAPIModel = Backbone.Model.extend({
|
|
187
187
|
this.linked[type].remove(obj);
|
188
188
|
},
|
189
189
|
|
190
|
-
urlRoot: function() { return(flapjack.api_url + this.name); },
|
190
|
+
urlRoot: function() { return(flapjack.api_url + "/" + this.name); },
|
191
191
|
|
192
192
|
// can only be called from inside a 'change' event
|
193
193
|
setDirty: function() {
|
@@ -48,7 +48,7 @@
|
|
48
48
|
|
49
49
|
Contact.List = Backbone.JSONAPICollection.extend({
|
50
50
|
model: Contact.Model,
|
51
|
-
url: function() { return flapjack.api_url + "contacts"; }
|
51
|
+
url: function() { return flapjack.api_url + "/contacts"; }
|
52
52
|
});
|
53
53
|
|
54
54
|
Contact.Views.List = Backbone.View.extend({
|
@@ -518,4 +518,4 @@
|
|
518
518
|
}
|
519
519
|
});
|
520
520
|
|
521
|
-
})(flapjack, flapjack.module("contact"));
|
521
|
+
})(flapjack, flapjack.module("contact"));
|
@@ -22,7 +22,7 @@
|
|
22
22
|
Entity.List = Backbone.JSONAPICollection.extend({
|
23
23
|
model: Entity.Model,
|
24
24
|
comparator: 'name',
|
25
|
-
url: function() { return flapjack.api_url + "entities"; }
|
25
|
+
url: function() { return flapjack.api_url + "/entities"; }
|
26
26
|
});
|
27
27
|
|
28
|
-
})(flapjack, flapjack.module("entity"));
|
28
|
+
})(flapjack, flapjack.module("entity"));
|
@@ -21,9 +21,9 @@
|
|
21
21
|
},
|
22
22
|
sync: function(method, model, options) {
|
23
23
|
if ( method == 'create') {
|
24
|
-
options.url = flapjack.api_url + 'contacts/' + model.contact.get('id') + '/' + this.name;
|
24
|
+
options.url = flapjack.api_url + '/contacts/' + model.contact.get('id') + '/' + this.name;
|
25
25
|
} else {
|
26
|
-
options.url = flapjack.api_url + this.name + '/' + model.contact.get('id') + '_' + model.get('type');
|
26
|
+
options.url = flapjack.api_url + '/' + this.name + '/' + model.contact.get('id') + '_' + model.get('type');
|
27
27
|
}
|
28
28
|
Backbone.JSONAPIModel.prototype.sync(method, model, options);
|
29
29
|
}
|
@@ -33,7 +33,7 @@
|
|
33
33
|
Medium.List = Backbone.JSONAPICollection.extend({
|
34
34
|
model: Medium.Model,
|
35
35
|
comparator: 'type',
|
36
|
-
url: function() { return flapjack.api_url + "media"; }
|
36
|
+
url: function() { return flapjack.api_url + "/media"; }
|
37
37
|
});
|
38
38
|
|
39
|
-
})(flapjack, flapjack.module("medium"));
|
39
|
+
})(flapjack, flapjack.module("medium"));
|
@@ -62,7 +62,7 @@ $(document).ready(function() {
|
|
62
62
|
|
63
63
|
function updateData() {
|
64
64
|
var api_url = $('div#data-api-url').data('api-url');
|
65
|
-
$.get(api_url + 'metrics?filter=event_queue_length', function(json) {
|
65
|
+
$.get(api_url + '/metrics?filter=event_queue_length', function(json) {
|
66
66
|
var d = new Date().getTime();
|
67
67
|
var value = {x: d, y: json.event_queue_length}
|
68
68
|
data[0].values.push(value);
|
@@ -4,7 +4,7 @@
|
|
4
4
|
current_time = Time.now
|
5
5
|
%>
|
6
6
|
<div class="page-header">
|
7
|
-
<% entity_link = "
|
7
|
+
<% entity_link = u(@base_url) + "entity/" << u(@entity) %>
|
8
8
|
<h2><%= h @check %> on <a href="<%= entity_link %>" title="entity summary"><%= h @entity %></a></h2>
|
9
9
|
</div>
|
10
10
|
|
@@ -62,7 +62,7 @@
|
|
62
62
|
<% if @current_unscheduled_maintenance %>
|
63
63
|
<div class="alert alert-warning">
|
64
64
|
|
65
|
-
<form action="
|
65
|
+
<form action="<%= @base_url %>end_unscheduled_maintenance/<%= check_path_escaped %>" method="post" class="form-horizontal" role="form">
|
66
66
|
|
67
67
|
<div class="form-group">
|
68
68
|
<label class="col-md-3 control-label">State</label>
|
@@ -132,7 +132,7 @@
|
|
132
132
|
<div class="alert alert-warning">
|
133
133
|
<% action = @current_unscheduled_maintenance ? "Re-acknowledge" : "Acknowledge" %>
|
134
134
|
<h4><%= action %> alert</h4>
|
135
|
-
<form action="
|
135
|
+
<form action="<%= @base_url %>acknowledgements/<%= check_path_escaped %>" method="post" class="form-horizontal">
|
136
136
|
<div class="form-group">
|
137
137
|
<div class="col-sm-12 text-left">
|
138
138
|
<label class="col-sm-3 control-label" for="summary">Summary</label>
|
@@ -307,7 +307,7 @@
|
|
307
307
|
<td>
|
308
308
|
<% if end_time > current_time.to_i %>
|
309
309
|
<% label = (start_time > current_time.to_i) ? 'Delete' : 'End Now' %>
|
310
|
-
<form action="
|
310
|
+
<form action="<%= @base_url %>scheduled_maintenances/<%= check_path_escaped %>" method="post">
|
311
311
|
<input type="hidden" name="_method" value="delete">
|
312
312
|
<input type="hidden" name="start_time" value="<%= start_time %>">
|
313
313
|
<button type="submit" class="btn btn-danger"><%= label %></button>
|
@@ -333,7 +333,7 @@
|
|
333
333
|
<h3 class="panel-title">Add Scheduled Maintenance</h4>
|
334
334
|
</div>
|
335
335
|
<div class="panel-body">
|
336
|
-
<form action="
|
336
|
+
<form action="<%= @base_url %>scheduled_maintenances/<%= check_path_escaped %>" method="post" role="form" class="form-horizontal">
|
337
337
|
|
338
338
|
<div class="form-group">
|
339
339
|
<label class="col-sm-2 control-label" for="start_time">Start time:</label>
|
@@ -394,7 +394,7 @@
|
|
394
394
|
</tr>
|
395
395
|
<% @contacts.sort_by {|c| [c.first_name, c.last_name] }.each do |contact| %>
|
396
396
|
<tr>
|
397
|
-
<td><a href="
|
397
|
+
<td><a href="<%= @base_url %>contacts/<%= contact.id %>" title="contact details"><%= h contact.name %></a></td>
|
398
398
|
<td>
|
399
399
|
<% if contact.media && !contact.media.empty? %>
|
400
400
|
<p><%= h contact.media.keys.collect(&:capitalize).join(", ") %></p>
|
@@ -423,7 +423,7 @@
|
|
423
423
|
<div class="panel-body">
|
424
424
|
<% if @check_enabled %>
|
425
425
|
<h4>Decommission check</h4>
|
426
|
-
<form action="
|
426
|
+
<form action="<%= @base_url %>checks/<%= check_path_escaped %>" method="post" style="display:inline-block" class="pull-right">
|
427
427
|
<input type='hidden' name='_method' value='delete'>
|
428
428
|
<button type='submit' class="btn btn-danger decommission-check">Decommission Check</button>
|
429
429
|
</form>
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<tbody>
|
22
22
|
<% @entities_sorted.each do |entity| %>
|
23
23
|
<% row_entity = nil %>
|
24
|
-
<% entity_link = "
|
24
|
+
<% entity_link = u(@base_url) + "entity/" << u(entity) %>
|
25
25
|
<% @states[entity].each do |check, status, summary, changed, updated, in_unscheduled_outage, in_scheduled_outage, notified| %>
|
26
26
|
<%
|
27
27
|
row_colour = case status
|
@@ -33,8 +33,7 @@
|
|
33
33
|
status
|
34
34
|
end
|
35
35
|
|
36
|
-
check_link = "
|
37
|
-
|
36
|
+
check_link = u(@base_url) + "check?entity=" << u(entity) << "&check=" << u(check)
|
38
37
|
%>
|
39
38
|
<tr class="<%= row_colour %>">
|
40
39
|
<% unless row_entity && entity == row_entity %>
|
@@ -81,9 +81,9 @@
|
|
81
81
|
<td>
|
82
82
|
<% checks.each do |entity_check| %>
|
83
83
|
<% entity, check = entity_check.split(':', 2) %>
|
84
|
-
<% check_link = "<a href=\"
|
84
|
+
<% check_link = "<a href=\"#{u(@base_url)}check?entity=#{u(entity)}&check=#{u(check)}\" title=\"check status\">" +
|
85
85
|
h(check) + "</a>"%>
|
86
|
-
<a href="
|
86
|
+
<a href="<%= @base_url %>entity/<%= u(entity) %>" title="entity status"><%= h entity %></a> ::
|
87
87
|
<%= check_link %> <br />
|
88
88
|
<% end %>
|
89
89
|
</td>
|
@@ -144,10 +144,10 @@
|
|
144
144
|
checks = ec[:checks]
|
145
145
|
%>
|
146
146
|
<tr>
|
147
|
-
<td><a href="
|
147
|
+
<td><a href="<%= @base_url %>entity/<%= u(entity.name) %>" title="entity status"><%= h entity.name %></a></td>
|
148
148
|
<td>
|
149
149
|
<% checks.each do |check| %>
|
150
|
-
<%= "<a href=\"
|
150
|
+
<%= "<a href=\"#{u(@base_url)}check?entity=#{u(entity.name)}&check=#{u(check)}\" title=\"check status\">#{ h check }</a>" %>
|
151
151
|
<% end %>
|
152
152
|
</td>
|
153
153
|
</tr>
|
@@ -14,14 +14,14 @@
|
|
14
14
|
</tr>
|
15
15
|
<% @contacts.sort_by {|c| [c.last_name, c.first_name] }.each do |contact| %>
|
16
16
|
<tr>
|
17
|
-
<td><a href="
|
17
|
+
<td><a href="<%= @base_url %>contacts/<%= contact.id %>" title="contact details"><%= h contact.name %></a></td>
|
18
18
|
<td><%= h contact.email %></td>
|
19
19
|
</tr>
|
20
20
|
<% end %>
|
21
21
|
</table>
|
22
22
|
<% end %>
|
23
23
|
|
24
|
-
<a href="
|
24
|
+
<a href="<%= @base_url %>edit_contacts"/>
|
25
25
|
Edit contacts
|
26
26
|
<span class="label label-danger">beta</span>
|
27
27
|
</a>
|
@@ -36,7 +36,7 @@
|
|
36
36
|
<h4 class="modal-title" id="contactModalLabel"><@- is_new ? 'New' : 'Edit' @> Contact</h4>
|
37
37
|
</div>
|
38
38
|
<div class="modal-body">
|
39
|
-
<form action="
|
39
|
+
<form action="<%= @base_url %>contacts" method="post" role="form" class="form-horizontal">
|
40
40
|
|
41
41
|
<div id="contactDetails">
|
42
42
|
<div class="form-group">
|
@@ -4,5 +4,5 @@
|
|
4
4
|
<h2>Summary</h2>
|
5
5
|
</div> <!-- page header -->
|
6
6
|
|
7
|
-
<h4><a href="
|
8
|
-
<h4><a href="
|
7
|
+
<h4><a href="<% @base_url %>entities_failing" title="failing entities"><%= h @count_failing_entities %></a> out of <a href="<% @base_url %>entities_all" title="all entities"><%= h @count_all_entities %></a> entities have failing checks</h4>
|
8
|
+
<h4><a href="<% @base_url %>checks_failing" title="failing checks"><%= h @count_failing_checks %></a> out of <a href="<% @base_url %>checks_all" title="all checks"><%= h @count_all_checks %></a> checks are failing</h4>
|
@@ -16,7 +16,7 @@
|
|
16
16
|
<head>
|
17
17
|
<title><%= h include_page_title %></title>
|
18
18
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
19
|
-
<link rel="shortcut icon" href="
|
19
|
+
<link rel="shortcut icon" href="<%= @base_url %>img/flapjack-favicon-64-32-24-16.ico"> <!-- thank you http://xiconeditor.com/ -->
|
20
20
|
<%= include_required_css %>
|
21
21
|
<%= include_required_js %>
|
22
22
|
</head>
|
@@ -24,8 +24,8 @@
|
|
24
24
|
<nav class="navbar navbar-default navbar-inverse" role="navigation">
|
25
25
|
|
26
26
|
<div class="navbar-header">
|
27
|
-
<a class="navbar-brand" title="Summary" href="
|
28
|
-
<img alt="Flapjack" class="logo" src="
|
27
|
+
<a class="navbar-brand" title="Summary" href="<%= @base_url %>">
|
28
|
+
<img alt="Flapjack" class="logo" src="<%= @base_url %><%= @logo_image_file ? "img/branding#{@logo_image_ext}" : @default_logo_url %>">
|
29
29
|
</a>
|
30
30
|
</div>
|
31
31
|
|
@@ -33,37 +33,37 @@
|
|
33
33
|
|
34
34
|
<ul class="nav navbar-nav">
|
35
35
|
<li<%= include_active?('') %>>
|
36
|
-
<a title="Summary" href="
|
36
|
+
<a title="Summary" href="<%= @base_url %>">
|
37
37
|
<i class="fa fa-trophy fa-lg"></i>
|
38
38
|
Summary
|
39
39
|
</a>
|
40
40
|
</li>
|
41
41
|
<li<%= include_active?('entities_all') %>>
|
42
|
-
<a title="All Entities" href="
|
42
|
+
<a title="All Entities" href="<%= @base_url %>entities_all">
|
43
43
|
<i class="fa fa-bullseye fa-lg"></i>
|
44
44
|
All Entities
|
45
45
|
</a>
|
46
46
|
</li>
|
47
47
|
<li<%= include_active?('entities_failing') %>>
|
48
|
-
<a title="Failing Entities" href="
|
48
|
+
<a title="Failing Entities" href="<%= @base_url %>entities_failing">
|
49
49
|
<i class="fa fa-bullhorn fa-lg"></i>
|
50
50
|
Failing Entities
|
51
51
|
</a>
|
52
52
|
</li>
|
53
53
|
<li<%= include_active?('checks_all') %>>
|
54
|
-
<a title="All Checks" href="
|
54
|
+
<a title="All Checks" href="<%= @base_url %>checks_all">
|
55
55
|
<i class="fa fa-check-circle-o fa-lg"></i>
|
56
56
|
All Checks
|
57
57
|
</a>
|
58
58
|
</li>
|
59
59
|
<li<%= include_active?('checks_failing') %>>
|
60
|
-
<a title="Failing Checks" href="
|
60
|
+
<a title="Failing Checks" href="<%= @base_url %>checks_failing">
|
61
61
|
<i class="fa fa-times-circle-o fa-lg"></i>
|
62
62
|
Failing Checks
|
63
63
|
</a>
|
64
64
|
</li>
|
65
65
|
<li<%= include_active?('contacts') %>>
|
66
|
-
<a title="Contacts" href="
|
66
|
+
<a title="Contacts" href="<%= @base_url %>contacts">
|
67
67
|
<i class="fa fa-users fa-lg"></i>
|
68
68
|
Contacts
|
69
69
|
</a>
|
@@ -72,7 +72,7 @@
|
|
72
72
|
|
73
73
|
<ul class="nav navbar-nav navbar-right">
|
74
74
|
<li<%= include_active?('self_stats') %>>
|
75
|
-
<a title="Internal Statistics" href="
|
75
|
+
<a title="Internal Statistics" href="<%= @base_url %>self_stats">
|
76
76
|
<i class="fa fa-tachometer fa-lg"></i>
|
77
77
|
Internal Statistics
|
78
78
|
</a>
|
@@ -125,7 +125,7 @@
|
|
125
125
|
</div>
|
126
126
|
|
127
127
|
<p>
|
128
|
-
<a class="btn btn-success" href="
|
128
|
+
<a class="btn btn-success" href="<% @base_url %>self_stats.json">View as JSON</a>
|
129
129
|
Learn how to
|
130
130
|
<a href="https://github.com/flapjack/flapjack/wiki/Gathering-internal-statistics-with-collectd">
|
131
131
|
use these metrics</a>.
|
@@ -67,6 +67,28 @@ module Flapjack
|
|
67
67
|
@logger.error "api_url is not configured, parts of the web interface will be broken"
|
68
68
|
end
|
69
69
|
|
70
|
+
@base_url = @config['base_url']
|
71
|
+
if @base_url
|
72
|
+
@base_url = $1 if @base_url.match(/^(.+\/)$/)
|
73
|
+
else
|
74
|
+
dummy_url = "/"
|
75
|
+
@logger.error "base_url must contain trailing '/', setting it to safe default (#{dummy_url})"
|
76
|
+
@base_url = dummy_url
|
77
|
+
end
|
78
|
+
|
79
|
+
# constants won't be exposed to eRb scope
|
80
|
+
@default_logo_url = "img/flapjack-2013-notext-transparent-300-300.png"
|
81
|
+
@logo_image_file = nil
|
82
|
+
@logo_image_ext = nil
|
83
|
+
|
84
|
+
if logo_image_path = @config['logo_image_path']
|
85
|
+
if File.file?(logo_image_path)
|
86
|
+
@logo_image_file = logo_image_path
|
87
|
+
@logo_image_ext = File.extname(logo_image_path)
|
88
|
+
else
|
89
|
+
@logger.error "logo_image_path '#{logo_image_path}'' does not point to a valid file."
|
90
|
+
end
|
91
|
+
end
|
70
92
|
end
|
71
93
|
end
|
72
94
|
|
@@ -99,8 +121,17 @@ module Flapjack
|
|
99
121
|
self.class.instance_variable_get('@logger')
|
100
122
|
end
|
101
123
|
|
102
|
-
|
103
|
-
self.class.instance_variable_get('@api_url')
|
124
|
+
before do
|
125
|
+
@api_url = self.class.instance_variable_get('@api_url')
|
126
|
+
@base_url = self.class.instance_variable_get('@base_url')
|
127
|
+
@default_logo_url = self.class.instance_variable_get('@default_logo_url')
|
128
|
+
@logo_image_file = self.class.instance_variable_get('@logo_image_file')
|
129
|
+
@logo_image_ext = self.class.instance_variable_get('@logo_image_ext')
|
130
|
+
end
|
131
|
+
|
132
|
+
get '/img/branding.*' do
|
133
|
+
halt(404) unless @logo_image_file && params[:splat].first.eql?(@logo_image_ext[1..-1])
|
134
|
+
send_file(@logo_image_file)
|
104
135
|
end
|
105
136
|
|
106
137
|
get '/' do
|
@@ -313,7 +344,6 @@ module Flapjack
|
|
313
344
|
end
|
314
345
|
|
315
346
|
get '/edit_contacts' do
|
316
|
-
@api_url = api_url
|
317
347
|
erb 'edit_contacts.html'.to_sym
|
318
348
|
end
|
319
349
|
|
@@ -389,7 +419,6 @@ module Flapjack
|
|
389
419
|
def self_stats
|
390
420
|
@fqdn = `/bin/hostname -f`.chomp
|
391
421
|
@pid = Process.pid
|
392
|
-
@api_url = api_url
|
393
422
|
|
394
423
|
@dbsize = redis.dbsize
|
395
424
|
@executive_instances = redis.keys("executive_instance:*").inject({}) do |memo, i|
|
@@ -454,7 +483,7 @@ module Flapjack
|
|
454
483
|
def include_required_js
|
455
484
|
if @required_js
|
456
485
|
@required_js.map { |filename|
|
457
|
-
"<script type='text/javascript' src='#{link_to("
|
486
|
+
"<script type='text/javascript' src='#{link_to("js/#{filename}.js")}'></script>"
|
458
487
|
}.join("\n ")
|
459
488
|
else
|
460
489
|
""
|
@@ -464,7 +493,7 @@ module Flapjack
|
|
464
493
|
def include_required_css
|
465
494
|
if @required_css
|
466
495
|
@required_css.map { |filename|
|
467
|
-
%(<link rel="stylesheet" href="#{link_to("
|
496
|
+
%(<link rel="stylesheet" href="#{link_to("css/#{filename}.css")}" media="screen">)
|
468
497
|
}.join("\n ")
|
469
498
|
else
|
470
499
|
""
|
@@ -475,7 +504,7 @@ module Flapjack
|
|
475
504
|
def link_to(url_fragment, mode=:path_only)
|
476
505
|
case mode
|
477
506
|
when :path_only
|
478
|
-
base =
|
507
|
+
base = @base_url
|
479
508
|
when :full_url
|
480
509
|
if (request.scheme == 'http' && request.port == 80 ||
|
481
510
|
request.scheme == 'https' && request.port == 443)
|
data/lib/flapjack/pikelet.rb
CHANGED
@@ -19,7 +19,6 @@ require 'thin'
|
|
19
19
|
|
20
20
|
require 'flapjack/notifier'
|
21
21
|
require 'flapjack/processor'
|
22
|
-
require 'flapjack/gateways/api'
|
23
22
|
require 'flapjack/gateways/jsonapi'
|
24
23
|
require 'flapjack/gateways/jabber'
|
25
24
|
require 'flapjack/gateways/oobetet'
|
@@ -218,7 +217,6 @@ module Flapjack
|
|
218
217
|
class Thin < Flapjack::Pikelet::Base
|
219
218
|
|
220
219
|
PIKELET_TYPES = {'web' => Flapjack::Gateways::Web,
|
221
|
-
'api' => Flapjack::Gateways::API,
|
222
220
|
'jsonapi' => Flapjack::Gateways::JSONAPI}
|
223
221
|
|
224
222
|
def self.create(type, opts = {})
|
data/lib/flapjack/processor.rb
CHANGED
@@ -38,6 +38,8 @@ module Flapjack
|
|
38
38
|
ncsm_duration_conf = @config['new_check_scheduled_maintenance_duration'] || '100 years'
|
39
39
|
@ncsm_duration = ChronicDuration.parse(ncsm_duration_conf, :keep_zero => true)
|
40
40
|
|
41
|
+
@ncsm_ignore_tags = @config['new_check_scheduled_maintenance_ignore_tags'] || []
|
42
|
+
|
41
43
|
@exit_on_queue_empty = !! @config['exit_on_queue_empty']
|
42
44
|
|
43
45
|
options = { :logger => opts[:logger], :redis => @redis }
|
@@ -208,7 +210,7 @@ module Flapjack
|
|
208
210
|
if previous_state.nil?
|
209
211
|
@logger.info("No previous state for event #{event.id}")
|
210
212
|
|
211
|
-
if @ncsm_duration > 0
|
213
|
+
if @ncsm_duration > 0 && (event.tags & @ncsm_ignore_tags).empty?
|
212
214
|
@logger.info("Setting scheduled maintenance for #{time_period_in_words(@ncsm_duration)}")
|
213
215
|
entity_check.create_scheduled_maintenance(timestamp,
|
214
216
|
@ncsm_duration, :summary => 'Automatically created for new check')
|