flapjack 1.0.0rc3 → 1.0.0rc5

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -2
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +20 -0
  5. data/CONTRIBUTING.md +2 -2
  6. data/Gemfile +1 -1
  7. data/README.md +6 -16
  8. data/build.sh +13 -1
  9. data/etc/flapjack_config.yaml.example +98 -12
  10. data/features/cli.feature +8 -8
  11. data/features/cli_flapjack-nagios-receiver.feature +29 -37
  12. data/features/cli_flapper.feature +24 -12
  13. data/features/cli_simulate-failed-check.feature +2 -2
  14. data/features/notifications.feature +18 -1
  15. data/features/steps/cli_steps.rb +2 -2
  16. data/features/steps/notifications_steps.rb +71 -0
  17. data/features/support/env.rb +7 -6
  18. data/flapjack.gemspec +3 -1
  19. data/lib/flapjack/cli/flapper.rb +74 -25
  20. data/lib/flapjack/cli/import.rb +3 -4
  21. data/lib/flapjack/cli/maintenance.rb +182 -0
  22. data/lib/flapjack/cli/receiver.rb +110 -121
  23. data/lib/flapjack/cli/server.rb +30 -26
  24. data/lib/flapjack/cli/simulate.rb +2 -3
  25. data/lib/flapjack/data/contact.rb +1 -1
  26. data/lib/flapjack/data/entity.rb +425 -32
  27. data/lib/flapjack/data/entity_check.rb +212 -14
  28. data/lib/flapjack/data/event.rb +1 -1
  29. data/lib/flapjack/gateways/aws_sns.rb +134 -0
  30. data/lib/flapjack/gateways/aws_sns/alert.text.erb +5 -0
  31. data/lib/flapjack/gateways/aws_sns/rollup.text.erb +2 -0
  32. data/lib/flapjack/gateways/jabber.rb +2 -2
  33. data/lib/flapjack/gateways/jsonapi/check_methods.rb +1 -1
  34. data/lib/flapjack/gateways/jsonapi/contact_methods.rb +1 -1
  35. data/lib/flapjack/gateways/jsonapi/entity_methods.rb +15 -1
  36. data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +4 -3
  37. data/lib/flapjack/gateways/jsonapi/report_methods.rb +1 -1
  38. data/lib/flapjack/gateways/web.rb +35 -16
  39. data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -16
  40. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
  41. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -45
  42. data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
  43. data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
  44. data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
  45. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
  46. data/lib/flapjack/gateways/web/views/check.html.erb +10 -10
  47. data/lib/flapjack/gateways/web/views/checks.html.erb +1 -1
  48. data/lib/flapjack/gateways/web/views/contact.html.erb +5 -1
  49. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +3 -4
  50. data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
  51. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  52. data/lib/flapjack/gateways/web/views/layout.erb +3 -3
  53. data/lib/flapjack/gateways/web/views/self_stats.html.erb +5 -6
  54. data/lib/flapjack/notifier.rb +4 -1
  55. data/lib/flapjack/patches.rb +8 -2
  56. data/lib/flapjack/pikelet.rb +3 -1
  57. data/lib/flapjack/version.rb +1 -1
  58. data/libexec/httpbroker.go +1 -1
  59. data/spec/lib/flapjack/coordinator_spec.rb +3 -3
  60. data/spec/lib/flapjack/data/contact_spec.rb +2 -2
  61. data/spec/lib/flapjack/data/entity_check_spec.rb +805 -53
  62. data/spec/lib/flapjack/data/entity_spec.rb +661 -0
  63. data/spec/lib/flapjack/gateways/aws_sns_spec.rb +123 -0
  64. data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -1
  65. data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +1 -1
  66. data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +2 -2
  67. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
  68. data/spec/lib/flapjack/gateways/web_spec.rb +11 -11
  69. data/spec/support/profile_all_formatter.rb +10 -10
  70. data/spec/support/uncolored_doc_formatter.rb +66 -4
  71. data/src/flapjack/event.go +1 -1
  72. data/tasks/benchmarks.rake +24 -20
  73. data/tasks/entities.rake +148 -0
  74. data/tmp/dummy_contacts.json +43 -0
  75. data/tmp/dummy_entities.json +37 -1
  76. metadata +43 -7
  77. data/tmp/test_entities.json +0 -1
@@ -250,4 +250,665 @@ describe Flapjack::Data::Entity, :redis => true do
250
250
  expect(entities.first).to eq('def-456')
251
251
  end
252
252
 
253
+ context 'renaming and merging' do
254
+
255
+ let(:time_i) { Time.now.to_i }
256
+
257
+ let(:sha1) { Digest::SHA1.new }
258
+ let(:hash_name1) { Digest.hexencode(sha1.digest('name1:PING'))[0..7].downcase }
259
+ let(:hash_name2) { Digest.hexencode(sha1.digest('name2:PING'))[0..7].downcase }
260
+
261
+ def add_name1
262
+ Flapjack::Data::Entity.add({'id' => '5000',
263
+ 'name' => 'name1',
264
+ 'contacts' => ['362']},
265
+ :redis => @redis)
266
+ end
267
+
268
+ def add_name2
269
+ Flapjack::Data::Entity.add({'id' => '5000',
270
+ 'name' => 'name2',
271
+ 'contacts' => ['362']},
272
+ :redis => @redis)
273
+ end
274
+
275
+ before(:each) do
276
+ Flapjack::Data::Contact.add({'id' => '362',
277
+ 'first_name' => 'John',
278
+ 'last_name' => 'Johnson',
279
+ 'email' => 'johnj@example.com' },
280
+ :redis => @redis)
281
+ end
282
+
283
+ context 'entity renaming on #add' do
284
+
285
+ let(:time_i) { Time.now.to_i }
286
+
287
+ let(:sha1) { Digest::SHA1.new }
288
+ let(:hash_name1) { Digest.hexencode(sha1.digest('name1:PING'))[0..7].downcase }
289
+ let(:hash_name2) { Digest.hexencode(sha1.digest('name2:PING'))[0..7].downcase }
290
+
291
+ before(:each) do
292
+ add_name1
293
+ end
294
+
295
+ it 'renames the "entity name to id lookup" and the name in the "entity hash by id"' do
296
+ expect(@redis.get('entity_id:name1')).to eq('5000')
297
+ expect(@redis.hget('entity:5000', 'name')).to eq('name1')
298
+
299
+ add_name2
300
+
301
+ expect(@redis.get('entity_id:name1')).to be_nil
302
+ expect(@redis.get('entity_id:name2')).to eq('5000')
303
+ expect(@redis.hget('entity:5000', 'name')).to eq('name2')
304
+ end
305
+
306
+ it 'does not rename an entity if an entity with the new name already exists' do
307
+ Flapjack::Data::Entity.add({'id' => '5001',
308
+ 'name' => 'name2',
309
+ 'contacts' => []},
310
+ :redis => @redis)
311
+
312
+ expect(@redis.get('entity_id:name1')).to eq('5000')
313
+ expect(@redis.hget('entity:5000', 'name')).to eq('name1')
314
+ expect(@redis.get('entity_id:name2')).to eq('5001')
315
+ expect(@redis.hget('entity:5001', 'name')).to eq('name2')
316
+
317
+ add_name2
318
+
319
+ # no change
320
+ expect(@redis.get('entity_id:name1')).to eq('5000')
321
+ expect(@redis.hget('entity:5000', 'name')).to eq('name1')
322
+ expect(@redis.get('entity_id:name2')).to eq('5001')
323
+ expect(@redis.hget('entity:5001', 'name')).to eq('name2')
324
+ end
325
+
326
+ it 'renames current check state' do
327
+ data = {'state' => 'critical', 'last_change' => time_i.to_s, 'last_update' => time_i.to_s}
328
+ @redis.mapped_hmset('check:name1:PING', data)
329
+
330
+ add_name2
331
+
332
+ expect(@redis.hgetall('check:name1:PING')).to eq({})
333
+ expect(@redis.hgetall('check:name2:PING')).to eq(data)
334
+ end
335
+
336
+ it 'renames stored check state changes' do
337
+ @redis.rpush('name1:PING:states', time_i)
338
+ @redis.set("name1:PING:#{time_i}:state", 'critical')
339
+ @redis.set("name1:PING:#{time_i}:summary", 'bad')
340
+ @redis.zadd('name1:PING:sorted_state_timestamps', time_i, time_i)
341
+
342
+ add_name2
343
+
344
+ expect(@redis.type('name1:PING:states')).to eq('none')
345
+ expect(@redis.type('name2:PING:states')).to eq('list')
346
+ expect(@redis.lindex('name2:PING:states', 0)).to eq(time_i.to_s)
347
+ expect(@redis.get("name1:PING:#{time_i}:state")).to be_nil
348
+ expect(@redis.get("name2:PING:#{time_i}:state")).to eq('critical')
349
+ expect(@redis.get("name1:PING:#{time_i}:summary")).to be_nil
350
+ expect(@redis.get("name2:PING:#{time_i}:summary")).to eq('bad')
351
+ expect(@redis.zrange("name1:PING:sorted_state_timestamps", 0, -1, :with_scores => true)).to eq([])
352
+ expect(@redis.zrange("name2:PING:sorted_state_timestamps", 0, -1, :with_scores => true)).to eq([[time_i.to_s, time_i.to_f]])
353
+ end
354
+
355
+ it 'renames stored action events' do
356
+ @redis.hset('name1:PING:actions', time_i.to_s, 'acknowledgement')
357
+
358
+ add_name2
359
+
360
+ expect(@redis.hget('name1:PING:actions', time_i.to_s)).to be_nil
361
+ expect(@redis.hget('name2:PING:actions', time_i.to_s)).to eq('acknowledgement')
362
+ end
363
+
364
+ it 'renames entries in the sorted set of failing checks' do
365
+ data = {'state' => 'critical', 'last_change' => time_i.to_s, 'last_update' => time_i.to_s}
366
+ @redis.mapped_hmset('check:name1:PING', data)
367
+
368
+ @redis.zadd('failed_checks', time_i, 'name1:PING')
369
+
370
+ add_name2
371
+
372
+ expect(@redis.zrange('failed_checks', 0, -1, :with_scores => true)).to eq([['name2:PING', time_i.to_f]])
373
+ end
374
+
375
+ it 'renames the list of current checks, and its entries' do
376
+ @redis.zadd('current_checks:name1', time_i, 'PING')
377
+
378
+ add_name2
379
+
380
+ expect(@redis.zrange('current_checks:name1', 0, -1, :with_scores => true)).to eq([])
381
+ expect(@redis.zrange('current_checks:name2', 0, -1, :with_scores => true)).to eq([['PING', time_i.to_f]])
382
+ end
383
+
384
+ it 'renames an entry in the list of current entities' do
385
+ @redis.zadd('current_entities', time_i, 'name1')
386
+
387
+ add_name2
388
+
389
+ expect(@redis.zrange('current_entities', 0, -1, :with_scores => true)).to eq([['name2', time_i.to_f]])
390
+ end
391
+
392
+ it 'renames a current unscheduled maintenance key' do
393
+ @redis.setex('name1:PING:unscheduled_maintenance', 30, time_i)
394
+
395
+ add_name2
396
+
397
+ expect(@redis.get('name1:PING:unscheduled_maintenance')).to be_nil
398
+ expect(@redis.get('name2:PING:unscheduled_maintenance')).to eq(time_i.to_s)
399
+ expect(@redis.ttl('name2:PING:unscheduled_maintenance')).to be <= 30
400
+ end
401
+
402
+ it 'renames stored unscheduled maintenance periods and sorted timestamps' do
403
+ @redis.zadd('name1:PING:unscheduled_maintenances', 30, time_i)
404
+ @redis.set("name1:PING:#{time_i}:unscheduled_maintenance:summary", 'really bad')
405
+ @redis.zadd('name1:PING:sorted_unscheduled_maintenance_timestamps', time_i, time_i)
406
+
407
+ add_name2
408
+
409
+ expect(@redis.zrange('name1:PING:unscheduled_maintenances', 0, -1, :with_scores => true)).to eq([])
410
+ expect(@redis.zrange('name2:PING:unscheduled_maintenances', 0, -1, :with_scores => true)).to eq([[time_i.to_s, 30.0]])
411
+ expect(@redis.get("name1:PING:#{time_i}:unscheduled_maintenance:summary")).to be_nil
412
+ expect(@redis.get("name2:PING:#{time_i}:unscheduled_maintenance:summary")).to eq('really bad')
413
+ expect(@redis.zrange('name1:PING:sorted_unscheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq([])
414
+ expect(@redis.zrange('name2:PING:sorted_unscheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq([[time_i.to_s, time_i.to_f]])
415
+ end
416
+
417
+ it 'renames a current scheduled maintenance key' do
418
+ @redis.setex('name1:PING:scheduled_maintenance', 30, time_i)
419
+
420
+ add_name2
421
+
422
+ expect(@redis.get('name1:PING:scheduled_maintenance')).to be_nil
423
+ expect(@redis.get('name2:PING:scheduled_maintenance')).to eq(time_i.to_s)
424
+ expect(@redis.ttl('name2:PING:scheduled_maintenance')).to be <= 30
425
+ end
426
+
427
+ it 'renames stored scheduled maintenance periods and sorted timestamps' do
428
+ @redis.zadd('name1:PING:scheduled_maintenances', 30, time_i)
429
+ @redis.set("name1:PING:#{time_i}:scheduled_maintenance:summary", 'really bad')
430
+ @redis.zadd('name1:PING:sorted_scheduled_maintenance_timestamps', time_i, time_i)
431
+
432
+ add_name2
433
+
434
+ expect(@redis.zrange('name1:PING:scheduled_maintenances', 0, -1, :with_scores => true)).to eq([])
435
+ expect(@redis.zrange('name2:PING:scheduled_maintenances', 0, -1, :with_scores => true)).to eq([[time_i.to_s, 30.0]])
436
+ expect(@redis.get("name1:PING:#{time_i}:scheduled_maintenance:summary")).to be_nil
437
+ expect(@redis.get("name2:PING:#{time_i}:scheduled_maintenance:summary")).to eq('really bad')
438
+ expect(@redis.zrange('name1:PING:sorted_scheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq([])
439
+ expect(@redis.zrange('name2:PING:sorted_scheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq([[time_i.to_s, time_i.to_f]])
440
+ end
441
+
442
+ it 'renames current notifications' do
443
+ @redis.set('name1:PING:last_problem_notification', time_i)
444
+ @redis.set('name1:PING:last_unknown_notification', time_i - 100)
445
+ @redis.set('name1:PING:last_warning_notification', time_i - 50)
446
+ @redis.set('name1:PING:last_critical_notification', time_i)
447
+ @redis.set('name1:PING:last_recovery_notification', time_i - 200)
448
+ @redis.set('name1:PING:last_acknowledgement_notification', time_i - 250)
449
+
450
+ add_name2
451
+
452
+ expect(@redis.get('name1:PING:last_problem_notification')).to be_nil
453
+ expect(@redis.get('name1:PING:last_unknown_notification')).to be_nil
454
+ expect(@redis.get('name1:PING:last_warning_notification')).to be_nil
455
+ expect(@redis.get('name1:PING:last_critical_notification')).to be_nil
456
+ expect(@redis.get('name1:PING:last_recovery_notification')).to be_nil
457
+ expect(@redis.get('name1:PING:last_acknowledgement_notification')).to be_nil
458
+ expect(@redis.get('name2:PING:last_problem_notification')).to eq(time_i.to_s)
459
+ expect(@redis.get('name2:PING:last_unknown_notification')).to eq((time_i - 100).to_s)
460
+ expect(@redis.get('name2:PING:last_warning_notification')).to eq((time_i - 50).to_s)
461
+ expect(@redis.get('name2:PING:last_critical_notification')).to eq(time_i.to_s)
462
+ expect(@redis.get('name2:PING:last_recovery_notification')).to eq((time_i - 200).to_s)
463
+ expect(@redis.get('name2:PING:last_acknowledgement_notification')).to eq((time_i - 250).to_s)
464
+ end
465
+
466
+ it 'renames stored notifications' do
467
+ @redis.lpush('name1:PING:problem_notifications', time_i)
468
+ @redis.lpush('name1:PING:unknown_notifications', time_i - 100)
469
+ @redis.lpush('name1:PING:warning_notifications', time_i - 50)
470
+ @redis.lpush('name1:PING:critical_notifications', time_i)
471
+ @redis.lpush('name1:PING:recovery_notifications', time_i - 200)
472
+ @redis.lpush('name1:PING:acknowledgement_notifications', time_i - 250)
473
+
474
+ add_name2
475
+
476
+ expect(@redis.llen('name1:PING:problem_notifications')).to eq(0)
477
+ expect(@redis.llen('name1:PING:unknown_notifications')).to eq(0)
478
+ expect(@redis.llen('name1:PING:warning_notifications')).to eq(0)
479
+ expect(@redis.llen('name1:PING:critical_notifications')).to eq(0)
480
+ expect(@redis.llen('name1:PING:recovery_notifications')).to eq(0)
481
+ expect(@redis.llen('name1:PING:acknowledgement_notifications')).to eq(0)
482
+ expect(@redis.lindex('name2:PING:problem_notifications', 0)).to eq(time_i.to_s)
483
+ expect(@redis.lindex('name2:PING:unknown_notifications', 0)).to eq((time_i - 100).to_s)
484
+ expect(@redis.lindex('name2:PING:warning_notifications', 0)).to eq((time_i - 50).to_s)
485
+ expect(@redis.lindex('name2:PING:critical_notifications', 0)).to eq(time_i.to_s)
486
+ expect(@redis.lindex('name2:PING:recovery_notifications', 0)).to eq((time_i - 200).to_s)
487
+ expect(@redis.lindex('name2:PING:acknowledgement_notifications', 0)).to eq((time_i - 250).to_s)
488
+ end
489
+
490
+ it 'renames alert blocks' do
491
+ @redis.setex('drop_alerts_for_contact:362:email:name1:PING:critical', 30, 30)
492
+
493
+ add_name2
494
+
495
+ expect(@redis.get('drop_alerts_for_contact:362:email:name1:PING:critical')).to be_nil
496
+ expect(@redis.get('drop_alerts_for_contact:362:email:name2:PING:critical')).to eq(30.to_s)
497
+ expect(@redis.ttl('drop_alerts_for_contact:362:email:name2:PING:critical')).to be <= 30
498
+ end
499
+
500
+ it "updates the check hash set" do
501
+ data = {'state' => 'critical', 'last_change' => time_i.to_s, 'last_update' => time_i.to_s}
502
+ @redis.mapped_hmset('check:name1:PING', data)
503
+
504
+ @redis.hset('checks_by_hash', hash_name1, 'name1:PING')
505
+
506
+ add_name2
507
+
508
+ expect(@redis.hget('checks_by_hash', hash_name1)).to be_nil
509
+ expect(@redis.hget('checks_by_hash', hash_name2)).to eq('name2:PING')
510
+ end
511
+
512
+ it 'renames entries within alerting checks' do
513
+ data = {'state' => 'critical', 'last_change' => time_i.to_s, 'last_update' => time_i.to_s}
514
+ @redis.mapped_hmset('check:name1:PING', data)
515
+
516
+ @redis.zadd('contact_alerting_checks:362:media:email', time_i, 'name1:PING')
517
+
518
+ add_name2
519
+
520
+ expect(@redis.zrange('contact_alerting_checks:362:media:email', 0, -1, :with_scores => true)).to eq(
521
+ [['name2:PING', time_i.to_f]]
522
+ )
523
+ end
524
+
525
+ end
526
+
527
+ context 'entity merging' do
528
+
529
+ let(:time_2_i) { time_i + 30 }
530
+
531
+ def do_merge
532
+ Flapjack::Data::Entity.merge('name1', 'name2', :redis => @redis)
533
+ end
534
+
535
+ # used as basic existence check for state on check on original entity
536
+ def add_state1
537
+ data = {'state' => 'critical', 'last_change' => time_i.to_s, 'last_update' => time_i.to_s}
538
+ @redis.mapped_hmset('check:name1:PING', data)
539
+ end
540
+
541
+ def add_state2
542
+ data = {'state' => 'critical', 'last_change' => time_2_i.to_s, 'last_update' => time_2_i.to_s}
543
+ @redis.mapped_hmset('check:name2:PING', data)
544
+ end
545
+
546
+ before(:each) do
547
+ add_name2
548
+ end
549
+
550
+ it 'does not overwrite current state for a check' do
551
+ add_state1
552
+ data_2 = {'state' => 'critical', 'last_change' => time_2_i.to_s, 'last_update' => time_2_i.to_s}
553
+ @redis.mapped_hmset('check:name2:PING', data_2)
554
+
555
+ do_merge
556
+
557
+ expect(@redis.hgetall('check:name1:PING')).to eq({})
558
+ expect(@redis.hgetall('check:name2:PING')).to eq(data_2)
559
+ end
560
+
561
+ it 'sets current state for a check if no new state is set' do
562
+ data = {'state' => 'critical', 'last_change' => time_i.to_s, 'last_update' => time_i.to_s}
563
+ @redis.mapped_hmset('check:name1:PING', data)
564
+
565
+ do_merge
566
+
567
+ expect(@redis.hgetall('check:name1:PING')).to eq({})
568
+ expect(@redis.hgetall('check:name2:PING')).to eq(data)
569
+ end
570
+
571
+ it 'merges stored check state changes' do
572
+ add_state1
573
+ add_state2
574
+
575
+ @redis.rpush('name1:PING:states', time_i)
576
+ @redis.set("name1:PING:#{time_i}:state", 'critical')
577
+ @redis.set("name1:PING:#{time_i}:summary", 'bad')
578
+ @redis.zadd('name1:PING:sorted_state_timestamps', time_i, time_i)
579
+
580
+ @redis.rpush('name2:PING:states', time_2_i)
581
+ @redis.set("name2:PING:#{time_2_i}:state", 'ok')
582
+ @redis.set("name2:PING:#{time_2_i}:summary", 'good')
583
+ @redis.zadd('name2:PING:sorted_state_timestamps', time_2_i, time_2_i)
584
+
585
+ do_merge
586
+
587
+ expect(@redis.type('name1:PING:states')).to eq('none')
588
+ expect(@redis.type('name2:PING:states')).to eq('list')
589
+
590
+ expect(@redis.llen('name2:PING:states')).to eq(2)
591
+ expect(@redis.lindex('name2:PING:states', 0)).to eq(time_i.to_s)
592
+ expect(@redis.lindex('name2:PING:states', 1)).to eq(time_2_i.to_s)
593
+
594
+ expect(@redis.get("name1:PING:#{time_i}:state")).to be_nil
595
+ expect(@redis.get("name2:PING:#{time_i}:state")).to eq('critical')
596
+ expect(@redis.get("name2:PING:#{time_2_i}:state")).to eq('ok')
597
+
598
+ expect(@redis.get("name1:PING:#{time_i}:summary")).to be_nil
599
+ expect(@redis.get("name2:PING:#{time_i}:summary")).to eq('bad')
600
+ expect(@redis.get("name2:PING:#{time_2_i}:summary")).to eq('good')
601
+
602
+ expect(@redis.zrange("name1:PING:sorted_state_timestamps", 0, -1, :with_scores => true)).to eq(
603
+ [])
604
+ expect(@redis.zrange("name2:PING:sorted_state_timestamps", 0, -1, :with_scores => true)).to eq(
605
+ [[time_i.to_s, time_i.to_f], [time_2_i.to_s, time_2_i.to_f]])
606
+ end
607
+
608
+ it 'merges stored action events' do
609
+ @redis.hset('name1:PING:actions', time_i, 'acknowledgement')
610
+ @redis.hset('name2:PING:actions', time_2_i, 'test_notifications')
611
+
612
+ do_merge
613
+
614
+ expect(@redis.hget('name1:PING:actions', time_i.to_s)).to be_nil
615
+ expect(@redis.hget('name2:PING:actions', time_i.to_s)).to eq('acknowledgement')
616
+ expect(@redis.hget('name2:PING:actions', time_2_i.to_s)).to eq('test_notifications')
617
+ end
618
+
619
+ it 'does not overwrite an entry in the sorted set of failing checks' do
620
+ add_state1
621
+ add_state2
622
+
623
+ @redis.zadd('failed_checks', time_i, 'name1:PING')
624
+ @redis.zadd('failed_checks', time_2_i, 'name2:PING')
625
+
626
+ do_merge
627
+
628
+ expect(@redis.zrange('failed_checks', 0, -1, :with_scores => true)).to eq([['name2:PING', time_2_i.to_f]])
629
+ end
630
+
631
+ it 'merges an entry in the sorted set of failing checks (if no new state data)' do
632
+ add_state1
633
+
634
+ @redis.zadd('failed_checks', time_i, 'name1:PING')
635
+
636
+ do_merge
637
+
638
+ expect(@redis.zrange('failed_checks', 0, -1, :with_scores => true)).to eq([['name2:PING', time_i.to_f]])
639
+ end
640
+
641
+ it 'merges the list of current checks, and its entries' do
642
+ @redis.zadd('current_checks:name1', time_i, 'PING')
643
+ @redis.zadd('current_checks:name2', time_2_i, 'SSH')
644
+
645
+ do_merge
646
+
647
+ expect(@redis.zrange('current_checks:name1', 0, -1, :with_scores => true)).to eq(
648
+ [])
649
+ expect(@redis.zrange('current_checks:name2', 0, -1, :with_scores => true)).to eq(
650
+ [['PING', time_i.to_f], ['SSH', time_2_i.to_f]])
651
+ end
652
+
653
+ it 'removes an entry from the list of current entities' do
654
+ @redis.zadd('current_entities', time_i, 'name1')
655
+ @redis.zadd('current_entities', time_2_i, 'name2')
656
+
657
+ do_merge
658
+
659
+ expect(@redis.zrange('current_entities', 0, -1, :with_scores => true)).to eq([['name2', time_2_i.to_f]])
660
+ end
661
+
662
+ it 'moves an entry within the list of current entities' do
663
+ @redis.zadd('current_entities', time_i, 'name1')
664
+
665
+ do_merge
666
+
667
+ expect(@redis.zrange('current_entities', 0, -1, :with_scores => true)).to eq([['name2', time_i.to_f]])
668
+ end
669
+
670
+ it "renames an unscheduled maintenance key" do
671
+ @redis.setex('name1:PING:unscheduled_maintenance', 30, time_i)
672
+ @redis.zadd('name1:PING:unscheduled_maintenances', 30, time_i)
673
+
674
+ do_merge
675
+
676
+ expect(@redis.get('name1:PING:unscheduled_maintenance')).to be_nil
677
+ expect(@redis.get('name2:PING:unscheduled_maintenance')).to eq(time_i.to_s)
678
+ expect(@redis.ttl('name2:PING:unscheduled_maintenance')).to be <= 30
679
+ end
680
+
681
+ it 'merges an unscheduled maintenance key (older has longest to live)' do
682
+ @redis.setex('name1:PING:unscheduled_maintenance', 60, time_i)
683
+ @redis.zadd('name1:PING:unscheduled_maintenances', 60, time_i)
684
+ @redis.setex('name2:PING:unscheduled_maintenance', 20, time_2_i)
685
+ @redis.zadd('name2:PING:unscheduled_maintenances', 20, time_2_i)
686
+
687
+ do_merge
688
+
689
+ expect(@redis.get('name1:PING:unscheduled_maintenance')).to be_nil
690
+ expect(@redis.get('name2:PING:unscheduled_maintenance')).to eq(time_i.to_s)
691
+ expect(@redis.ttl('name2:PING:unscheduled_maintenance')).to be <= 60
692
+ end
693
+
694
+ it 'merges an unscheduled maintenance key (newer has longest to live)' do
695
+ @redis.setex('name1:PING:unscheduled_maintenance', 40, time_i)
696
+ @redis.zadd('name1:PING:unscheduled_maintenances', 40, time_i)
697
+ @redis.setex('name2:PING:unscheduled_maintenance', 20, time_2_i)
698
+ @redis.zadd('name2:PING:unscheduled_maintenances', 20, time_i)
699
+
700
+ do_merge
701
+
702
+ expect(@redis.get('name1:PING:unscheduled_maintenance')).to be_nil
703
+ expect(@redis.get('name2:PING:unscheduled_maintenance')).to eq(time_2_i.to_s)
704
+ expect(@redis.ttl('name2:PING:unscheduled_maintenance')).to be <= 20
705
+ end
706
+
707
+ it 'merges stored unscheduled maintenance periods and sorted timestamps' do
708
+ @redis.zadd('name1:PING:unscheduled_maintenances', 30, time_i)
709
+ @redis.set("name1:PING:#{time_i}:unscheduled_maintenance:summary", 'really bad')
710
+ @redis.zadd('name1:PING:sorted_unscheduled_maintenance_timestamps', time_i, time_i)
711
+
712
+ @redis.zadd('name2:PING:unscheduled_maintenances', 20, time_2_i)
713
+ @redis.set("name2:PING:#{time_2_i}:unscheduled_maintenance:summary", 'not too bad')
714
+ @redis.zadd('name2:PING:sorted_unscheduled_maintenance_timestamps', time_2_i, time_2_i)
715
+
716
+ do_merge
717
+
718
+ expect(@redis.zrange('name1:PING:unscheduled_maintenances', 0, -1, :with_scores => true)).to eq(
719
+ [])
720
+ expect(@redis.zrange('name2:PING:unscheduled_maintenances', 0, -1, :with_scores => true)).to eq(
721
+ [[time_2_i.to_s, 20.0], [time_i.to_s, 30.0]])
722
+ expect(@redis.get("name1:PING:#{time_i}:unscheduled_maintenance:summary")).to be_nil
723
+ expect(@redis.get("name2:PING:#{time_i}:unscheduled_maintenance:summary")).to eq('really bad')
724
+ expect(@redis.get("name2:PING:#{time_2_i}:unscheduled_maintenance:summary")).to eq('not too bad')
725
+ expect(@redis.zrange('name1:PING:sorted_unscheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq(
726
+ [])
727
+ expect(@redis.zrange('name2:PING:sorted_unscheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq(
728
+ [[time_i.to_s, time_i.to_f], [time_2_i.to_s, time_2_i.to_f]])
729
+ end
730
+
731
+ it "renames a scheduled maintenance key" do
732
+ @redis.setex('name1:PING:scheduled_maintenance', 30, time_i)
733
+
734
+ do_merge
735
+
736
+ expect(@redis.get('name1:PING:scheduled_maintenance')).to be_nil
737
+ expect(@redis.get('name2:PING:scheduled_maintenance')).to eq(time_i.to_s)
738
+ expect(@redis.ttl('name2:PING:scheduled_maintenance')).to be <= 30
739
+ end
740
+
741
+ it 'merges a scheduled maintenance key (older has longer to live)' do
742
+ @redis.setex('name1:PING:scheduled_maintenance', 60, time_i)
743
+ @redis.setex('name2:PING:scheduled_maintenance', 20, time_2_i)
744
+
745
+ do_merge
746
+
747
+ expect(@redis.get('name1:PING:scheduled_maintenance')).to be_nil
748
+ expect(@redis.get('name2:PING:scheduled_maintenance')).to eq(time_i.to_s)
749
+ expect(@redis.ttl('name2:PING:scheduled_maintenance')).to be <= 60
750
+ end
751
+
752
+ it 'merges a scheduled maintenance key (newer has longer to live)' do
753
+ @redis.setex('name1:PING:scheduled_maintenance', 40, time_i)
754
+ @redis.setex('name2:PING:scheduled_maintenance', 20, time_2_i)
755
+
756
+ do_merge
757
+
758
+ expect(@redis.get('name1:PING:scheduled_maintenance')).to be_nil
759
+ expect(@redis.get('name2:PING:scheduled_maintenance')).to eq(time_2_i.to_s)
760
+ expect(@redis.ttl('name2:PING:scheduled_maintenance')).to be <= 20
761
+ end
762
+
763
+ it 'merges stored scheduled maintenance periods and sorted timestamps' do
764
+ @redis.zadd('name1:PING:scheduled_maintenances', 30, time_i)
765
+ @redis.set("name1:PING:#{time_i}:scheduled_maintenance:summary", 'really bad')
766
+ @redis.zadd('name1:PING:sorted_scheduled_maintenance_timestamps', time_i, time_i)
767
+
768
+ @redis.zadd('name2:PING:scheduled_maintenances', 20, time_2_i)
769
+ @redis.set("name2:PING:#{time_2_i}:scheduled_maintenance:summary", 'not too bad')
770
+ @redis.zadd('name2:PING:sorted_scheduled_maintenance_timestamps', time_2_i, time_2_i)
771
+
772
+ do_merge
773
+
774
+ expect(@redis.zrange('name1:PING:scheduled_maintenances', 0, -1, :with_scores => true)).to eq(
775
+ [])
776
+ expect(@redis.zrange('name2:PING:scheduled_maintenances', 0, -1, :with_scores => true)).to eq(
777
+ [[time_2_i.to_s, 20.0], [time_i.to_s, 30.0]])
778
+ expect(@redis.get("name1:PING:#{time_i}:scheduled_maintenance:summary")).to be_nil
779
+ expect(@redis.get("name2:PING:#{time_i}:scheduled_maintenance:summary")).to eq('really bad')
780
+ expect(@redis.get("name2:PING:#{time_2_i}:scheduled_maintenance:summary")).to eq('not too bad')
781
+ expect(@redis.zrange('name1:PING:sorted_scheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq(
782
+ [])
783
+ expect(@redis.zrange('name2:PING:sorted_scheduled_maintenance_timestamps', 0, -1, :with_scores => true)).to eq(
784
+ [[time_i.to_s, time_i.to_f], [time_2_i.to_s, time_2_i.to_f]])
785
+ end
786
+
787
+ it 'merges current notifications, using old timestamp if no new one' do
788
+ @redis.set('name1:PING:last_problem_notification', time_i)
789
+ @redis.set('name1:PING:last_unknown_notification', time_i - 100)
790
+ @redis.set('name1:PING:last_warning_notification', time_i - 50)
791
+ @redis.set('name1:PING:last_critical_notification', time_i)
792
+ @redis.set('name1:PING:last_recovery_notification', time_i - 200)
793
+ @redis.set('name1:PING:last_acknowledgement_notification', time_i - 250)
794
+
795
+ @redis.set('name2:PING:last_problem_notification', time_i + 800)
796
+ @redis.set('name2:PING:last_critical_notification', time_i + 800)
797
+
798
+ do_merge
799
+
800
+ expect(@redis.get('name1:PING:last_problem_notification')).to be_nil
801
+ expect(@redis.get('name1:PING:last_unknown_notification')).to be_nil
802
+ expect(@redis.get('name1:PING:last_warning_notification')).to be_nil
803
+ expect(@redis.get('name1:PING:last_critical_notification')).to be_nil
804
+ expect(@redis.get('name1:PING:last_recovery_notification')).to be_nil
805
+ expect(@redis.get('name1:PING:last_acknowledgement_notification')).to be_nil
806
+
807
+ expect(@redis.get('name2:PING:last_problem_notification')).to eq((time_i + 800).to_s)
808
+ expect(@redis.get('name2:PING:last_unknown_notification')).to eq((time_i - 100).to_s)
809
+ expect(@redis.get('name2:PING:last_warning_notification')).to eq((time_i - 50).to_s)
810
+ expect(@redis.get('name2:PING:last_critical_notification')).to eq((time_i + 800).to_s)
811
+ expect(@redis.get('name2:PING:last_recovery_notification')).to eq((time_i - 200).to_s)
812
+ expect(@redis.get('name2:PING:last_acknowledgement_notification')).to eq((time_i - 250).to_s)
813
+ end
814
+
815
+ it 'merges stored notifications' do
816
+ add_state1
817
+
818
+ @redis.lpush('name1:PING:problem_notifications', time_i)
819
+ @redis.lpush('name1:PING:unknown_notifications', time_i - 100)
820
+ @redis.lpush('name1:PING:warning_notifications', time_i - 50)
821
+ @redis.lpush('name1:PING:critical_notifications', time_i)
822
+ @redis.lpush('name1:PING:recovery_notifications', time_i - 200)
823
+ @redis.lpush('name1:PING:acknowledgement_notifications', time_i - 250)
824
+
825
+ @redis.lpush('name2:PING:problem_notifications', time_i + 800)
826
+ @redis.lpush('name2:PING:unknown_notifications', time_i + 800)
827
+
828
+ do_merge
829
+
830
+ expect(@redis.llen('name1:PING:problem_notifications')).to eq(0)
831
+ expect(@redis.llen('name1:PING:unknown_notifications')).to eq(0)
832
+ expect(@redis.llen('name1:PING:warning_notifications')).to eq(0)
833
+ expect(@redis.llen('name1:PING:critical_notifications')).to eq(0)
834
+ expect(@redis.llen('name1:PING:recovery_notifications')).to eq(0)
835
+ expect(@redis.llen('name1:PING:acknowledgement_notifications')).to eq(0)
836
+ expect(@redis.lindex('name2:PING:problem_notifications', 0)).to eq(time_i.to_s)
837
+ expect(@redis.lindex('name2:PING:problem_notifications', 1)).to eq((time_i + 800).to_s)
838
+ expect(@redis.lindex('name2:PING:unknown_notifications', 0)).to eq((time_i - 100).to_s)
839
+ expect(@redis.lindex('name2:PING:unknown_notifications', 1)).to eq((time_i + 800).to_s)
840
+ expect(@redis.lindex('name2:PING:warning_notifications', 0)).to eq((time_i - 50).to_s)
841
+ expect(@redis.lindex('name2:PING:critical_notifications', 0)).to eq(time_i.to_s)
842
+ expect(@redis.lindex('name2:PING:recovery_notifications', 0)).to eq((time_i - 200).to_s)
843
+ expect(@redis.lindex('name2:PING:acknowledgement_notifications', 0)).to eq((time_i - 250).to_s)
844
+ end
845
+
846
+ it 'merges alerting checks (no notification state for new)' do
847
+ add_state1
848
+
849
+ @redis.zadd('contact_alerting_checks:362:media:email', time_i, 'name1:PING')
850
+
851
+ @redis.lpush('name1:PING:problem_notifications', time_i)
852
+ @redis.lpush('name1:PING:critical_notifications', time_i)
853
+
854
+ do_merge
855
+
856
+ expect(@redis.zrange('contact_alerting_checks:362:media:email', 0, -1, :with_scores => true)).to eq(
857
+ [['name2:PING', time_i.to_f]])
858
+ end
859
+
860
+ it 'merges alerting checks (existing notification state for new)' do
861
+ add_state1
862
+
863
+ @redis.zadd('contact_alerting_checks:362:media:email', time_i, 'name1:PING')
864
+
865
+ @redis.lpush('name1:PING:problem_notifications', time_i)
866
+ @redis.lpush('name1:PING:critical_notifications', time_i)
867
+
868
+ @redis.lpush('name2:PING:problem_notifications', time_i + 100)
869
+ @redis.lpush('name2:PING:critical_notifications', time_i + 100)
870
+ @redis.lpush('name2:PING:recovery_notifications', time_i + 150)
871
+
872
+ do_merge
873
+
874
+ expect(@redis.zrange('contact_alerting_checks:362:media:email', 0, -1, :with_scores => true)).to eq(
875
+ [])
876
+ end
877
+
878
+ it 'merges alert blocks (no notification state for new)' do
879
+ @redis.setex('drop_alerts_for_contact:362:email:name1:PING:critical', 30, 30)
880
+
881
+ do_merge
882
+
883
+ expect(@redis.get('drop_alerts_for_contact:362:email:name1:PING:critical')).to be_nil
884
+ expect(@redis.get('drop_alerts_for_contact:362:email:name2:PING:critical')).to eq(30.to_s)
885
+ expect(@redis.ttl('drop_alerts_for_contact:362:email:name2:PING:critical')).to be <= 30
886
+ end
887
+
888
+ it 'merges alert blocks (older has longer to run)' do
889
+ @redis.setex('drop_alerts_for_contact:362:email:name1:PING:critical', 30, 30)
890
+ @redis.setex('drop_alerts_for_contact:362:email:name2:PING:critical', 10, 10)
891
+
892
+ do_merge
893
+
894
+ expect(@redis.get('drop_alerts_for_contact:362:email:name1:PING:critical')).to be_nil
895
+ expect(@redis.get('drop_alerts_for_contact:362:email:name2:PING:critical')).to eq(30.to_s)
896
+ expect(@redis.ttl('drop_alerts_for_contact:362:email:name2:PING:critical')).to be <= 30
897
+ end
898
+
899
+ it 'merges alert blocks (newer has longer to run)' do
900
+ @redis.setex('drop_alerts_for_contact:362:email:name1:PING:critical', 30, 30)
901
+ @redis.setex('drop_alerts_for_contact:362:email:name2:PING:critical', 60, 60)
902
+
903
+ do_merge
904
+
905
+ expect(@redis.get('drop_alerts_for_contact:362:email:name1:PING:critical')).to be_nil
906
+ expect(@redis.get('drop_alerts_for_contact:362:email:name2:PING:critical')).to eq(60.to_s)
907
+ expect(@redis.ttl('drop_alerts_for_contact:362:email:name2:PING:critical')).to be <= 60
908
+ end
909
+
910
+ end
911
+
912
+ end
913
+
253
914
  end