flapjack 1.0.0rc3 → 1.0.0rc5

Sign up to get free protection for your applications and to get access to all the features.
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