flapjack 0.7.2 → 0.7.3

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.
@@ -282,9 +282,8 @@ module Flapjack
282
282
  event, :type => notification_type, :max_notified_severity => max_notified_severity)
283
283
 
284
284
  messages = notification.messages(:contacts => contacts)
285
- messages = apply_notification_rules(messages)
285
+ messages = apply_notification_rules(messages, event.state)
286
286
  enqueue_messages(messages)
287
-
288
287
  end
289
288
 
290
289
  # time restrictions match?
@@ -295,21 +294,20 @@ module Flapjack
295
294
  contact = opts[:contact]
296
295
  return true if rule.time_restrictions.nil? or rule.time_restrictions.empty?
297
296
 
298
- time_zone = contact.timezone(:default => @default_contact_timezone)
299
- usertime = time_zone.now
297
+ timezone = contact.timezone(:default => @default_contact_timezone)
298
+ usertime = timezone.now
300
299
 
301
300
  match = rule.time_restrictions.any? do |tr|
302
- # add contact's timezone to the time restriction hash
303
- tr = Flapjack::Data::NotificationRule.time_restriction_to_ice_cube_hash(tr, time_zone)
304
-
305
- schedule = IceCube::Schedule.from_hash(tr)
306
- schedule.occurring_at?(usertime)
301
+ # add contact's timezone to the time restriction schedule
302
+ schedule = Flapjack::Data::NotificationRule.
303
+ time_restriction_to_icecube_schedule(tr, timezone)
304
+ schedule && schedule.occurring_at?(usertime)
307
305
  end
308
306
  !!match
309
307
  end
310
308
 
311
309
  # delete messages based on entity name(s), tags, severity, time of day
312
- def apply_notification_rules(messages)
310
+ def apply_notification_rules(messages, severity)
313
311
  # first get all rules matching entity and time
314
312
  @logger.debug "apply_notification_rules: got messages with size #{messages.size}"
315
313
 
@@ -342,8 +340,8 @@ module Flapjack
342
340
  end
343
341
  if have_specific
344
342
  # delete the rule for all entities
345
- matchers.map! do |matcher|
346
- matcher.entities.nil? and matcher.entity_tags.nil? ? nil : matcher
343
+ matchers.reject! do |matcher|
344
+ matcher.entities.nil? && matcher.entity_tags.nil?
347
345
  end
348
346
  end
349
347
  end
@@ -352,7 +350,6 @@ module Flapjack
352
350
 
353
351
  # delete media based on blackholes
354
352
  tuple = tuple.find_all do |message, matchers, options|
355
- severity = message.notification.event.state
356
353
  # or use message.notification.contents['state']
357
354
  matchers.none? {|matcher| matcher.blackhole?(severity) }
358
355
  end
@@ -376,13 +373,7 @@ module Flapjack
376
373
  end
377
374
  options[:no_rules_for_contact] ||
378
375
  matchers.any? {|matcher|
379
- mms = matcher.media_for_severity(severity)
380
- unless mms
381
- answer = false
382
- else
383
- answer = mms.include?(message.medium)
384
- end
385
- answer
376
+ (matcher.media_for_severity(severity) || []).include?(message.medium)
386
377
  }
387
378
  end
388
379
 
@@ -27,7 +27,8 @@ module Rack
27
27
  if env['rack.input'] and not input_parsed?(env) and type_match?(env)
28
28
  env['rack.request.form_input'] = env['rack.input']
29
29
  data = env['rack.input'].read
30
- env['rack.request.form_hash'] = data.empty?? {} : JSON.parse(data)
30
+ env['rack.input'].rewind
31
+ env['rack.request.form_hash'] = data.empty? ? {} : JSON.parse(data)
31
32
  end
32
33
  app.call(env)
33
34
  end
@@ -48,6 +49,9 @@ module Flapjack
48
49
  module Gateways
49
50
 
50
51
  class API < Sinatra::Base
52
+
53
+ include Flapjack::Utility
54
+
51
55
  set :show_exceptions, false
52
56
 
53
57
  rescue_exception = Proc.new { |env, exception|
@@ -63,6 +67,9 @@ module Flapjack
63
67
  class << self
64
68
  def start
65
69
  @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1)
70
+
71
+ @logger.info "starting api - class"
72
+
66
73
  if @config && @config['access_log']
67
74
  access_logger = Flapjack::AsyncLogger.new(@config['access_log'])
68
75
  use Flapjack::CommonLogger, access_logger
@@ -92,12 +99,9 @@ module Flapjack
92
99
 
93
100
  get '/checks/:entity' do
94
101
  content_type :json
95
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
96
- if entity.nil?
97
- status 404
98
- return
102
+ find_entity(params[:entity]) do |entity|
103
+ entity.check_list.to_json
99
104
  end
100
- entity.check_list.to_json
101
105
  end
102
106
 
103
107
  get %r{/status/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(.+))?} do
@@ -106,24 +110,17 @@ module Flapjack
106
110
  entity_name = params[:captures][0]
107
111
  check = params[:captures][1]
108
112
 
109
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
110
- if entity.nil?
111
- status 404
112
- return
113
- end
114
-
115
- ret = if check
116
- entity_check_status(entity, check)
117
- else
118
- entity.check_list.sort.collect {|c|
119
- entity_check_status(entity, c)
120
- }
121
- end
122
- if ret.nil?
123
- status 404
124
- return
113
+ find_entity(entity_name) do |entity|
114
+ ret = if check
115
+ entity_check_status(entity, check)
116
+ else
117
+ entity.check_list.sort.collect {|c|
118
+ entity_check_status(entity, c)
119
+ }
120
+ end
121
+ return error(404, "could not find entity check '#{entity_name}:#{check}'") if ret.nil?
122
+ ret.to_json
125
123
  end
126
- ret.to_json
127
124
  end
128
125
 
129
126
  # the first capture group in the regex checks for acceptable
@@ -135,24 +132,12 @@ module Flapjack
135
132
  entity_name = params[:captures][0]
136
133
  check = params[:captures][1]
137
134
 
138
- entity = entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
139
- if entity.nil?
140
- status 404
141
- return
142
- end
143
-
144
135
  start_time = validate_and_parsetime(params[:start_time])
145
136
  end_time = validate_and_parsetime(params[:end_time])
146
137
 
147
- presenter = if check
148
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
149
- check, :redis => redis)
150
- Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check)
151
- else
152
- Flapjack::Gateways::API::EntityPresenter.new(entity, :redis => redis)
138
+ find_api_presenter(entity_name, check) do |presenter|
139
+ presenter.outages(start_time, end_time).to_json
153
140
  end
154
-
155
- presenter.outages(start_time, end_time).to_json
156
141
  end
157
142
 
158
143
  get %r{/unscheduled_maintenances/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
@@ -161,24 +146,12 @@ module Flapjack
161
146
  entity_name = params[:captures][0]
162
147
  check = params[:captures][1]
163
148
 
164
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
165
- if entity.nil?
166
- status 404
167
- return
168
- end
169
-
170
149
  start_time = validate_and_parsetime(params[:start_time])
171
150
  end_time = validate_and_parsetime(params[:end_time])
172
151
 
173
- presenter = if check
174
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
175
- check, :redis => redis)
176
- Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check)
177
- else
178
- Flapjack::Gateways::API::EntityPresenter.new(entity, :redis => redis)
152
+ find_api_presenter(entity_name, check) do |presenter|
153
+ presenter.unscheduled_maintenance(start_time, end_time).to_json
179
154
  end
180
-
181
- presenter.unscheduled_maintenance(start_time, end_time).to_json
182
155
  end
183
156
 
184
157
  get %r{/scheduled_maintenances/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
@@ -187,23 +160,12 @@ module Flapjack
187
160
  entity_name = params[:captures][0]
188
161
  check = params[:captures][1]
189
162
 
190
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
191
- if entity.nil?
192
- status 404
193
- return
194
- end
195
-
196
163
  start_time = validate_and_parsetime(params[:start_time])
197
164
  end_time = validate_and_parsetime(params[:end_time])
198
165
 
199
- presenter = if check
200
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
201
- check, :redis => redis)
202
- Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check)
203
- else
204
- Flapjack::Gateways::API::EntityPresenter.new(entity, :redis => redis)
166
+ find_api_presenter(entity_name, check) do |presenter|
167
+ presenter.scheduled_maintenance(start_time, end_time).to_json
205
168
  end
206
- presenter.scheduled_maintenance(start_time, end_time).to_json
207
169
  end
208
170
 
209
171
  get %r{/downtime/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(\w+))?} do
@@ -212,42 +174,27 @@ module Flapjack
212
174
  entity_name = params[:captures][0]
213
175
  check = params[:captures][1]
214
176
 
215
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
216
- if entity.nil?
217
- status 404
218
- return
219
- end
220
-
221
177
  start_time = validate_and_parsetime(params[:start_time])
222
178
  end_time = validate_and_parsetime(params[:end_time])
223
179
 
224
- presenter = if check
225
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
226
- check, :redis => redis)
227
- Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check)
228
- else
229
- Flapjack::Gateways::API::EntityPresenter.new(entity, :redis => redis)
180
+ find_api_presenter(entity_name, check) do |presenter|
181
+ presenter.downtime(start_time, end_time).to_json
230
182
  end
231
-
232
- presenter.downtime(start_time, end_time).to_json
233
183
  end
234
184
 
235
185
  # create a scheduled maintenance period for a service on an entity
236
186
  post '/scheduled_maintenances/:entity/:check' do
237
187
  content_type :json
238
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
239
- if entity.nil?
240
- status 404
241
- return
242
- end
243
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
244
- params[:check], :redis => redis)
245
188
 
246
189
  start_time = validate_and_parsetime(params[:start_time])
247
190
 
248
- entity_check.create_scheduled_maintenance(:start_time => start_time,
249
- :duration => params[:duration].to_i, :summary => params[:summary])
250
- status 204
191
+ find_entity(params[:entity]) do |entity|
192
+ find_entity_check(entity, params[:check]) do |entity_check|
193
+ entity_check.create_scheduled_maintenance(:start_time => start_time,
194
+ :duration => params[:duration].to_i, :summary => params[:summary])
195
+ status 204
196
+ end
197
+ end
251
198
  end
252
199
 
253
200
  # create an acknowledgement for a service on an entity
@@ -255,36 +202,28 @@ module Flapjack
255
202
  # the entity-check as a whole
256
203
  post '/acknowledgements/:entity/:check' do
257
204
  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
205
 
264
206
  dur = params[:duration] ? params[:duration].to_i : nil
265
207
  duration = (dur.nil? || (dur <= 0)) ? (4 * 60 * 60) : dur
266
208
 
267
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
268
- params[:check], :redis => redis)
269
- entity_check.create_acknowledgement('summary' => params[:summary],
270
- 'duration' => duration)
271
- status 204
209
+ find_entity(params[:entity]) do |entity|
210
+ find_entity_check(entity, params[:check]) do |entity_check|
211
+ entity_check.create_acknowledgement('summary' => params[:summary],
212
+ 'duration' => duration)
213
+ status 204
214
+ end
215
+ end
272
216
  end
273
217
 
274
218
  post '/test_notifications/:entity/:check' do
275
219
  content_type :json
276
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
277
- if entity.nil?
278
- status 404
279
- return
220
+ find_entity(params[:entity]) do |entity|
221
+ find_entity_check(entity, params[:check]) do |entity_check|
222
+ summary = params[:summary] || "Testing notifications to all contacts interested in entity #{entity.name}"
223
+ entity_check.test_notifications('summary' => summary)
224
+ status 204
225
+ end
280
226
  end
281
-
282
- summary = params[:summary] || "Testing notifications to all contacts interested in entity #{entity.name}"
283
-
284
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
285
- params[:check], :redis => redis)
286
- entity_check.test_notifications('summary' => summary)
287
- status 204
288
227
  end
289
228
 
290
229
  post '/entities' do
@@ -294,21 +233,26 @@ module Flapjack
294
233
  errors = []
295
234
  ret = nil
296
235
 
236
+ # FIXME should scan for invalid records before making any changes, fail early
237
+
297
238
  entities = params[:entities]
298
- if entities && entities.is_a?(Enumerable) && entities.any? {|e| !e['id'].nil?}
299
- entities.each do |entity|
300
- unless entity['id']
301
- errors << "Entity not imported as it has no id: #{entity.inspect}"
302
- next
303
- end
304
- Flapjack::Data::Entity.add(entity, :redis => redis)
239
+ unless entities
240
+ logger.debug("no entities object found in the following supplied JSON:")
241
+ logger.debug(request.body)
242
+ return error(403, "No entities object received")
243
+ end
244
+ return error(403, "The received entities object is not an Enumerable") unless entities.is_a?(Enumerable)
245
+ return error(403, "Entity with a nil id detected") unless entities.any? {|e| !e['id'].nil?}
246
+
247
+ entities.each do |entity|
248
+ unless entity['id']
249
+ errors << "Entity not imported as it has no id: #{entity.inspect}"
250
+ next
305
251
  end
306
- ret = 200
307
- else
308
- ret = 403
309
- errors << "No valid entities were submitted"
252
+ Flapjack::Data::Entity.add(entity, :redis => redis)
310
253
  end
311
- errors.empty? ? ret : [ret, {}, {:errors => [errors]}.to_json]
254
+
255
+ errors.empty? ? 204 : error(403, *errors)
312
256
  end
313
257
 
314
258
  post '/contacts' do
@@ -349,7 +293,7 @@ module Flapjack
349
293
  end
350
294
  end
351
295
  end
352
- errors.empty? ? 200 : [403, {}, {:errors => [errors]}.to_json]
296
+ errors.empty? ? 204 : error(403, *errors)
353
297
  end
354
298
 
355
299
  # Returns all the contacts
@@ -363,369 +307,325 @@ module Flapjack
363
307
  # https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id
364
308
  get '/contacts/:contact_id' do
365
309
  content_type :json
366
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
367
- if contact.nil?
368
- logger.warn "contact not found with id #{params[:contact_id]}"
369
- status 404
370
- return
310
+ find_contact(params[:contact_id]) do |contact|
311
+ contact.to_json
371
312
  end
372
- contact.to_json
373
313
  end
374
314
 
375
315
  # Lists this contact's notification rules
376
316
  # https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_notification_rules
377
317
  get '/contacts/:contact_id/notification_rules' do
378
318
  content_type :json
379
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
380
- if contact.nil?
381
- logger.warn "contact not found with id #{params[:contact_id]}"
382
- status 404
383
- return
319
+ find_contact(params[:contact_id]) do |contact|
320
+ contact.notification_rules.to_json
384
321
  end
385
- contact.notification_rules.to_json
386
322
  end
387
323
 
388
324
  # Get the specified notification rule for this user
389
325
  # https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_notification_rules_id
390
- get '/notification_rules/:rule_id' do
326
+ get '/notification_rules/:id' do
391
327
  content_type :json
392
328
 
393
- rule = Flapjack::Data::NotificationRule.find_by_id(params[:rule_id], :redis => redis)
394
- if rule.nil?
395
- logger.warn("Unable to find a notification rule with id [#{params[:rule_id]}]")
396
- status 404
397
- return
329
+ find_rule(params[:id]) do |rule|
330
+ rule.to_json
398
331
  end
399
- rule.to_json
400
332
  end
401
333
 
402
334
  # Creates a notification rule for a contact
403
335
  # https://github.com/flpjck/flapjack/wiki/API#wiki-post_contacts_id_notification_rules
404
336
  post '/notification_rules' do
405
- # # NB if parameters are correctly passed, we shouldn't mandate a request format
406
- # pass unless 'application/json'.eql?(request.content_type)
407
337
  content_type :json
408
-
409
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
410
- if contact.nil?
411
- logger.warn "contact not found with id #{params[:contact_id]}"
412
- status 404
413
- return
414
- end
415
338
  if params[:id]
416
- logger.warn "post cannot be used for update, do a put instead"
417
- status 403
418
- return
339
+ return error(403, "post cannot be used for update, do a put instead")
419
340
  end
420
341
 
421
- rule_data = hashify(:entities, :entity_tags,
422
- :warning_media, :critical_media, :time_restrictions,
423
- :warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
424
- rule = contact.add_notification_rule(rule_data)
425
- rule.to_json
342
+ find_contact(params[:contact_id]) do |contact|
343
+
344
+ rule_data = hashify(:entities, :entity_tags,
345
+ :warning_media, :critical_media, :time_restrictions,
346
+ :warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
347
+
348
+ unless rule = contact.add_notification_rule(rule_data)
349
+ return error(403, "invalid notification rule data")
350
+ end
351
+ rule.to_json
352
+ end
426
353
  end
427
354
 
428
355
  # Updates a notification rule
429
356
  # https://github.com/flpjck/flapjack/wiki/API#wiki-put_notification_rules_id
430
357
  put('/notification_rules/:id') do
431
- # # NB if parameters are correctly passed, we shouldn't mandate a request format
432
- # pass unless 'application/json'.eql?(request.content_type)
433
358
  content_type :json
359
+ find_rule(params[:id]) do |rule|
360
+ find_contact(rule.contact_id) do |contact|
434
361
 
435
- ret = nil
362
+ rule_data = hashify(:entities, :entity_tags,
363
+ :warning_media, :critical_media, :time_restrictions,
364
+ :warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
436
365
 
437
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
438
- if contact.nil?
439
- logger.warn "contact not found with id #{params[:contact_id]}"
440
- status 404
441
- return
442
- end
443
- rule = Flapjack::Data::NotificationRule.find_by_id(params[:id], :redis => redis)
444
- if rule.nil?
445
- logger.warn "rule not found with id #{params[:id]}"
446
- status 404
447
- return
366
+ unless rule.update(rule_data)
367
+ return error(403, "invalid notification rule data")
368
+ end
369
+ rule.to_json
370
+ end
448
371
  end
449
-
450
- rule_data = hashify(:entities, :entity_tags,
451
- :warning_media, :critical_media, :time_restrictions,
452
- :warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
453
- rule.update(rule_data)
454
- rule.to_json
455
372
  end
456
373
 
457
374
  # Deletes a notification rule
458
375
  # https://github.com/flpjck/flapjack/wiki/API#wiki-put_notification_rules_id
459
376
  delete('/notification_rules/:id') do
460
- rule = Flapjack::Data::NotificationRule.find_by_id(params[:id], :redis => redis)
461
- if rule.nil?
462
- status 404
463
- return
464
- end
465
- contact = Flapjack::Data::Contact.find_by_id(rule.contact_id, :redis => redis)
466
- if contact.nil?
467
- logger.warn "contact not found with id #{rule.contact_id}"
468
- status 404
469
- return
377
+ find_rule(params[:id]) do |rule|
378
+ find_contact(rule.contact_id) do |contact|
379
+ contact.delete_notification_rule(rule)
380
+ status 204
381
+ end
470
382
  end
471
- contact.delete_notification_rule(rule)
472
- status 204
473
383
  end
474
384
 
475
385
  # Returns the media of a contact
476
386
  # https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_media
477
387
  get '/contacts/:contact_id/media' do
478
388
  content_type :json
479
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
480
- if contact.nil?
481
- status 404
482
- return
389
+ find_contact(params[:contact_id]) do |contact|
390
+ media = contact.media
391
+ media_intervals = contact.media_intervals
392
+ media_addr_int = hashify(*media.keys) {|k|
393
+ [k, {'address' => media[k],
394
+ 'interval' => media_intervals[k] }]
395
+ }
396
+ media_addr_int.to_json
483
397
  end
484
- media = contact.media
485
- media_intervals = contact.media_intervals
486
- media_addr_int = hashify(*media.keys) {|k|
487
- [k, {'address' => media[k],
488
- 'interval' => media_intervals[k] }]
489
- }
490
- media_addr_int.to_json
491
398
  end
492
399
 
493
400
  # Returns the specified media of a contact
494
401
  # https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_media_media
495
- get('/contacts/:contact_id/media/:media_id') do
402
+ get('/contacts/:contact_id/media/:id') do
496
403
  content_type :json
497
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
498
- if contact.nil?
499
- status 404
500
- return
501
- end
502
- if contact.media[params[:media_id]].nil?
503
- status 404
504
- return
404
+ find_contact(params[:contact_id]) do |contact|
405
+ if contact.media[params[:id]].nil?
406
+ status 404
407
+ return
408
+ end
409
+ {'address' => contact.media[params[:id]],
410
+ 'interval' => contact.media_intervals[params[:id]]}.to_json
505
411
  end
506
- { 'address' => contact.media[params[:media_id]],
507
- 'interval' => contact.media_intervals[params[:media_id]] }.to_json
508
412
  end
509
413
 
510
414
  # Creates or updates a media of a contact
511
415
  # https://github.com/flpjck/flapjack/wiki/API#wiki-put_contacts_id_media_media
512
- put('/contacts/:contact_id/media/:media_id') do
416
+ put('/contacts/:contact_id/media/:id') do
513
417
  content_type :json
514
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
515
- if contact.nil?
516
- status 404
517
- return
518
- end
519
- if params[:address].nil? || params[:interval].nil?
520
- status 403
521
- return
522
- end
523
- contact.set_address_for_media(params[:media_id], params[:address])
524
- contact.set_interval_for_media(params[:media_id], params[:interval])
418
+ find_contact(params[:contact_id]) do |contact|
419
+ errors = []
420
+ if params[:address].nil?
421
+ errors << "no address for '#{params[:id]}' media"
422
+ end
423
+ if params[:interval].nil?
424
+ errors << "no interval for '#{params[:id]}' media"
425
+ end
426
+
427
+ return error(403, *errors) unless errors.empty?
428
+
429
+ contact.set_address_for_media(params[:id], params[:address])
430
+ contact.set_interval_for_media(params[:id], params[:interval])
525
431
 
526
- { 'address' => contact.media[params[:media_id]],
527
- 'interval' => contact.media_intervals[params[:media_id]] }.to_json
432
+ {'address' => contact.media[params[:id]],
433
+ 'interval' => contact.media_intervals[params[:id]]}.to_json
434
+ end
528
435
  end
529
436
 
530
437
  # delete a media of a contact
531
- delete('/contacts/:contact_id/media/:media_id') do
532
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
533
- if contact.nil?
534
- status 404
535
- return
438
+ delete('/contacts/:contact_id/media/:id') do
439
+ find_contact(params[:contact_id]) do |contact|
440
+ contact.remove_media(params[:id])
441
+ status 204
536
442
  end
537
- contact.remove_media(params[:media_id])
538
- status 204
539
443
  end
540
444
 
541
445
  # Returns the timezone of a contact
542
446
  # https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_timezone
543
447
  get('/contacts/:contact_id/timezone') do
544
448
  content_type :json
545
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
546
- if contact.nil?
547
- status 404
548
- return
449
+ find_contact(params[:contact_id]) do |contact|
450
+ contact.timezone.name.to_json
549
451
  end
550
- contact.timezone.name.to_json
551
452
  end
552
453
 
553
454
  # Sets the timezone of a contact
554
455
  # https://github.com/flpjck/flapjack/wiki/API#wiki-put_contacts_id_timezone
555
456
  put('/contacts/:contact_id/timezone') do
556
457
  content_type :json
557
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
558
- if contact.nil?
559
- status 404
560
- return
458
+ find_contact(params[:contact_id]) do |contact|
459
+ contact.timezone = params[:timezone]
460
+ contact.timezone.name.to_json
561
461
  end
562
- contact.timezone = params[:timezone]
563
- contact.timezone.name.to_json
564
462
  end
565
463
 
566
464
  # Removes the timezone of a contact
567
465
  # https://github.com/flpjck/flapjack/wiki/API#wiki-put_contacts_id_timezone
568
466
  delete('/contacts/:contact_id/timezone') do
569
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
570
- if contact.nil?
571
- status 404
572
- return
467
+ find_contact(params[:contact_id]) do |contact|
468
+ contact.timezone = nil
469
+ status 204
573
470
  end
574
- contact.timezone = nil
575
- status 204
576
471
  end
577
472
 
578
473
  post '/contacts/:contact_id/tags' do
579
474
  content_type :json
580
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
581
- if contact.nil?
582
- status 404
583
- return
584
- end
585
- tags = params[:tag]
586
- if tags.nil? || tags.empty?
587
- status 403
588
- return
475
+ check_tags(params[:tag]) do |tags|
476
+ find_contact(params[:contact_id]) do |contact|
477
+ contact.add_tags(*tags)
478
+ contact.tags.to_json
479
+ end
589
480
  end
590
- tags = [tags] unless tags.respond_to?(:each)
591
- contact.add_tags(*tags)
592
- contact.tags.to_json
593
481
  end
594
482
 
595
483
  post '/contacts/:contact_id/entity_tags' do
596
484
  content_type :json
597
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
598
- if contact.nil?
599
- status 404
600
- return
601
- end
602
- contact.entities.map {|e| e[:entity]}.each do |entity|
603
- next unless tags = params[:entity][entity.name]
604
- entity.add_tags(*tags)
485
+ find_contact(params[:contact_id]) do |contact|
486
+ contact.entities.map {|e| e[:entity]}.each do |entity|
487
+ next unless tags = params[:entity][entity.name]
488
+ entity.add_tags(*tags)
489
+ end
490
+ contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
491
+ [et[:entity].name, et[:tags]]
492
+ }
493
+ contact_ent_tag.to_json
605
494
  end
606
- contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
607
- [et[:entity].name, et[:tags]]
608
- }
609
- contact_ent_tag.to_json
610
495
  end
611
496
 
612
497
  delete '/contacts/:contact_id/tags' do
613
498
  content_type :json
614
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
615
- if contact.nil?
616
- status 404
617
- return
618
- end
619
- tags = params[:tag]
620
- if tags.nil? || tags.empty?
621
- status 403
622
- return
499
+ check_tags(params[:tag]) do |tags|
500
+ find_contact(params[:contact_id]) do |contact|
501
+ contact.delete_tags(*tags)
502
+ status 204
503
+ end
623
504
  end
624
- tags = [tags] unless tags.respond_to?(:each)
625
- contact.delete_tags(*tags)
626
- status 204
627
505
  end
628
506
 
629
507
  delete '/contacts/:contact_id/entity_tags' do
630
508
  content_type :json
631
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
632
- if contact.nil?
633
- status 404
634
- return
635
- end
636
- contact.entities.map {|e| e[:entity]}.each do |entity|
637
- next unless tags = params[:entity][entity.name]
638
- entity.delete_tags(*tags)
509
+ find_contact(params[:contact_id]) do |contact|
510
+ contact.entities.map {|e| e[:entity]}.each do |entity|
511
+ next unless tags = params[:entity][entity.name]
512
+ entity.delete_tags(*tags)
513
+ end
514
+ status 204
639
515
  end
640
- status 204
641
516
  end
642
517
 
643
518
  get '/contacts/:contact_id/tags' do
644
519
  content_type :json
645
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
646
- if contact.nil?
647
- status 404
648
- return
520
+ find_contact(params[:contact_id]) do |contact|
521
+ contact.tags.to_json
649
522
  end
650
- contact.tags.to_json
651
523
  end
652
524
 
653
525
  get '/contacts/:contact_id/entity_tags' do
654
526
  content_type :json
655
- contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
656
- if contact.nil?
657
- status 404
658
- return
527
+ find_contact(params[:contact_id]) do |contact|
528
+ contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
529
+ [et[:entity].name, et[:tags]]
530
+ }
531
+ contact_ent_tag.to_json
659
532
  end
660
- contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
661
- [et[:entity].name, et[:tags]]
662
- }
663
- contact_ent_tag.to_json
664
533
  end
665
534
 
666
535
  post '/entities/:entity/tags' do
667
536
  content_type :json
668
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
669
- if entity.nil?
670
- status 404
671
- return
672
- end
673
- tags = params[:tag]
674
- if tags.nil? || tags.empty?
675
- status 403
676
- return
537
+ check_tags(params[:tag]) do |tags|
538
+ find_entity(params[:entity]) do |entity|
539
+ entity.add_tags(*tags)
540
+ entity.tags.to_json
541
+ end
677
542
  end
678
- tags = [tags] unless tags.respond_to?(:each)
679
- entity.add_tags(*tags)
680
- entity.tags.to_json
681
543
  end
682
544
 
683
545
  delete '/entities/:entity/tags' do
684
546
  content_type :json
685
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
686
- if entity.nil?
687
- status 404
688
- return
689
- end
690
- tags = params[:tag]
691
- if tags.nil? || tags.empty?
692
- status 403
693
- return
547
+ check_tags(params[:tag]) do |tags|
548
+ find_entity(params[:entity]) do |entity|
549
+ entity.delete_tags(*tags)
550
+ status 204
551
+ end
694
552
  end
695
- tags = [tags] unless tags.respond_to?(:each)
696
- entity.delete_tags(*tags)
697
- status 204
698
553
  end
699
554
 
700
555
  get '/entities/:entity/tags' do
701
556
  content_type :json
702
- entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
703
- if entity.nil?
704
- status 404
705
- return
557
+ find_entity(params[:entity]) do |entity|
558
+ entity.tags.to_json
706
559
  end
707
- entity.tags.to_json
708
560
  end
709
561
 
710
562
  not_found do
711
- [404, {}, {:errors => ["Not found"]}.to_json]
563
+ error(404, "not routable")
712
564
  end
713
565
 
714
566
  private
715
567
 
568
+ def error(status, *msg)
569
+ msg_str = msg.join(", ")
570
+ logger.info "Error: #{msg_str}"
571
+ [status, {}, {:errors => msg}.to_json]
572
+ end
573
+
716
574
  def entity_check_status(entity, check)
717
575
  entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
718
576
  check, :redis => redis)
719
577
  return if entity_check.nil?
720
- { 'name' => check,
721
- 'state' => entity_check.state,
722
- 'in_unscheduled_maintenance' => entity_check.in_unscheduled_maintenance?,
723
- 'in_scheduled_maintenance' => entity_check.in_scheduled_maintenance?,
724
- 'last_update' => entity_check.last_update,
725
- 'last_problem_notification' => entity_check.last_problem_notification,
726
- 'last_recovery_notification' => entity_check.last_recovery_notification,
727
- 'last_acknowledgement_notification' => entity_check.last_acknowledgement_notification
728
- }
578
+ {'name' => check,
579
+ 'state' => entity_check.state,
580
+ 'in_unscheduled_maintenance' => entity_check.in_unscheduled_maintenance?,
581
+ 'in_scheduled_maintenance' => entity_check.in_scheduled_maintenance?,
582
+ 'last_update' => entity_check.last_update,
583
+ 'last_problem_notification' => entity_check.last_problem_notification,
584
+ 'last_recovery_notification' => entity_check.last_recovery_notification,
585
+ 'last_acknowledgement_notification' => entity_check.last_acknowledgement_notification}
586
+ end
587
+
588
+ # following a callback-heavy pattern -- feels like nodejs :)
589
+ def find_contact(contact_id, &block)
590
+ contact = Flapjack::Data::Contact.find_by_id(contact_id, :redis => redis)
591
+ return(yield(contact)) if contact
592
+ error(404, "could not find contact with id '#{contact_id}'")
593
+ end
594
+
595
+ def find_rule(rule_id, &block)
596
+ rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :redis => redis)
597
+ return(yield(rule)) if rule
598
+ error(404, "could not find notification rule with id '#{rule_id}'")
599
+ end
600
+
601
+ def find_entity(entity_name, &block)
602
+ entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
603
+ return(yield(entity)) if entity
604
+ error(404, "could not find entity '#{entity_name}'")
605
+ end
606
+
607
+ def find_entity_check(entity, check, &block)
608
+ entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
609
+ check, :redis => redis)
610
+ return(yield(entity_check)) if entity_check
611
+ error(404, "could not find entity check '#{entity.name}:#{check}'")
612
+ end
613
+
614
+ def find_api_presenter(entity_name, check, &block)
615
+ find_entity(entity_name) do |entity|
616
+ if check
617
+ find_entity_check(entity, check) do |entity_check|
618
+ yield(Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check))
619
+ end
620
+ else
621
+ yield(Flapjack::Gateways::API::EntityPresenter.new(entity, :redis => redis))
622
+ end
623
+ end
624
+ end
625
+
626
+ def check_tags(tags)
627
+ return(yield(tags)) unless tags.nil? || tags.empty?
628
+ error(403, "no tag params passed")
729
629
  end
730
630
 
731
631
  # NB: casts to UTC before converting to a timestamp
@@ -737,22 +637,6 @@ module Flapjack
737
637
  nil
738
638
  end
739
639
 
740
- # The passed block will be provided each value from the args
741
- # and must return array pairs [key, value] representing members of
742
- # the hash this method returns. Keys should be unique -- if they're
743
- # not, the earlier pair for that key will be overwritten.
744
- def hashify(*args, &block)
745
- key_value_pairs = args.map {|a| yield(a) }
746
-
747
- # if using Ruby 1.9,
748
- # Hash[ key_value_pairs ]
749
- # is all that's needed, but for Ruby 1.8 compatability, these must
750
- # be flattened and the resulting array unpacked. flatten(1) only
751
- # flattens the arrays constructed in the block, it won't mess up
752
- # any values (or keys) that are themselves arrays.
753
- Hash[ *( key_value_pairs.flatten(1) )]
754
- end
755
-
756
640
  end
757
641
 
758
642
  end