flapjack 1.1.0 → 1.2.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +12 -7
- data/CHANGELOG.md +12 -0
- data/Gemfile +6 -2
- data/Gemfile-ruby1.9 +29 -0
- data/Gemfile-ruby1.9.lock +251 -0
- data/README.md +2 -2
- data/Rakefile +1 -0
- data/etc/flapjack_config.yaml.example +2 -2
- data/features/steps/events_steps.rb +2 -2
- data/features/steps/flapjack-netsaint-parser_steps.rb +1 -1
- data/features/support/env.rb +1 -6
- data/lib/flapjack/cli/import.rb +2 -5
- data/lib/flapjack/cli/purge.rb +4 -4
- data/lib/flapjack/cli/receiver.rb +122 -54
- data/lib/flapjack/cli/server.rb +0 -5
- data/lib/flapjack/coordinator.rb +6 -0
- data/lib/flapjack/data/contact.rb +10 -62
- data/lib/flapjack/data/entity.rb +36 -52
- data/lib/flapjack/data/entity_check.rb +90 -21
- data/lib/flapjack/data/event.rb +4 -5
- data/lib/flapjack/data/notification.rb +8 -10
- data/lib/flapjack/data/notification_rule.rb +32 -35
- data/lib/flapjack/data/tagged.rb +48 -0
- data/lib/flapjack/gateways/jabber.rb +4 -5
- data/lib/flapjack/gateways/jsonapi/check_methods.rb +45 -7
- data/lib/flapjack/gateways/jsonapi/check_presenter.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +8 -2
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +26 -8
- data/lib/flapjack/gateways/jsonapi/medium_methods.rb +13 -9
- data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +2 -2
- data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +24 -17
- data/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +4 -4
- data/lib/flapjack/gateways/jsonapi.rb +52 -31
- data/lib/flapjack/gateways/oobetet.rb +2 -3
- data/lib/flapjack/gateways/pagerduty.rb +9 -8
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +19 -0
- data/lib/flapjack/gateways/web/public/js/flapjack.js +6 -2
- data/lib/flapjack/gateways/web/public/js/modules/contact.js +9 -14
- data/lib/flapjack/gateways/web/public/js/modules/medium.js +1 -0
- data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +3 -3
- data/lib/flapjack/gateways/web.rb +8 -7
- data/lib/flapjack/notifier.rb +2 -4
- data/lib/flapjack/processor.rb +2 -2
- data/lib/flapjack/version.rb +1 -1
- data/lib/flapjack.rb +10 -0
- data/spec/lib/flapjack/coordinator_spec.rb +18 -0
- data/spec/lib/flapjack/data/contact_spec.rb +4 -12
- data/spec/lib/flapjack/data/entity_check_spec.rb +56 -3
- data/spec/lib/flapjack/data/entity_spec.rb +79 -67
- data/spec/lib/flapjack/data/event_spec.rb +78 -78
- data/spec/lib/flapjack/data/notification_rule_spec.rb +4 -2
- data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +94 -11
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +84 -0
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +5 -3
- data/spec/lib/flapjack/gateways/web_spec.rb +3 -3
- data/spec/service_consumers/pact_helper.rb +74 -0
- data/spec/service_consumers/pacts/flapjack-diner_v1.0.json +4522 -0
- data/spec/service_consumers/provider_states_for_flapjack-diner.rb +356 -0
- data/spec/spec_helper.rb +0 -8
- data/spec/support/jsonapi_helper.rb +1 -1
- data/tasks/benchmarks.rake +6 -3
- data/tasks/profile.rake +1 -1
- data/tmp/acknowledge.rb +0 -3
- data/tmp/create_event_ok.rb +0 -3
- data/tmp/create_event_unknown.rb +0 -3
- data/tmp/create_events_failure.rb +0 -3
- data/tmp/create_events_ok.rb +0 -3
- data/tmp/create_events_ok_fail_ack_ok.rb +0 -3
- data/tmp/create_events_ok_failure.rb +2 -5
- data/tmp/create_events_ok_failure_ack.rb +0 -3
- data/tmp/test_json_post.rb +4 -3
- data/tmp/test_notification_rules_api.rb +2 -3
- metadata +13 -8
- data/lib/flapjack/data/tag.rb +0 -61
- data/lib/flapjack/data/tag_set.rb +0 -16
- 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
|
28
|
-
|
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
|
-
@
|
39
|
+
@redis_options = @config.for_redis
|
40
|
+
end
|
32
41
|
|
33
|
-
|
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
|
-
|
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(
|
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
|
-
:
|
114
|
-
:
|
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 =>
|
127
|
-
:log_path =>
|
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(
|
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
|
-
|
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
|
-
|
340
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
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
|
-
|
377
|
-
|
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(
|
396
|
-
source_redis
|
397
|
-
|
398
|
-
|
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,
|
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
|
data/lib/flapjack/cli/server.rb
CHANGED
data/lib/flapjack/coordinator.rb
CHANGED
@@ -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
|
-
|
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 =>
|
256
|
-
:regex_tags =>
|
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
|
-
|
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
|
-
}
|
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}")
|
data/lib/flapjack/data/entity.rb
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
require 'securerandom'
|
4
4
|
|
5
5
|
require 'flapjack/data/contact'
|
6
|
-
require 'flapjack/data/
|
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
|
-
|
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
|
-
|
456
|
-
|
457
|
-
|
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.
|
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.
|
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
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
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
|
583
|
+
:contacts => opts[:contact_ids] || [],
|
584
|
+
:checks => opts[:check_ids] || [],
|
602
585
|
}
|
603
|
-
}
|
586
|
+
}
|
587
|
+
Flapjack.dump_json(json_data)
|
604
588
|
end
|
605
589
|
|
606
590
|
private
|