flapjack 0.6.43 → 0.6.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. data/bin/flapjack +4 -2
  2. data/bin/flapjack-nagios-receiver +4 -1
  3. data/bin/flapjack-populator +4 -1
  4. data/etc/flapjack_config.yaml.example +111 -106
  5. data/features/steps/notifications_steps.rb +6 -6
  6. data/lib/flapjack/configuration.rb +76 -24
  7. data/lib/flapjack/coordinator.rb +27 -44
  8. data/lib/flapjack/data/entity.rb +28 -7
  9. data/lib/flapjack/data/entity_check.rb +18 -20
  10. data/lib/flapjack/executive.rb +5 -4
  11. data/lib/flapjack/gateways/api.rb +391 -0
  12. data/lib/flapjack/gateways/api/entity_check_presenter.rb +185 -0
  13. data/lib/flapjack/gateways/api/entity_presenter.rb +70 -0
  14. data/lib/flapjack/gateways/base.rb +38 -0
  15. data/lib/flapjack/{notification → gateways}/email.rb +4 -5
  16. data/lib/flapjack/{notification → gateways}/email/alert.html.haml +0 -0
  17. data/lib/flapjack/{notification → gateways}/email/alert.text.erb +0 -0
  18. data/lib/flapjack/gateways/jabber.rb +387 -0
  19. data/lib/flapjack/gateways/oobetet.rb +241 -0
  20. data/lib/flapjack/gateways/pagerduty.rb +247 -0
  21. data/lib/flapjack/{notification → gateways}/sms.rb +5 -6
  22. data/lib/flapjack/{notification → gateways}/sms/messagenet.rb +1 -1
  23. data/lib/flapjack/gateways/web.rb +293 -0
  24. data/lib/flapjack/{web → gateways/web}/views/_css.haml +0 -0
  25. data/lib/flapjack/{web → gateways/web}/views/_nav.haml +0 -0
  26. data/lib/flapjack/{web → gateways/web}/views/check.haml +0 -0
  27. data/lib/flapjack/{web → gateways/web}/views/contact.haml +0 -0
  28. data/lib/flapjack/{web → gateways/web}/views/contacts.haml +0 -0
  29. data/lib/flapjack/{web → gateways/web}/views/index.haml +0 -0
  30. data/lib/flapjack/{web → gateways/web}/views/self_stats.haml +0 -0
  31. data/lib/flapjack/pikelet.rb +0 -23
  32. data/lib/flapjack/version.rb +1 -1
  33. data/spec/lib/flapjack/coordinator_spec.rb +56 -36
  34. data/spec/lib/flapjack/data/entity_spec.rb +53 -4
  35. data/spec/lib/flapjack/{api → gateways/api}/entity_check_presenter_spec.rb +10 -13
  36. data/spec/lib/flapjack/{api → gateways/api}/entity_presenter_spec.rb +10 -10
  37. data/spec/lib/flapjack/{api_spec.rb → gateways/api_spec.rb} +14 -14
  38. data/spec/lib/flapjack/gateways/email_spec.rb +6 -0
  39. data/spec/lib/flapjack/{jabber_spec.rb → gateways/jabber_spec.rb} +9 -9
  40. data/spec/lib/flapjack/{oobetet_spec.rb → gateways/oobetet_spec.rb} +10 -10
  41. data/spec/lib/flapjack/{pagerduty_spec.rb → gateways/pagerduty_spec.rb} +11 -11
  42. data/spec/lib/flapjack/gateways/sms_spec.rb +6 -0
  43. data/spec/lib/flapjack/{web_spec.rb → gateways/web_spec.rb} +4 -4
  44. metadata +46 -79
  45. data/bin/install-flapjack-systemwide +0 -58
  46. data/features/steps/flapjack-importer_steps.rb +0 -109
  47. data/features/steps/flapjack-worker_steps.rb +0 -68
  48. data/lib/flapjack/api.rb +0 -388
  49. data/lib/flapjack/api/entity_check_presenter.rb +0 -181
  50. data/lib/flapjack/api/entity_presenter.rb +0 -66
  51. data/lib/flapjack/cli/worker_manager.rb +0 -46
  52. data/lib/flapjack/inifile.rb +0 -44
  53. data/lib/flapjack/jabber.rb +0 -383
  54. data/lib/flapjack/notifier_engine.rb +0 -40
  55. data/lib/flapjack/notifiers/mailer/init.rb +0 -3
  56. data/lib/flapjack/notifiers/mailer/mailer.rb +0 -51
  57. data/lib/flapjack/notifiers/xmpp/init.rb +0 -3
  58. data/lib/flapjack/notifiers/xmpp/xmpp.rb +0 -46
  59. data/lib/flapjack/oobetet.rb +0 -240
  60. data/lib/flapjack/pagerduty.rb +0 -242
  61. data/lib/flapjack/web.rb +0 -286
  62. data/spec.old/check_sandbox/echo +0 -3
  63. data/spec.old/check_sandbox/sandboxed_check +0 -5
  64. data/spec.old/configs/flapjack-notifier-couchdb.ini +0 -25
  65. data/spec.old/configs/flapjack-notifier.ini +0 -39
  66. data/spec.old/configs/recipients.ini +0 -14
  67. data/spec.old/helpers.rb +0 -15
  68. data/spec.old/inifile_spec.rb +0 -66
  69. data/spec.old/mock-notifiers/mock/init.rb +0 -3
  70. data/spec.old/mock-notifiers/mock/mock.rb +0 -19
  71. data/spec.old/notifier-directories/spoons/testmailer/init.rb +0 -20
  72. data/spec.old/notifier_application_spec.rb +0 -222
  73. data/spec.old/notifier_filters_spec.rb +0 -52
  74. data/spec.old/notifier_options_multiplexer_spec.rb +0 -71
  75. data/spec.old/notifier_options_spec.rb +0 -115
  76. data/spec.old/notifier_spec.rb +0 -57
  77. data/spec.old/notifiers/mailer_spec.rb +0 -36
  78. data/spec.old/notifiers/xmpp_spec.rb +0 -36
  79. data/spec.old/persistence/datamapper_spec.rb +0 -74
  80. data/spec.old/persistence/mock_persistence_backend.rb +0 -26
  81. data/spec.old/simple.ini +0 -6
  82. data/spec.old/spec.opts +0 -4
  83. data/spec.old/test-filters/blocker.rb +0 -13
  84. data/spec.old/test-filters/mock.rb +0 -13
  85. data/spec.old/transports/beanstalkd_spec.rb +0 -44
  86. data/spec.old/transports/mock_transport.rb +0 -58
  87. data/spec.old/worker_application_spec.rb +0 -62
  88. data/spec.old/worker_options_spec.rb +0 -83
  89. data/spec/lib/flapjack/notification/email_spec.rb +0 -6
  90. data/spec/lib/flapjack/notification/sms_spec.rb +0 -6
@@ -1,68 +0,0 @@
1
- Given /^beanstalkd is not running$/ do
2
- if @beanstalk
3
- Process.kill("KILL", @beanstalk.pid)
4
- end
5
- end
6
-
7
- Then /^I should see "([^"]*)" running$/ do |command|
8
- instance_variable_name = "@" + command.split("-")[1]
9
- pipe = instance_variable_get(instance_variable_name)
10
- pipe.should_not be_nil
11
- `ps -p #{pipe.pid}`.split("\n").size.should == 2
12
- end
13
-
14
- When /^I background run "flapjack-worker"$/ do
15
- @root = Pathname.new(File.dirname(__FILE__)).parent.parent.expand_path
16
- bin_path = @root.join('bin')
17
- command = "ruby -rubygems #{bin_path}/flapjack-worker 2>&1"
18
-
19
- @worker = spawn_daemon(command)
20
-
21
- sleep 1
22
- end
23
-
24
- Then /^I should see "([^"]*)" in the "([^"]*)" output$/ do |string, command|
25
- instance_variable_name = "@" + command.split("-")[1]
26
- pipe = instance_variable_get(instance_variable_name)
27
- pipe.should_not be_nil
28
-
29
- @output = read_until_timeout(pipe, 4)
30
- @output.grep(/#{string}/).size.should > 0
31
- end
32
-
33
- Then /^I should not see "([^"]*)" in the "([^"]*)" output$/ do |string, command|
34
- instance_variable_name = "@" + command.split("-")[1]
35
- pipe = instance_variable_get(instance_variable_name)
36
- pipe.should_not be_nil
37
-
38
- @output = read_until_timeout(pipe, 4)
39
- @output.grep(/#{string}/).size.should == 0
40
- end
41
-
42
- When /^beanstalkd is killed$/ do
43
- Given "beanstalkd is not running"
44
- end
45
-
46
- Then /^show me the output from "([^"]*)"$/ do |command|
47
- instance_variable_name = "@" + command.split("-")[1]
48
- pipe = instance_variable_get(instance_variable_name)
49
- pipe.should_not be_nil
50
-
51
- @output = read_until_timeout(pipe, 5)
52
- puts @output
53
- end
54
-
55
- When /^I sleep "(\d+)" seconds$/ do |time|
56
- sleep(time.to_i)
57
- end
58
-
59
- When /^I insert a check onto the beanstalk$/ do
60
- @queue = Beanstalk::Connection.new('localhost:11300', 'checks')
61
-
62
-
63
- pending # express the regexp above with the code you wish you had
64
- end
65
-
66
- Then /^I should see a job on the "([^"]*)" beanstalk queue$/ do |arg1|
67
- pending # express the regexp above with the code you wish you had
68
- end
data/lib/flapjack/api.rb DELETED
@@ -1,388 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # A HTTP-based API server, which provides queries to determine the status of
4
- # entities and the checks that are reported against them.
5
- #
6
- # There's a matching flapjack-diner gem at https://github.com/flpjck/flapjack-diner
7
- # which consumes data from this API.
8
-
9
- require 'time'
10
-
11
- require 'rack/fiber_pool'
12
- require 'sinatra/base'
13
-
14
- require 'flapjack/pikelet'
15
- require 'flapjack/redis_pool'
16
-
17
- require 'flapjack/api/entity_presenter'
18
-
19
- require 'async-rack'
20
- require 'flapjack/rack_logger'
21
-
22
- require 'flapjack/data/contact'
23
- require 'flapjack/data/entity'
24
- require 'flapjack/data/entity_check'
25
-
26
- # from https://github.com/sinatra/sinatra/issues/501
27
- # TODO move to its own file
28
- module Rack
29
- class JsonParamsParser < Struct.new(:app)
30
- def call(env)
31
- if env['rack.input'] and not input_parsed?(env) and type_match?(env)
32
- env['rack.request.form_input'] = env['rack.input']
33
- data = env['rack.input'].read
34
- env['rack.request.form_hash'] = data.empty?? {} : JSON.parse(data)
35
- end
36
- app.call(env)
37
- end
38
-
39
- def input_parsed? env
40
- env['rack.request.form_input'].eql? env['rack.input']
41
- end
42
-
43
- def type_match? env
44
- type = env['CONTENT_TYPE'] and
45
- type.split(/\s*[;,]\s*/, 2).first.downcase == 'application/json'
46
- end
47
- end
48
- end
49
-
50
- module Flapjack
51
-
52
- class API < Sinatra::Base
53
-
54
- set :show_exceptions, false
55
-
56
- if defined?(FLAPJACK_ENV) && 'test'.eql?(FLAPJACK_ENV)
57
- # expose test errors properly
58
- set :raise_errors, true
59
- else
60
- # doesn't work with Rack::Test unless we wrap tests in EM.synchrony blocks
61
- rescue_exception = Proc.new { |env, exception|
62
- logger.error exception.message
63
- logger.error exception.backtrace.join("\n")
64
- [503, {}, {:errors => [exception.message]}.to_json]
65
- }
66
-
67
- use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
68
- end
69
- use Rack::MethodOverride
70
- use Rack::JsonParamsParser
71
-
72
- class << self
73
- include Flapjack::ThinPikelet
74
-
75
- attr_accessor :redis
76
-
77
- alias_method :thin_bootstrap, :bootstrap
78
- alias_method :thin_cleanup, :cleanup
79
-
80
- def bootstrap(opts = {})
81
- thin_bootstrap(opts)
82
- @redis = Flapjack::RedisPool.new(:config => opts[:redis_config], :size => 1)
83
-
84
- if config && config['access_log']
85
- access_logger = Flapjack::RackLogger.new(config['access_log'])
86
- use Rack::CommonLogger, access_logger
87
- end
88
- end
89
-
90
- def cleanup
91
- @redis.empty! if @redis
92
- thin_cleanup
93
- end
94
-
95
- end
96
-
97
- def redis
98
- self.class.instance_variable_get('@redis')
99
- end
100
-
101
- def logger
102
- self.class.instance_variable_get('@logger')
103
- end
104
-
105
- get '/entities' do
106
- content_type :json
107
- ret = Flapjack::Data::Entity.all(:redis => redis).sort_by(&:name).collect {|e|
108
- {'id' => e.id, 'name' => e.name,
109
- 'checks' => e.check_list.sort.collect {|c|
110
- entity_check_status(e, c)
111
- }
112
- }
113
- }
114
- ret.to_json
115
- end
116
-
117
- get '/checks/:entity' do
118
- content_type :json
119
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
120
- if entity.nil?
121
- status 404
122
- return
123
- end
124
- entity.check_list.to_json
125
- end
126
-
127
- get %r{/status/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
128
- content_type :json
129
-
130
- entity_name = params[:captures][0]
131
- check = params[:captures][1]
132
-
133
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
134
- if entity.nil?
135
- status 404
136
- return
137
- end
138
-
139
- ret = if check
140
- entity_check_status(entity, check)
141
- else
142
- entity.check_list.sort.collect {|c|
143
- entity_check_status(entity, c)
144
- }
145
- end
146
- ret.to_json
147
- end
148
-
149
- # the first capture group in the regex checks for acceptable
150
- # characters in a domain name -- this will also match strings
151
- # that aren't acceptable domain names as well, of course.
152
- get %r{/outages/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
153
- content_type :json
154
-
155
- entity_name = params[:captures][0]
156
- check = params[:captures][1]
157
-
158
- entity = entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
159
- if entity.nil?
160
- status 404
161
- return
162
- end
163
-
164
- start_time = validate_and_parsetime(params[:start_time])
165
- end_time = validate_and_parsetime(params[:end_time])
166
-
167
- presenter = if check
168
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
169
- check, :redis => redis)
170
- Flapjack::API::EntityCheckPresenter.new(entity_check)
171
- else
172
- Flapjack::API::EntityPresenter.new(entity, :redis => redis)
173
- end
174
-
175
- presenter.outages(start_time, end_time).to_json
176
- end
177
-
178
- get %r{/unscheduled_maintenances/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
179
- content_type :json
180
-
181
- entity_name = params[:captures][0]
182
- check = params[:captures][1]
183
-
184
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
185
- if entity.nil?
186
- status 404
187
- return
188
- end
189
-
190
- start_time = validate_and_parsetime(params[:start_time])
191
- end_time = validate_and_parsetime(params[:end_time])
192
-
193
- presenter = if check
194
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
195
- check, :redis => redis)
196
- Flapjack::API::EntityCheckPresenter.new(entity_check)
197
- else
198
- Flapjack::API::EntityPresenter.new(entity, :redis => redis)
199
- end
200
-
201
- presenter.unscheduled_maintenance(start_time, end_time).to_json
202
- end
203
-
204
- get %r{/scheduled_maintenances/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
205
- content_type :json
206
-
207
- entity_name = params[:captures][0]
208
- check = params[:captures][1]
209
-
210
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
211
- if entity.nil?
212
- status 404
213
- return
214
- end
215
-
216
- start_time = validate_and_parsetime(params[:start_time])
217
- end_time = validate_and_parsetime(params[:end_time])
218
-
219
- presenter = if check
220
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
221
- check, :redis => redis)
222
- Flapjack::API::EntityCheckPresenter.new(entity_check)
223
- else
224
- Flapjack::API::EntityPresenter.new(entity, :redis => redis)
225
- end
226
- presenter.scheduled_maintenance(start_time, end_time).to_json
227
- end
228
-
229
- get %r{/downtime/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
230
- content_type :json
231
-
232
- entity_name = params[:captures][0]
233
- check = params[:captures][1]
234
-
235
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
236
- if entity.nil?
237
- status 404
238
- return
239
- end
240
-
241
- start_time = validate_and_parsetime(params[:start_time])
242
- end_time = validate_and_parsetime(params[:end_time])
243
-
244
- presenter = if check
245
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
246
- check, :redis => redis)
247
- Flapjack::API::EntityCheckPresenter.new(entity_check)
248
- else
249
- Flapjack::API::EntityPresenter.new(entity, :redis => redis)
250
- end
251
-
252
- presenter.downtime(start_time, end_time).to_json
253
- end
254
-
255
- # create a scheduled maintenance period for a service on an entity
256
- post '/scheduled_maintenances/:entity/:check' do
257
- content_type :json
258
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
259
- if entity.nil?
260
- status 404
261
- return
262
- end
263
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
264
- params[:check], :redis => redis)
265
- entity_check.create_scheduled_maintenance(:start_time => params[:start_time],
266
- :duration => params[:duration], :summary => params[:summary])
267
- status 204
268
- end
269
-
270
- # create an acknowledgement for a service on an entity
271
- # NB currently, this does not acknowledge a specific failure event, just
272
- # the entity-check as a whole
273
- post '/acknowledgements/:entity/:check' do
274
- content_type :json
275
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
276
- if entity.nil?
277
- status 404
278
- return
279
- end
280
-
281
- dur = params[:duration] ? params[:duration].to_i : nil
282
- duration = (dur.nil? || (dur <= 0)) ? (4 * 60 * 60) : dur
283
-
284
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
285
- params[:check], :redis => redis)
286
- entity_check.create_acknowledgement('summary' => params[:summary],
287
- 'duration' => duration)
288
- status 204
289
- end
290
-
291
- post '/test_notifications/:entity/:check' do
292
- content_type :json
293
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
294
- if entity.nil?
295
- status 404
296
- return
297
- end
298
-
299
- summary = params[:summary] || "Testing notifications to all contacts interested in entity #{entity.name}"
300
-
301
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
302
- params[:check], :redis => redis)
303
- entity_check.test_notifications('summary' => summary)
304
- status 204
305
- end
306
-
307
- post '/entities' do
308
- pass unless 'application/json'.eql?(request.content_type)
309
- content_type :json
310
-
311
- errors = []
312
- ret = nil
313
-
314
- entities = params[:entities]
315
- if entities && entities.is_a?(Enumerable) && entities.any? {|e| !e['id'].nil?}
316
- entities.each do |entity|
317
- unless entity['id']
318
- errors << "Entity not imported as it has no id: #{entity.inspect}"
319
- next
320
- end
321
- Flapjack::Data::Entity.add(entity, :redis => redis)
322
- end
323
- ret = 200
324
- else
325
- ret = 403
326
- errors << "No valid entities were submitted"
327
- end
328
- errors.empty? ? ret : [ret, {}, {:errors => [errors]}.to_json]
329
- end
330
-
331
- post '/contacts' do
332
- pass unless 'application/json'.eql?(request.content_type)
333
- content_type :json
334
-
335
- errors = []
336
- ret = nil
337
-
338
- contacts = params[:contacts]
339
- if contacts && contacts.is_a?(Enumerable) && contacts.any? {|c| !c['id'].nil?}
340
- Flapjack::Data::Contact.delete_all(:redis => redis)
341
- contacts.each do |contact|
342
- unless contact['id']
343
- logger.warn "Contact not imported as it has no id: #{contact.inspect}"
344
- next
345
- end
346
- Flapjack::Data::Contact.add(contact, :redis => redis)
347
- end
348
- ret = 200
349
- else
350
- ret = 403
351
- errors << "No valid contacts were submitted"
352
- end
353
- errors.empty? ? ret : [ret, {}, {:errors => [errors]}.to_json]
354
- end
355
-
356
- not_found do
357
- [404, {}, {:errors => ["Not found"]}.to_json]
358
- end
359
-
360
- private
361
-
362
- def entity_check_status(entity, check)
363
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
364
- check, :redis => redis)
365
- return if entity_check.nil?
366
- { 'name' => check,
367
- 'state' => entity_check.state,
368
- 'in_unscheduled_maintenance' => entity_check.in_unscheduled_maintenance?,
369
- 'in_scheduled_maintenance' => entity_check.in_scheduled_maintenance?,
370
- 'last_update' => entity_check.last_update,
371
- 'last_problem_notification' => entity_check.last_problem_notification,
372
- 'last_recovery_notification' => entity_check.last_recovery_notification,
373
- 'last_acknowledgement_notification' => entity_check.last_acknowledgement_notification
374
- }
375
- end
376
-
377
- # NB: casts to UTC before converting to a timestamp
378
- def validate_and_parsetime(value)
379
- return unless value
380
- Time.iso8601(value).getutc.to_i
381
- rescue ArgumentError => e
382
- logger.error "Couldn't parse time from '#{value}'"
383
- nil
384
- end
385
-
386
- end
387
-
388
- end