flapjack 1.1.0 → 1.2.0rc1

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +12 -7
  5. data/CHANGELOG.md +12 -0
  6. data/Gemfile +6 -2
  7. data/Gemfile-ruby1.9 +29 -0
  8. data/Gemfile-ruby1.9.lock +251 -0
  9. data/README.md +2 -2
  10. data/Rakefile +1 -0
  11. data/etc/flapjack_config.yaml.example +2 -2
  12. data/features/steps/events_steps.rb +2 -2
  13. data/features/steps/flapjack-netsaint-parser_steps.rb +1 -1
  14. data/features/support/env.rb +1 -6
  15. data/lib/flapjack/cli/import.rb +2 -5
  16. data/lib/flapjack/cli/purge.rb +4 -4
  17. data/lib/flapjack/cli/receiver.rb +122 -54
  18. data/lib/flapjack/cli/server.rb +0 -5
  19. data/lib/flapjack/coordinator.rb +6 -0
  20. data/lib/flapjack/data/contact.rb +10 -62
  21. data/lib/flapjack/data/entity.rb +36 -52
  22. data/lib/flapjack/data/entity_check.rb +90 -21
  23. data/lib/flapjack/data/event.rb +4 -5
  24. data/lib/flapjack/data/notification.rb +8 -10
  25. data/lib/flapjack/data/notification_rule.rb +32 -35
  26. data/lib/flapjack/data/tagged.rb +48 -0
  27. data/lib/flapjack/gateways/jabber.rb +4 -5
  28. data/lib/flapjack/gateways/jsonapi/check_methods.rb +45 -7
  29. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +1 -1
  30. data/lib/flapjack/gateways/jsonapi/contact_methods.rb +8 -2
  31. data/lib/flapjack/gateways/jsonapi/entity_methods.rb +26 -8
  32. data/lib/flapjack/gateways/jsonapi/medium_methods.rb +13 -9
  33. data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +2 -2
  34. data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +1 -1
  35. data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +24 -17
  36. data/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb +1 -1
  37. data/lib/flapjack/gateways/jsonapi/report_methods.rb +4 -4
  38. data/lib/flapjack/gateways/jsonapi.rb +52 -31
  39. data/lib/flapjack/gateways/oobetet.rb +2 -3
  40. data/lib/flapjack/gateways/pagerduty.rb +9 -8
  41. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +19 -0
  42. data/lib/flapjack/gateways/web/public/js/flapjack.js +6 -2
  43. data/lib/flapjack/gateways/web/public/js/modules/contact.js +9 -14
  44. data/lib/flapjack/gateways/web/public/js/modules/medium.js +1 -0
  45. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
  46. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +3 -3
  47. data/lib/flapjack/gateways/web.rb +8 -7
  48. data/lib/flapjack/notifier.rb +2 -4
  49. data/lib/flapjack/processor.rb +2 -2
  50. data/lib/flapjack/version.rb +1 -1
  51. data/lib/flapjack.rb +10 -0
  52. data/spec/lib/flapjack/coordinator_spec.rb +18 -0
  53. data/spec/lib/flapjack/data/contact_spec.rb +4 -12
  54. data/spec/lib/flapjack/data/entity_check_spec.rb +56 -3
  55. data/spec/lib/flapjack/data/entity_spec.rb +79 -67
  56. data/spec/lib/flapjack/data/event_spec.rb +78 -78
  57. data/spec/lib/flapjack/data/notification_rule_spec.rb +4 -2
  58. data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +94 -11
  59. data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +84 -0
  60. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +5 -3
  61. data/spec/lib/flapjack/gateways/web_spec.rb +3 -3
  62. data/spec/service_consumers/pact_helper.rb +74 -0
  63. data/spec/service_consumers/pacts/flapjack-diner_v1.0.json +4522 -0
  64. data/spec/service_consumers/provider_states_for_flapjack-diner.rb +356 -0
  65. data/spec/spec_helper.rb +0 -8
  66. data/spec/support/jsonapi_helper.rb +1 -1
  67. data/tasks/benchmarks.rake +6 -3
  68. data/tasks/profile.rake +1 -1
  69. data/tmp/acknowledge.rb +0 -3
  70. data/tmp/create_event_ok.rb +0 -3
  71. data/tmp/create_event_unknown.rb +0 -3
  72. data/tmp/create_events_failure.rb +0 -3
  73. data/tmp/create_events_ok.rb +0 -3
  74. data/tmp/create_events_ok_fail_ack_ok.rb +0 -3
  75. data/tmp/create_events_ok_failure.rb +2 -5
  76. data/tmp/create_events_ok_failure_ack.rb +0 -3
  77. data/tmp/test_json_post.rb +4 -3
  78. data/tmp/test_notification_rules_api.rb +2 -3
  79. metadata +13 -8
  80. data/lib/flapjack/data/tag.rb +0 -61
  81. data/lib/flapjack/data/tag_set.rb +0 -16
  82. data/spec/lib/flapjack/data/tag_spec.rb +0 -36
@@ -2,9 +2,7 @@
2
2
 
3
3
  require 'dante'
4
4
  require 'redis'
5
-
6
- require 'oj'
7
- Oj.default_options = { :indent => 0, :mode => :strict }
5
+ require 'hiredis'
8
6
 
9
7
  require 'flapjack/configuration'
10
8
  require 'flapjack/data/event'
@@ -21,16 +19,28 @@ module Flapjack
21
19
  @options = options
22
20
 
23
21
  @config = Flapjack::Configuration.new
24
- @config.load(global_options[:config])
25
- @config_env = @config.all
26
22
 
27
- if @config_env.nil? || @config_env.empty?
28
- exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
23
+ if 'mirror'.eql?(@options[:type]) &&
24
+ (global_options[:config].nil? || global_options[:config].strip.empty?)
25
+
26
+ @config_env = {}
27
+ @config_runner = {}
28
+ else
29
+ @config.load(global_options[:config])
30
+ @config_env = @config.all
31
+
32
+ if @config_env.nil? || @config_env.empty?
33
+ exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
34
+ end
35
+
36
+ @config_runner = @config_env["#{@options[:type]}-receiver"] || {}
29
37
  end
30
38
 
31
- @config_runner = @config_env["#{@options[:type]}-receiver"] || {}
39
+ @redis_options = @config.for_redis
40
+ end
32
41
 
33
- @pidfile = case
42
+ def pidfile
43
+ @pidfile ||= case
34
44
  when !@options[:pidfile].nil?
35
45
  @options[:pidfile]
36
46
  when !@config_env['pid_dir'].nil?
@@ -38,8 +48,10 @@ module Flapjack
38
48
  else
39
49
  "/var/run/flapjack/#{@options[:type]}-receiver.pid"
40
50
  end
51
+ end
41
52
 
42
- @logfile = case
53
+ def logfile
54
+ @logfile ||= case
43
55
  when !@options[:logfile].nil?
44
56
  @options[:logfile]
45
57
  when !@config_env['log_dir'].nil?
@@ -47,8 +59,6 @@ module Flapjack
47
59
  else
48
60
  "/var/run/flapjack/#{@options[:type]}-receiver.log"
49
61
  end
50
-
51
- @redis_options = @config.for_redis
52
62
  end
53
63
 
54
64
  def start
@@ -97,7 +107,7 @@ module Flapjack
97
107
  def status
98
108
  if runner(@options[:type]).daemon_running?
99
109
  pid = get_pid
100
- uptime = Time.now - File.stat(@pidfile).ctime
110
+ uptime = Time.now - File.stat(pidfile).ctime
101
111
  puts "#{@options[:type]}-receiver is running: pid #{pid}, uptime #{uptime}"
102
112
  else
103
113
  exit_now! "#{@options[:type]}-receiver is not running"
@@ -109,22 +119,30 @@ module Flapjack
109
119
  end
110
120
 
111
121
  def mirror
122
+ if (@options[:dest].nil? || @options[:dest].strip.empty?) &&
123
+ @redis_options.nil?
124
+
125
+ exit_now! "No destination redis URL passed, and none configured"
126
+ end
127
+
112
128
  mirror_receive(:source => @options[:source],
113
- :all => @options[:all], :follow => @options[:follow],
114
- :last => @options[:last], :time => @options[:time])
129
+ :dest => @options[:dest] || @redis_options,
130
+ :include => @options[:include], :all => @options[:all],
131
+ :follow => @options[:follow], :last => @options[:last],
132
+ :time => @options[:time])
115
133
  end
116
134
 
117
135
  private
118
136
 
119
137
  def redis
120
- @redis ||= Redis.new(@redis_options)
138
+ @redis ||= Redis.new(@redis_options.merge(:driver => :hiredis))
121
139
  end
122
140
 
123
141
  def runner(type)
124
142
  return @runner if @runner
125
143
 
126
- @runner = Dante::Runner.new("#{@options[:type]}-receiver", :pid_path => @pidfile,
127
- :log_path => @logfile)
144
+ @runner = Dante::Runner.new("#{@options[:type]}-receiver", :pid_path => pidfile,
145
+ :log_path => logfile)
128
146
  @runner
129
147
  end
130
148
 
@@ -254,7 +272,7 @@ module Flapjack
254
272
  end
255
273
 
256
274
  def get_pid
257
- IO.read(@pidfile).chomp.to_i
275
+ IO.read(pidfile).chomp.to_i
258
276
  rescue StandardError
259
277
  pid = nil
260
278
  end
@@ -298,7 +316,6 @@ module Flapjack
298
316
  end
299
317
 
300
318
  def json_feeder(opts = {})
301
-
302
319
  input = if opts[:from]
303
320
  File.open(opts[:from]) # Explodes if file does not exist.
304
321
  elsif $stdin.tty?
@@ -328,16 +345,30 @@ module Flapjack
328
345
  puts "Done."
329
346
  end
330
347
 
331
-
332
348
  def mirror_receive(opts)
333
349
  unless opts[:follow] || opts[:all]
334
350
  exit_now! "one or both of --follow or --all is required"
335
351
  end
336
352
 
337
- source_redis = Redis.new(:url => opts[:source])
353
+ include_re = nil
354
+ unless opts[:include].nil? || opts[:include].strip.empty?
355
+ begin
356
+ include_re = Regexp.new(opts[:include].strip)
357
+ rescue RegexpError
358
+ exit_now! "could not parse include Regexp: #{opts[:include].strip}"
359
+ end
360
+ end
361
+
362
+ source_addr = opts[:source]
363
+ source_redis = Redis.new(:url => source_addr, :driver => :hiredis)
338
364
 
339
- archives = mirror_get_archive_keys_stats(source_redis)
340
- raise "found no archives!" unless archives && archives.length > 0
365
+ dest_addr = opts[:dest]
366
+ dest_redis = Redis.new(:url => dest_addr, :driver => :hiredis)
367
+
368
+ refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis)
369
+ archives = mirror_get_archive_keys_stats(source_addr, :source => source_redis,
370
+ :dest => dest_redis)
371
+ raise "found no archives!" if archives.empty?
341
372
 
342
373
  puts "found archives: #{archives.inspect}"
343
374
 
@@ -350,53 +381,85 @@ module Flapjack
350
381
  events_sent = 0
351
382
  case
352
383
  when opts[:all]
353
- archive_key = archives[0][:name]
384
+ archive_idx = 0
354
385
  cursor = -1
355
386
  when opts[:last], opts[:time]
356
387
  raise "Sorry, unimplemented"
357
388
  else
358
389
  # wait for the next event to be archived, so point the cursor at a non-existant
359
390
  # slot in the list, the one before the 0'th
360
- archive_key = archives[-1][:name]
391
+ archive_idx = archives.size - 1
361
392
  cursor = -1 - archives[-1][:size]
362
393
  end
363
394
 
395
+ archive_key = archives[archive_idx][:name]
364
396
  puts archive_key
365
397
 
366
398
  loop do
367
- new_archive_key = false
368
- # something to read at cursor?
369
- event = source_redis.lindex(archive_key, cursor)
370
- if event
371
- Flapjack::Data::Event.add(event, :redis => redis)
372
- events_sent += 1
373
- print "#{events_sent} " if events_sent % 1000 == 0
399
+ event_json = source_redis.lindex(archive_key, cursor)
400
+ if event_json
401
+ event = Flapjack::Data::Event.parse_and_validate(event_json)
402
+ if !event.nil? && (include_re.nil? ||
403
+ (include_re === "#{event['entity']}:#{event['check']}"))
404
+
405
+ Flapjack::Data::Event.add(event, :redis => dest_redis)
406
+ events_sent += 1
407
+ print "#{events_sent} " if events_sent % 1000 == 0
408
+ end
374
409
  cursor -= 1
410
+ next
411
+ end
412
+
413
+ archives = mirror_get_archive_keys_stats(source_addr,
414
+ :source => source_redis, :dest => dest_redis)
415
+
416
+ if archives.any? {|a| a[:size] == 0}
417
+ # data may be out of date -- refresh, then reject any immediately
418
+ # expired keys directly; don't keep chasing updated data
419
+ refresh_archive_index(source_addr, :source => source_redis, :dest => dest_redis)
420
+ archives = mirror_get_archive_keys_stats(source_addr,
421
+ :source => source_redis, :dest => dest_redis).select {|a| a[:size] > 0}
422
+ end
423
+
424
+ if archives.empty?
425
+ sleep 1
426
+ next
427
+ end
428
+
429
+ archive_idx = archives.index {|a| a[:name] == archive_key }
430
+ archive_idx = archive_idx.nil? ? 0 : (archive_idx + 1)
431
+ if archives[archive_idx]
432
+ archive_key = archives[archive_idx][:name]
433
+ puts archive_key
434
+ cursor = -1
375
435
  else
376
- puts "\narchive key: #{archive_key}, cursor: #{cursor}"
377
- # do we need to look at the next archive bucket?
378
- archives = mirror_get_archive_keys_stats(source_redis)
379
- i = archives.index {|a| a[:name] == archive_key }
380
- if archives[i][:size] = (cursor.abs + 1)
381
- if archives[i + 1]
382
- archive_key = archives[i + 1][:name]
383
- puts archive_key
384
- cursor = -1
385
- new_archive_key = true
386
- else
387
- return unless opts[:follow]
388
- end
389
- end
390
- sleep 1 unless new_archive_key
436
+ break unless opts[:follow]
437
+ sleep 1
391
438
  end
392
439
  end
393
440
  end
394
441
 
395
- def mirror_get_archive_keys_stats(source_redis)
396
- source_redis.keys("events_archive:*").sort.map {|a|
397
- { :name => a,
398
- :size => source_redis.llen(a) }
399
- }
442
+ def mirror_get_archive_keys_stats(name, opts = {})
443
+ source_redis = opts[:source]
444
+ dest_redis = opts[:dest]
445
+ dest_redis.smembers("known_events_archive_keys:#{name}").sort.collect do |eak|
446
+ {:name => eak, :size => source_redis.llen(eak)}
447
+ end
448
+ end
449
+
450
+ def refresh_archive_index(name, opts = {})
451
+ source_redis = opts[:source]
452
+ dest_redis = opts[:dest]
453
+ # refresh the key name cache, avoid repeated calls to redis KEYS
454
+ # this cache will be updated any time a new archive bucket is created
455
+ archive_keys = source_redis.keys("events_archive:*").group_by do |ak|
456
+ (source_redis.llen(ak) > 0) ? 't' : 'f'
457
+ end
458
+
459
+ {'f' => :srem, 't' => :sadd}.each_pair do |k, cmd|
460
+ next unless archive_keys.has_key?(k) && !archive_keys[k].empty?
461
+ dest_redis.send(cmd, "known_events_archive_keys:#{name}", archive_keys[k])
462
+ end
400
463
  end
401
464
 
402
465
  end
@@ -596,9 +659,13 @@ command :receiver do |receiver|
596
659
  receiver.desc 'Mirror receiver'
597
660
  receiver.command :mirror do |mirror|
598
661
 
599
- mirror.flag [:s, 'source'], :desc => 'URL of source redis database, eg redis://localhost:6379/0',
662
+ mirror.flag [:s, 'source'], :desc => 'URL of source redis database, e.g. redis://localhost:6379/0',
600
663
  :required => true
601
664
 
665
+ mirror.flag [:d, 'dest'], :desc => 'URL of destination redis database, e.g. redis://localhost:6379/1'
666
+
667
+ mirror.flag [:i, 'include'], :desc => 'Regexp which must match event id for it to be mirrored'
668
+
602
669
  # one or both of follow, all is required
603
670
  mirror.switch [:f, 'follow'], :desc => 'keep reading events as they are archived on the source',
604
671
  :default_value => nil
@@ -615,6 +682,7 @@ command :receiver do |receiver|
615
682
  :default_value => nil
616
683
 
617
684
  mirror.action do |global_options,options,args|
685
+ options.merge!(:type => 'mirror')
618
686
  receiver = Flapjack::CLI::Receiver.new(global_options, options)
619
687
  receiver.mirror
620
688
  end
@@ -2,11 +2,6 @@
2
2
 
3
3
  require 'dante'
4
4
 
5
- require 'oj'
6
- Oj.mimic_JSON
7
- Oj.default_options = { :indent => 0, :mode => :strict }
8
- require 'active_support/json'
9
-
10
5
  require 'flapjack/coordinator'
11
6
 
12
7
  module Flapjack
@@ -32,6 +32,12 @@ module Flapjack
32
32
  EM.synchrony do
33
33
  setup_signals if options[:signals]
34
34
 
35
+ redis = Flapjack::RedisPool.new(:config => @redis_options, :size => 1)
36
+ ['entity', 'check'].each do |type|
37
+ discovered = redis.keys("#{type}_tag:*")
38
+ redis.sadd("known_tags:#{type}_tag", discovered) unless discovered.empty?
39
+ end
40
+
35
41
  begin
36
42
  add_pikelets(pikelets(@config.all))
37
43
  loop do
@@ -7,8 +7,6 @@ require 'set'
7
7
  require 'ice_cube'
8
8
  require 'flapjack/data/entity'
9
9
  require 'flapjack/data/notification_rule'
10
- require 'flapjack/data/tag'
11
- require 'flapjack/data/tag_set'
12
10
 
13
11
  require 'securerandom'
14
12
 
@@ -21,7 +19,6 @@ module Flapjack
21
19
  attr_accessor :id, :first_name, :last_name, :email, :media,
22
20
  :media_intervals, :media_rollup_thresholds, :pagerduty_credentials
23
21
 
24
- TAG_PREFIX = 'contact_tag'
25
22
  ALL_MEDIA = ['email', 'sms', 'sms_twilio', 'jabber', 'pagerduty', 'sns']
26
23
 
27
24
  def self.all(options = {})
@@ -75,9 +72,12 @@ module Flapjack
75
72
  end
76
73
 
77
74
  self.add_or_update(contact_id, contact_data, :redis => redis)
78
- if contact = self.find_by_id(contact_id, :redis => redis)
75
+ contact = self.find_by_id(contact_id, :redis => redis)
76
+
77
+ unless contact.nil?
79
78
  contact.notification_rules # invoke to create general rule
80
79
  end
80
+
81
81
  contact
82
82
  end
83
83
 
@@ -128,9 +128,6 @@ module Flapjack
128
128
  # the main alerts sorted set, remove all alerts_by sorted sets
129
129
  # for the contact
130
130
 
131
- # remove this contact from all tags it's marked with
132
- self.delete_tags(*self.tags.to_a)
133
-
134
131
  # remove all associated notification rules
135
132
  self.notification_rules.each do |nr|
136
133
  self.delete_notification_rule(nr)
@@ -252,8 +249,8 @@ module Flapjack
252
249
  rule = self.add_notification_rule({
253
250
  :entities => [],
254
251
  :regex_entities => [],
255
- :tags => Flapjack::Data::TagSet.new([]),
256
- :regex_tags => Flapjack::Data::TagSet.new([]),
252
+ :tags => Set.new([]),
253
+ :regex_tags => Set.new([]),
257
254
  :time_restrictions => [],
258
255
  :warning_media => ALL_MEDIA,
259
256
  :critical_media => ALL_MEDIA,
@@ -415,37 +412,6 @@ module Flapjack
415
412
  @redis.zcard("contact_alerting_checks:#{self.id}:media:#{media}")
416
413
  end
417
414
 
418
- # FIXME
419
- # do a mixin with the following tag methods, they will be the same
420
- # across all objects we allow tags on
421
-
422
- # return the set of tags for this contact
423
- def tags
424
- @tags ||= Flapjack::Data::TagSet.new( @redis.keys("#{TAG_PREFIX}:*").inject([]) {|memo, tag|
425
- if Flapjack::Data::Tag.find(tag, :redis => @redis).include?(@id.to_s)
426
- memo << tag.sub(/^#{TAG_PREFIX}:/, '')
427
- end
428
- memo
429
- } )
430
- end
431
-
432
- # adds tags to this contact
433
- def add_tags(*enum)
434
- enum.each do |t|
435
- Flapjack::Data::Tag.create("#{TAG_PREFIX}:#{t}", [@id], :redis => @redis)
436
- tags.add(t)
437
- end
438
- end
439
-
440
- # removes tags from this contact
441
- def delete_tags(*enum)
442
- enum.each do |t|
443
- tag = Flapjack::Data::Tag.find("#{TAG_PREFIX}:#{t}", :redis => @redis)
444
- tag.delete(@id)
445
- tags.delete(t)
446
- end
447
- end
448
-
449
415
  # return a list of media enabled for this contact
450
416
  # eg [ 'email', 'sms' ]
451
417
  def media_list
@@ -488,32 +454,20 @@ module Flapjack
488
454
  end
489
455
  end
490
456
 
491
- def to_json(*args)
492
- { "id" => self.id,
493
- "first_name" => self.first_name,
494
- "last_name" => self.last_name,
495
- "email" => self.email,
496
- "media" => self.media,
497
- "media_intervals" => self.media_intervals,
498
- "media_rollup_thresholds" => self.media_rollup_thresholds,
499
- "timezone" => self.timezone.name,
500
- "tags" => self.tags.to_a
501
- }.to_json
502
- end
503
-
504
457
  def to_jsonapi(opts = {})
505
- { "id" => self.id,
458
+ json_data = {
459
+ "id" => self.id,
506
460
  "first_name" => self.first_name,
507
461
  "last_name" => self.last_name,
508
462
  "email" => self.email,
509
463
  "timezone" => self.timezone.name,
510
- "tags" => self.tags.to_a,
511
464
  "links" => {
512
465
  :entities => opts[:entity_ids] || [],
513
466
  :media => self.media_ids || [],
514
467
  :notification_rules => self.notification_rule_ids || [],
515
468
  }
516
- }.to_json
469
+ }
470
+ Flapjack.dump_json(json_data)
517
471
  end
518
472
 
519
473
  private
@@ -536,12 +490,6 @@ module Flapjack
536
490
 
537
491
  redis.hmset("contact:#{contact_id}", *attrs) unless attrs.empty?
538
492
 
539
- if ( ! contact_data['tags'].nil? && contact_data['tags'].is_a?(Enumerable))
540
- contact_data['tags'].each do |t|
541
- Flapjack::Data::Tag.create("#{TAG_PREFIX}:#{t}", [contact_id], :redis => redis)
542
- end
543
- end
544
-
545
493
  unless contact_data['media'].nil?
546
494
  redis.del("contact_media:#{contact_id}")
547
495
  redis.del("contact_media_intervals:#{contact_id}")
@@ -3,8 +3,7 @@
3
3
  require 'securerandom'
4
4
 
5
5
  require 'flapjack/data/contact'
6
- require 'flapjack/data/tag'
7
- require 'flapjack/data/tag_set'
6
+ require 'flapjack/data/tagged'
8
7
 
9
8
  module Flapjack
10
9
 
@@ -14,7 +13,7 @@ module Flapjack
14
13
 
15
14
  attr_accessor :name, :id
16
15
 
17
- TAG_PREFIX = 'entity_tag'
16
+ include Tagged
18
17
 
19
18
  def self.all(options = {})
20
19
  raise "Redis connection not set" unless redis = options[:redis]
@@ -452,9 +451,14 @@ module Flapjack
452
451
  redis.sadd("contacts_for:#{entity_id}", contact_id)
453
452
  }
454
453
  end
455
- self.new(:name => entity_name,
456
- :id => entity_id,
457
- :redis => redis)
454
+
455
+ e = self.new(:name => entity_name,
456
+ :id => entity_id,
457
+ :redis => redis)
458
+ if entity['tags'] && entity['tags'].respond_to?(:each)
459
+ e.add_tags(*entity['tags'])
460
+ end
461
+ e
458
462
  end
459
463
 
460
464
  def self.find_by_name(entity_name, options = {})
@@ -508,25 +512,14 @@ module Flapjack
508
512
  }.sort
509
513
  end
510
514
 
511
- def self.find_all_with_tags(tags, options = {})
512
- raise "Redis connection not set" unless redis = options[:redis]
513
- tags_prefixed = tags.collect {|tag|
514
- "#{TAG_PREFIX}:#{tag}"
515
- }
516
- logger.debug "tags_prefixed: #{tags_prefixed.inspect}" if logger = options[:logger]
517
- Flapjack::Data::Tag.find_intersection(tags_prefixed, :redis => redis).collect {|entity_id|
518
- Flapjack::Data::Entity.find_by_id(entity_id, :redis => redis).name
519
- }.compact
520
- end
521
-
522
515
  def self.current_names(options = {})
523
516
  raise "Redis connection not set" unless redis = options[:redis]
524
517
  redis.zrange('current_entities', 0, -1)
525
518
  end
526
519
 
527
- def self.find_all_with_failing_checks(options)
520
+ def self.find_all_names_with_failing_checks(options)
528
521
  raise "Redis connection not set" unless redis = options[:redis]
529
- Flapjack::Data::EntityCheck.find_current_failing_by_entity(:redis => redis).keys
522
+ Flapjack::Data::EntityCheck.find_current_names_failing_by_entity(:redis => redis).keys
530
523
  end
531
524
 
532
525
  def contacts
@@ -552,6 +545,19 @@ module Flapjack
552
545
  end
553
546
  end
554
547
 
548
+ def self.check_ids_for(entity_ids, options = {})
549
+ raise "Redis connection not set" unless redis = options[:redis]
550
+
551
+ entity_ids.inject({}) do |memo, entity_id|
552
+ entity_name = redis.hget("entity:#{entity_id}", 'name')
553
+ unless entity_name.nil? || entity_name.empty?
554
+ checks = Flapjack::Data::EntityCheck.find_all_names_for_entity_name(entity_name, :redis => redis)
555
+ memo[entity_id] = checks.collect {|check| "#{entity_name}:#{check}" }
556
+ end
557
+ memo
558
+ end
559
+ end
560
+
555
561
  def check_list
556
562
  @redis.zrange("current_checks:#{@name}", 0, -1)
557
563
  end
@@ -562,45 +568,23 @@ module Flapjack
562
568
  checks.length
563
569
  end
564
570
 
565
- def tags
566
- @tags ||= Flapjack::Data::TagSet.new( @redis.keys("#{TAG_PREFIX}:*").inject([]) {|memo, entity_tag|
567
- if Flapjack::Data::Tag.find(entity_tag, :redis => @redis).include?(@id.to_s)
568
- memo << entity_tag.sub(/^#{TAG_PREFIX}:/, '')
569
- end
570
- memo
571
- } )
572
- end
573
-
574
- def add_tags(*enum)
575
- enum.each do |t|
576
- Flapjack::Data::Tag.create("#{TAG_PREFIX}:#{t}", [@id], :redis => @redis)
577
- tags.add(t)
578
- end
579
- end
580
-
581
- def delete_tags(*enum)
582
- enum.each do |t|
583
- tag = Flapjack::Data::Tag.find("#{TAG_PREFIX}:#{t}", :redis => @redis)
584
- tag.delete(@id)
585
- tags.delete(t)
586
- end
587
- end
588
-
589
- def as_json(*args)
590
- {
591
- "id" => self.id,
592
- "name" => self.name,
593
- }
594
- end
571
+ # def as_json(*args)
572
+ # {
573
+ # "id" => self.id,
574
+ # "name" => self.name,
575
+ # }
576
+ # end
595
577
 
596
578
  def to_jsonapi(opts = {})
597
- {
579
+ json_data = {
598
580
  "id" => self.id,
599
581
  "name" => self.name,
600
582
  "links" => {
601
- :contacts => opts[:contact_ids] || [],
583
+ :contacts => opts[:contact_ids] || [],
584
+ :checks => opts[:check_ids] || [],
602
585
  }
603
- }.to_json
586
+ }
587
+ Flapjack.dump_json(json_data)
604
588
  end
605
589
 
606
590
  private