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
@@ -1,12 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'oj'
|
4
|
-
|
5
3
|
require 'flapjack/patches'
|
6
4
|
|
7
5
|
require 'flapjack/data/contact'
|
8
6
|
require 'flapjack/data/event'
|
9
7
|
require 'flapjack/data/entity'
|
8
|
+
require 'flapjack/data/tagged'
|
9
|
+
|
10
10
|
#FIXME: Require chronic_duration in the correct place
|
11
11
|
require 'chronic_duration'
|
12
12
|
|
@@ -27,8 +27,37 @@ module Flapjack
|
|
27
27
|
NOTIFICATION_STATES = [:problem, :warning, :critical, :unknown,
|
28
28
|
:recovery, :acknowledgement]
|
29
29
|
|
30
|
+
include Tagged
|
31
|
+
|
30
32
|
attr_accessor :entity, :check
|
31
33
|
|
34
|
+
def self.add(check_data, options = {})
|
35
|
+
raise "Redis connection not set" unless redis = options[:redis]
|
36
|
+
|
37
|
+
entity_id = check_data['entity_id']
|
38
|
+
raise "Entity id not provided" if entity_id.nil? || entity_id.empty?
|
39
|
+
|
40
|
+
check_name = check_data['name']
|
41
|
+
raise "Name not provided" if check_name.nil? || check_name.empty?
|
42
|
+
|
43
|
+
ent = Flapjack::Data::Entity.find_by_id(entity_id, :redis => redis)
|
44
|
+
|
45
|
+
raise "Entity not found for id '#{entity_id}'" if ent.nil?
|
46
|
+
|
47
|
+
logger = options[:logger]
|
48
|
+
timestamp = Time.now.to_i
|
49
|
+
|
50
|
+
redis.zadd("current_checks:#{ent.name}", timestamp, check_name)
|
51
|
+
redis.zadd('current_entities', timestamp, ent.name)
|
52
|
+
|
53
|
+
c = self.new(ent, check_name, :logger => logger,
|
54
|
+
:redis => redis)
|
55
|
+
if check_data['tags'] && check_data['tags'].respond_to?(:each)
|
56
|
+
c.add_tags(*check_data['tags'])
|
57
|
+
end
|
58
|
+
c
|
59
|
+
end
|
60
|
+
|
32
61
|
def self.for_event_id(event_id, options = {})
|
33
62
|
raise "Redis connection not set" unless redis = options[:redis]
|
34
63
|
entity_name, check_name = event_id.split(':', 2)
|
@@ -36,6 +65,7 @@ module Flapjack
|
|
36
65
|
logger = options[:logger]
|
37
66
|
entity = Flapjack::Data::Entity.find_by_name(entity_name,
|
38
67
|
:create => create_entity, :logger => logger, :redis => redis)
|
68
|
+
return if entity.nil?
|
39
69
|
self.new(entity, check_name, :logger => logger, :redis => redis)
|
40
70
|
end
|
41
71
|
|
@@ -65,23 +95,30 @@ module Flapjack
|
|
65
95
|
|
66
96
|
def self.all(options = {})
|
67
97
|
raise "Redis connection not set" unless redis = options[:redis]
|
68
|
-
checks = redis.keys('check:*').map {|c| c.match(/^check:(
|
98
|
+
checks = redis.keys('check:*').map {|c| c.match(/^check:(.+)$/) ; $1} |
|
99
|
+
find_current_names(:redis => redis)
|
69
100
|
checks.map {|ec|
|
70
|
-
self.
|
101
|
+
self.for_event_id(ec, options)
|
71
102
|
}
|
72
103
|
end
|
73
104
|
|
74
|
-
def self.
|
105
|
+
def self.find_all_names_for_entity_name(entity_name, options = {})
|
106
|
+
raise "Redis connection not set" unless redis = options[:redis]
|
107
|
+
en = Regexp.escape(entity_name)
|
108
|
+
redis.keys('check:*').map {|c| c.match(/^check:#{en}:(.+)$/); $1}
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.find_current_names_for_entity_name(entity_name, options = {})
|
75
112
|
raise "Redis connection not set" unless redis = options[:redis]
|
76
113
|
redis.zrange("current_checks:#{entity_name}", 0, -1)
|
77
114
|
end
|
78
115
|
|
79
|
-
def self.
|
116
|
+
def self.find_current_names(options = {})
|
80
117
|
raise "Redis connection not set" unless redis = options[:redis]
|
81
|
-
self.conflate_to_keys(self.
|
118
|
+
self.conflate_to_keys(self.find_current_names_by_entity(:redis => redis))
|
82
119
|
end
|
83
120
|
|
84
|
-
def self.
|
121
|
+
def self.find_current_names_by_entity(options = {})
|
85
122
|
raise "Redis connection not set" unless redis = options[:redis]
|
86
123
|
d = {}
|
87
124
|
redis.zrange("current_entities", 0, -1).each {|entity|
|
@@ -97,12 +134,12 @@ module Flapjack
|
|
97
134
|
}
|
98
135
|
end
|
99
136
|
|
100
|
-
def self.
|
137
|
+
def self.find_current_names_failing(options = {})
|
101
138
|
raise "Redis connection not set" unless redis = options[:redis]
|
102
|
-
self.conflate_to_keys(self.
|
139
|
+
self.conflate_to_keys(self.find_current_names_failing_by_entity(:redis => redis))
|
103
140
|
end
|
104
141
|
|
105
|
-
def self.
|
142
|
+
def self.find_current_names_failing_by_entity(options = {})
|
106
143
|
raise "Redis connection not set" unless redis = options[:redis]
|
107
144
|
redis.zrange("failed_checks", 0, -1).inject({}) do |memo, key|
|
108
145
|
entity, check = key.split(':', 2)
|
@@ -642,13 +679,21 @@ module Flapjack
|
|
642
679
|
# disables a check (removes currency)
|
643
680
|
def disable!
|
644
681
|
@logger.debug("disabling check [#{@key}]") if @logger
|
645
|
-
|
646
|
-
|
647
|
-
|
682
|
+
entity_name = entity.name
|
683
|
+
@redis.zrem("current_checks:#{entity_name}", check)
|
684
|
+
if @redis.zcount("current_checks:#{entity_name}", '-inf', '+inf') == 0
|
685
|
+
@redis.zrem("current_checks:#{entity_name}", check)
|
648
686
|
@redis.zrem("current_entities", entity.name)
|
649
687
|
end
|
650
688
|
end
|
651
689
|
|
690
|
+
def enable!
|
691
|
+
timestamp = Time.now.to_i
|
692
|
+
entity_name = entity.name
|
693
|
+
redis.zadd("current_checks:#{entity_name}", timestamp, check)
|
694
|
+
redis.zadd('current_entities', timestamp, entity_name)
|
695
|
+
end
|
696
|
+
|
652
697
|
def enabled?
|
653
698
|
!!@redis.zscore("current_checks:#{entity.name}", check)
|
654
699
|
end
|
@@ -855,13 +900,24 @@ module Flapjack
|
|
855
900
|
}.compact
|
856
901
|
end
|
857
902
|
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
903
|
+
# override default, which would be 'entity_check_tag'
|
904
|
+
def tag_prefix
|
905
|
+
'check_tag'
|
906
|
+
end
|
907
|
+
|
908
|
+
def tags_with_entity_and_check_name
|
909
|
+
tags_without_entity_and_check_name
|
910
|
+
|
911
|
+
# ensure that returned tags include split entity and check words
|
912
|
+
@tags += @entity.name.split('.', 2).map {|x| x.downcase} +
|
913
|
+
@check.split(' ').map {|x| x.downcase}
|
914
|
+
|
915
|
+
@tags
|
863
916
|
end
|
864
917
|
|
918
|
+
alias_method :tags_without_entity_and_check_name, :tags
|
919
|
+
alias_method :tags, :tags_with_entity_and_check_name
|
920
|
+
|
865
921
|
def ack_hash
|
866
922
|
@ack_hash ||= @redis.hget('check_hashes_by_id', @key)
|
867
923
|
if @ack_hash.nil?
|
@@ -905,14 +961,27 @@ module Flapjack
|
|
905
961
|
purge_stamps.length
|
906
962
|
end
|
907
963
|
|
964
|
+
def self.enabled_for(check_ids, opts = {})
|
965
|
+
raise "Redis connection not set" unless redis = opts[:redis]
|
966
|
+
|
967
|
+
check_ids.inject([]) do |memo, check_id|
|
968
|
+
entity_name, check_name = check_id.split(':', 2)
|
969
|
+
memo << check_id unless redis.zscore("current_checks:#{entity_name}", check_name).nil?
|
970
|
+
memo
|
971
|
+
end
|
972
|
+
end
|
973
|
+
|
908
974
|
def to_jsonapi(opts = {})
|
909
|
-
{
|
975
|
+
json_data = {
|
976
|
+
"id" => @key,
|
910
977
|
"name" => @check,
|
911
978
|
"entity_name" => @entity.name,
|
979
|
+
"enabled" => opts[:enabled].is_a?(TrueClass),
|
912
980
|
"links" => {
|
913
981
|
:entities => opts[:entity_ids] || [],
|
914
982
|
}
|
915
|
-
}
|
983
|
+
}
|
984
|
+
Flapjack.dump_json(json_data)
|
916
985
|
end
|
917
986
|
|
918
987
|
private
|
data/lib/flapjack/data/event.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'flapjack/data/tag_set'
|
3
|
+
require 'flapjack'
|
5
4
|
|
6
5
|
module Flapjack
|
7
6
|
module Data
|
@@ -120,7 +119,7 @@ module Flapjack
|
|
120
119
|
|
121
120
|
def self.parse_and_validate(raw, opts = {})
|
122
121
|
errors = []
|
123
|
-
if parsed = ::
|
122
|
+
if parsed = ::Flapjack.load_json(raw)
|
124
123
|
if parsed.is_a?(Hash)
|
125
124
|
errors = validation_errors_for_hash(parsed, opts)
|
126
125
|
else
|
@@ -177,7 +176,7 @@ module Flapjack
|
|
177
176
|
raise "Redis connection not set" unless redis = opts[:redis]
|
178
177
|
|
179
178
|
evt['time'] = Time.now.to_i if evt['time'].nil?
|
180
|
-
redis.lpush('events', ::
|
179
|
+
redis.lpush('events', ::Flapjack.dump_json(evt))
|
181
180
|
end
|
182
181
|
|
183
182
|
# Provide a count of the number of events on the queue to be processed.
|
@@ -220,7 +219,7 @@ module Flapjack
|
|
220
219
|
# perfdata is optional. set it to nil if it only contains whitespace
|
221
220
|
@perfdata = (@perfdata.is_a?(String) && ! @perfdata.strip.empty?) ? @perfdata.strip : nil
|
222
221
|
if attrs['tags']
|
223
|
-
@tags =
|
222
|
+
@tags = Set.new
|
224
223
|
attrs['tags'].each {|tag| @tags.add(tag)}
|
225
224
|
end
|
226
225
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'oj'
|
4
|
-
|
5
3
|
require 'flapjack/data/contact'
|
6
4
|
require 'flapjack/data/event'
|
7
5
|
require 'flapjack/data/message'
|
@@ -66,7 +64,7 @@ module Flapjack
|
|
66
64
|
'severity' => opts[:severity],
|
67
65
|
'tags' => tag_data }
|
68
66
|
|
69
|
-
redis.rpush(queue,
|
67
|
+
redis.rpush(queue, Flapjack.dump_json(notif))
|
70
68
|
end
|
71
69
|
|
72
70
|
def self.next(queue, opts = {})
|
@@ -82,7 +80,7 @@ module Flapjack
|
|
82
80
|
return unless raw
|
83
81
|
end
|
84
82
|
begin
|
85
|
-
parsed = ::
|
83
|
+
parsed = ::Flapjack.load_json( raw )
|
86
84
|
rescue Oj::Error => e
|
87
85
|
if options[:logger]
|
88
86
|
options[:logger].warn("Error deserialising notification json: #{e}, raw json: #{raw.inspect}")
|
@@ -133,7 +131,7 @@ module Flapjack
|
|
133
131
|
media = contact.media
|
134
132
|
|
135
133
|
logger.debug "Notification#messages: creating messages for contact: #{contact_id} " +
|
136
|
-
"event_id: \"#{@event_id}\" state: #{@state} event_tags: #{@tags
|
134
|
+
"event_id: \"#{@event_id}\" state: #{@state} event_tags: #{Flapjack.dump_json(@tags)} media: #{media.inspect}"
|
137
135
|
rlen = rules.length
|
138
136
|
logger.debug "found #{rlen} rule#{(rlen == 1) ? '' : 's'} for contact #{contact_id}"
|
139
137
|
|
@@ -144,7 +142,7 @@ module Flapjack
|
|
144
142
|
# for time, entity and tags
|
145
143
|
matchers = rules.select do |rule|
|
146
144
|
logger.debug("considering rule with entities: #{rule.entities}, entities regex: #{rule.regex_entities},
|
147
|
-
tags: #{rule.tags
|
145
|
+
tags: #{Flapjack.dump_json(rule.tags)} and regex tags: #{Flapjack.dump_json(rule.regex_tags)}")
|
148
146
|
rule_has_tags = rule.tags ? (rule.tags.length > 0) : false
|
149
147
|
rule_has_regex_tags = rule.regex_tags ? (rule.regex_tags.length > 0) : false
|
150
148
|
rule_has_entities = rule.entities ? (rule.entities.length > 0) : false
|
@@ -162,7 +160,7 @@ module Flapjack
|
|
162
160
|
|
163
161
|
logger.debug "#{matchers.length} matchers remain for this contact after time, entity and tags are matched:"
|
164
162
|
matchers.each do |matcher|
|
165
|
-
logger.debug " - #{matcher.
|
163
|
+
logger.debug " - #{matcher.to_jsonapi}"
|
166
164
|
end
|
167
165
|
|
168
166
|
# delete any general matchers if there are more specific matchers left
|
@@ -175,7 +173,7 @@ module Flapjack
|
|
175
173
|
if num_matchers != matchers.length
|
176
174
|
logger.debug("removal of general matchers when entity specific matchers are present: number of matchers changed from #{num_matchers} to #{matchers.length} for contact id: #{contact_id}")
|
177
175
|
matchers.each do |matcher|
|
178
|
-
logger.debug " - #{matcher.
|
176
|
+
logger.debug " - #{matcher.to_jsonapi}"
|
179
177
|
end
|
180
178
|
end
|
181
179
|
end
|
@@ -185,7 +183,7 @@ module Flapjack
|
|
185
183
|
if blackhole_matchers.length > 0
|
186
184
|
logger.debug "dropping this media as #{blackhole_matchers.length} blackhole matchers are present:"
|
187
185
|
blackhole_matchers.each {|bm|
|
188
|
-
logger.debug " - #{bm.
|
186
|
+
logger.debug " - #{bm.to_jsonapi}"
|
189
187
|
}
|
190
188
|
next
|
191
189
|
else
|
@@ -264,7 +262,7 @@ module Flapjack
|
|
264
262
|
@state_duration = opts['state_duration']
|
265
263
|
@type = opts['type']
|
266
264
|
@severity = opts['severity']
|
267
|
-
@tags = opts['tags'].is_a?(Array) ?
|
265
|
+
@tags = opts['tags'].is_a?(Array) ? Set.new(opts['tags']) : nil
|
268
266
|
end
|
269
267
|
|
270
268
|
# # time restrictions match?
|
@@ -1,10 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'oj'
|
4
3
|
require 'active_support/time'
|
5
4
|
require 'ice_cube'
|
6
5
|
require 'flapjack/utility'
|
7
|
-
require 'flapjack/data/tag_set'
|
8
6
|
|
9
7
|
module Flapjack
|
10
8
|
module Data
|
@@ -108,20 +106,19 @@ module Flapjack
|
|
108
106
|
nil
|
109
107
|
end
|
110
108
|
|
111
|
-
def to_json(*args)
|
112
|
-
self.class.hashify(:id, :contact_id, :tags, :regex_tags, :entities, :regex_entities,
|
113
|
-
:time_restrictions, :unknown_media, :warning_media, :critical_media,
|
114
|
-
:unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k|
|
115
|
-
[k, self.send(k)]
|
116
|
-
}.to_json
|
117
|
-
end
|
118
|
-
|
119
109
|
def to_jsonapi(opts = {})
|
120
|
-
self.class.hashify(:id, :tags, :regex_tags, :entities, :regex_entities,
|
110
|
+
json_data = self.class.hashify(:id, :tags, :regex_tags, :entities, :regex_entities,
|
121
111
|
:time_restrictions, :unknown_media, :warning_media, :critical_media,
|
122
112
|
:unknown_blackhole, :warning_blackhole, :critical_blackhole) {|k|
|
123
|
-
|
124
|
-
|
113
|
+
case k
|
114
|
+
when :tags, :regex_tags
|
115
|
+
[k.to_s, self.send(k).to_a.sort]
|
116
|
+
else
|
117
|
+
[k.to_s, self.send(k)]
|
118
|
+
end
|
119
|
+
}.merge('links' => {'contacts' => [self.contact_id]})
|
120
|
+
|
121
|
+
Flapjack.dump_json(json_data)
|
125
122
|
end
|
126
123
|
|
127
124
|
# entity names match?
|
@@ -203,10 +200,10 @@ module Flapjack
|
|
203
200
|
rule_data[:warning_blackhole] = rule_data[:warning_blackhole] || false
|
204
201
|
rule_data[:critical_blackhole] = rule_data[:critical_blackhole] || false
|
205
202
|
if rule_data[:tags].is_a?(Array)
|
206
|
-
rule_data[:tags] =
|
203
|
+
rule_data[:tags] = Set.new(rule_data[:tags])
|
207
204
|
end
|
208
205
|
if rule_data[:regex_tags].is_a?(Array)
|
209
|
-
rule_data[:regex_tags] =
|
206
|
+
rule_data[:regex_tags] = Set.new(rule_data[:regex_tags])
|
210
207
|
end
|
211
208
|
rule_data
|
212
209
|
end
|
@@ -227,14 +224,14 @@ module Flapjack
|
|
227
224
|
json_rule_data = {
|
228
225
|
:id => rule_data[:id].to_s,
|
229
226
|
:contact_id => rule_data[:contact_id].to_s,
|
230
|
-
:entities =>
|
231
|
-
:regex_entities =>
|
232
|
-
:tags =>
|
233
|
-
:regex_tags =>
|
234
|
-
:time_restrictions =>
|
235
|
-
:unknown_media =>
|
236
|
-
:warning_media =>
|
237
|
-
:critical_media =>
|
227
|
+
:entities => Flapjack.dump_json(rule_data[:entities]),
|
228
|
+
:regex_entities => Flapjack.dump_json(rule_data[:regex_entities]),
|
229
|
+
:tags => Flapjack.dump_json(tag_data),
|
230
|
+
:regex_tags => Flapjack.dump_json(regex_tag_data),
|
231
|
+
:time_restrictions => Flapjack.dump_json(rule_data[:time_restrictions]),
|
232
|
+
:unknown_media => Flapjack.dump_json(rule_data[:unknown_media]),
|
233
|
+
:warning_media => Flapjack.dump_json(rule_data[:warning_media]),
|
234
|
+
:critical_media => Flapjack.dump_json(rule_data[:critical_media]),
|
238
235
|
:unknown_blackhole => rule_data[:unknown_blackhole],
|
239
236
|
:warning_blackhole => rule_data[:warning_blackhole],
|
240
237
|
:critical_blackhole => rule_data[:critical_blackhole],
|
@@ -323,13 +320,13 @@ module Flapjack
|
|
323
320
|
|
324
321
|
proc {|d| !d.has_key?(:tags) ||
|
325
322
|
( d[:tags].nil? ||
|
326
|
-
d[:tags].is_a?(
|
323
|
+
d[:tags].is_a?(Set) &&
|
327
324
|
d[:tags].all? {|et| et.is_a?(String)} ) } =>
|
328
325
|
"tags must be a tag_set of strings",
|
329
326
|
|
330
327
|
proc {|d| !d.has_key?(:regex_tags) ||
|
331
328
|
( d[:regex_tags].nil? ||
|
332
|
-
d[:regex_tags].is_a?(
|
329
|
+
d[:regex_tags].is_a?(Set) &&
|
333
330
|
d[:regex_tags].all? {|et| et.is_a?(String)} ) } =>
|
334
331
|
"regex_tags must be a tag_set of strings",
|
335
332
|
|
@@ -400,16 +397,16 @@ module Flapjack
|
|
400
397
|
rule_data = @redis.hgetall("notification_rule:#{@id}")
|
401
398
|
|
402
399
|
@contact_id = rule_data['contact_id']
|
403
|
-
tags =
|
404
|
-
@tags = tags ?
|
405
|
-
regex_tags =
|
406
|
-
@regex_tags = regex_tags ?
|
407
|
-
@entities =
|
408
|
-
@regex_entities =
|
409
|
-
@time_restrictions =
|
410
|
-
@unknown_media =
|
411
|
-
@warning_media =
|
412
|
-
@critical_media =
|
400
|
+
tags = Flapjack.load_json(rule_data['tags'] || '')
|
401
|
+
@tags = tags ? Set.new(tags) : nil
|
402
|
+
regex_tags = Flapjack.load_json(rule_data['regex_tags'] || '')
|
403
|
+
@regex_tags = regex_tags ? Set.new(regex_tags) : nil
|
404
|
+
@entities = Flapjack.load_json(rule_data['entities'] || '')
|
405
|
+
@regex_entities = Flapjack.load_json(rule_data['regex_entities'] || '')
|
406
|
+
@time_restrictions = Flapjack.load_json(rule_data['time_restrictions'] || '')
|
407
|
+
@unknown_media = Flapjack.load_json(rule_data['unknown_media'] || '')
|
408
|
+
@warning_media = Flapjack.load_json(rule_data['warning_media'] || '')
|
409
|
+
@critical_media = Flapjack.load_json(rule_data['critical_media'] || '')
|
413
410
|
@unknown_blackhole = ((rule_data['unknown_blackhole'] || 'false').downcase == 'true')
|
414
411
|
@warning_blackhole = ((rule_data['warning_blackhole'] || 'false').downcase == 'true')
|
415
412
|
@critical_blackhole = ((rule_data['critical_blackhole'] || 'false').downcase == 'true')
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# mixed in to some of the Flapjack data classes
|
4
|
+
|
5
|
+
module Flapjack
|
6
|
+
|
7
|
+
module Tagged
|
8
|
+
|
9
|
+
def tag_prefix
|
10
|
+
self.class.name.split('::').last.downcase + '_tag'
|
11
|
+
end
|
12
|
+
|
13
|
+
def known_key
|
14
|
+
"known_tags:#{tag_prefix}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# return the set of tags for this object
|
18
|
+
def tags
|
19
|
+
return @tags unless @tags.nil?
|
20
|
+
@tags ||= Set.new( @redis.smembers(known_key).inject([]) {|memo, t|
|
21
|
+
tag_key = "#{tag_prefix}:#{t}"
|
22
|
+
memo << t if @redis.sismember(tag_key, @id.to_s)
|
23
|
+
memo
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
# adds tags to this object
|
28
|
+
def add_tags(*enum)
|
29
|
+
enum.each do |t|
|
30
|
+
@redis.sadd(known_key, t)
|
31
|
+
@redis.sadd("#{tag_prefix}:#{t}", @id)
|
32
|
+
tags.add(t)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# removes tags from this object
|
37
|
+
def delete_tags(*enum)
|
38
|
+
enum.each do |t|
|
39
|
+
tag_key = "#{tag_prefix}:#{t}"
|
40
|
+
@redis.srem(tag_key, @id)
|
41
|
+
tags.delete(t)
|
42
|
+
@redis.srem(known_key, t) if (@redis.scard(tag_key) == 0)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -6,7 +6,6 @@ require 'socket'
|
|
6
6
|
|
7
7
|
require 'blather/client/client'
|
8
8
|
require 'chronic_duration'
|
9
|
-
require 'oj'
|
10
9
|
|
11
10
|
require 'flapjack/data/entity_check'
|
12
11
|
require 'flapjack/redis_pool'
|
@@ -69,7 +68,7 @@ module Flapjack
|
|
69
68
|
redis_uri = @redis_config[:path] ||
|
70
69
|
"redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
|
71
70
|
shutdown_redis = EM::Hiredis.connect(redis_uri)
|
72
|
-
shutdown_redis.rpush(@config['queue'],
|
71
|
+
shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown'))
|
73
72
|
end
|
74
73
|
|
75
74
|
def setup
|
@@ -398,7 +397,7 @@ module Flapjack
|
|
398
397
|
when number_found == 0
|
399
398
|
msg = "found no entities matching /#{entity_pattern}/"
|
400
399
|
when number_found >= 1
|
401
|
-
failing_list = Flapjack::Data::EntityCheck.
|
400
|
+
failing_list = Flapjack::Data::EntityCheck.find_current_names_failing_by_entity(:redis => @redis)
|
402
401
|
entities = failing_list.select {|k,v| v.count >= 1 && entity_list.include?(k) }
|
403
402
|
if entities.length >= 1
|
404
403
|
entities.each_pair do |entity,check_list|
|
@@ -474,7 +473,7 @@ module Flapjack
|
|
474
473
|
msg = "found no entities matching /#{entity_pattern}/"
|
475
474
|
when number_found >= 1
|
476
475
|
|
477
|
-
failing_list = Flapjack::Data::EntityCheck.
|
476
|
+
failing_list = Flapjack::Data::EntityCheck.find_current_names_failing_by_entity(:redis => @redis)
|
478
477
|
|
479
478
|
my_failing_checks = Hash[failing_list.map do |k,v|
|
480
479
|
if entity_list.include?(k)
|
@@ -695,7 +694,7 @@ module Flapjack
|
|
695
694
|
events[queue] = @redis.blpop(queue, 0)
|
696
695
|
event_json = events[queue][1]
|
697
696
|
begin
|
698
|
-
event =
|
697
|
+
event = Flapjack.load_json(event_json)
|
699
698
|
|
700
699
|
@logger.debug('jabber notification event received: ' + event.inspect)
|
701
700
|
|
@@ -43,34 +43,72 @@ module Flapjack
|
|
43
43
|
Flapjack::Data::EntityCheck.for_event_id(req_check, :logger => logger, :redis => redis)
|
44
44
|
end
|
45
45
|
else
|
46
|
-
Flapjack::Data::EntityCheck.
|
46
|
+
Flapjack::Data::EntityCheck.all(:logger => logger, :redis => redis)
|
47
47
|
end
|
48
48
|
checks.compact!
|
49
49
|
|
50
50
|
if requested_checks && checks.empty?
|
51
|
-
raise Flapjack::Gateways::JSONAPI::
|
51
|
+
raise Flapjack::Gateways::JSONAPI::EntityChecksNotFound.new(requested_checks)
|
52
52
|
end
|
53
53
|
|
54
|
+
check_ids = checks.collect {|c| "#{c.entity.name}:#{c.check}" }
|
55
|
+
|
56
|
+
enabled_ids = Flapjack::Data::EntityCheck.enabled_for(check_ids, :redis => redis)
|
57
|
+
|
54
58
|
linked_entity_ids = checks.empty? ? [] : checks.inject({}) do |memo, check|
|
55
|
-
|
59
|
+
entity = check.entity
|
60
|
+
memo["#{entity.name}:#{check.check}"] = [entity.id]
|
56
61
|
memo
|
57
62
|
end
|
58
63
|
|
59
64
|
checks_json = checks.collect {|check|
|
60
|
-
|
65
|
+
check_name = "#{check.entity.name}:#{check.check}"
|
66
|
+
check.to_jsonapi(:enabled => enabled_ids.include?(check_name),
|
67
|
+
:entity_ids => linked_entity_ids[check_name])
|
61
68
|
}.join(",")
|
62
69
|
|
63
70
|
'{"checks":[' + checks_json + ']}'
|
64
71
|
end
|
65
72
|
|
73
|
+
app.post '/checks' do
|
74
|
+
checks = wrapped_params('checks')
|
75
|
+
|
76
|
+
check_names = checks.collect{|check_data|
|
77
|
+
check = Flapjack::Data::EntityCheck.add(check_data, :redis => redis)
|
78
|
+
"#{check.entity.name}:#{check.check}"
|
79
|
+
}
|
80
|
+
|
81
|
+
response.headers['Location'] = "#{request.base_url}/checks/#{check_names.join(',')}"
|
82
|
+
status 201
|
83
|
+
Flapjack.dump_json(check_names)
|
84
|
+
end
|
85
|
+
|
66
86
|
app.patch %r{^/checks/(.+)$} do
|
67
87
|
checks_for_check_names(params[:captures][0].split(',')).each do |check|
|
68
88
|
apply_json_patch('checks') do |op, property, linked, value|
|
69
89
|
case op
|
70
90
|
when 'replace'
|
71
|
-
|
72
|
-
|
73
|
-
|
91
|
+
case property
|
92
|
+
when 'enabled'
|
93
|
+
# explicitly checking for true/false being passed in
|
94
|
+
case value
|
95
|
+
when TrueClass
|
96
|
+
check.enable!
|
97
|
+
when FalseClass
|
98
|
+
check.disable!
|
99
|
+
end
|
100
|
+
end
|
101
|
+
when 'add'
|
102
|
+
case linked
|
103
|
+
when 'tags'
|
104
|
+
value.respond_to?(:each) ? check.add_tags(*value) :
|
105
|
+
check.add_tags(value)
|
106
|
+
end
|
107
|
+
when 'remove'
|
108
|
+
case linked
|
109
|
+
when 'tags'
|
110
|
+
value.respond_to?(:each) ? check.delete_tags(*value) :
|
111
|
+
check.delete_tags(value)
|
74
112
|
end
|
75
113
|
end
|
76
114
|
end
|
@@ -36,7 +36,7 @@ module Flapjack
|
|
36
36
|
def outage(start_time, end_time, options = {})
|
37
37
|
# hist_states is an array of hashes, with [state, timestamp, summary] keys
|
38
38
|
hist_states = @entity_check.historical_states(start_time, end_time)
|
39
|
-
return
|
39
|
+
return {:outages => []} if hist_states.empty?
|
40
40
|
|
41
41
|
initial = @entity_check.historical_state_before(hist_states.first[:timestamp])
|
42
42
|
hist_states.unshift(initial) if initial
|
@@ -45,7 +45,7 @@ module Flapjack
|
|
45
45
|
missing_ids = contacts_by_id.select {|k, v| v.nil? }.keys
|
46
46
|
unless missing_ids.empty?
|
47
47
|
semaphore.release
|
48
|
-
|
48
|
+
raise Flapjack::Gateways::JSONAPI::ContactsNotFound.new(missing_ids)
|
49
49
|
end
|
50
50
|
|
51
51
|
block.call(contacts_by_id.select {|k, v| !v.nil? }.values)
|
@@ -93,7 +93,7 @@ module Flapjack
|
|
93
93
|
|
94
94
|
response.headers['Location'] = "#{base_url}/contacts/#{contact_ids.join(',')}"
|
95
95
|
status 201
|
96
|
-
contact_ids
|
96
|
+
Flapjack.dump_json(contact_ids)
|
97
97
|
end
|
98
98
|
|
99
99
|
# Returns all (/contacts) or some (/contacts/1,2,3) or one (/contacts/2) contact(s)
|
@@ -144,6 +144,9 @@ module Flapjack
|
|
144
144
|
unless notification_rule.nil?
|
145
145
|
contact.grab_notification_rule(notification_rule)
|
146
146
|
end
|
147
|
+
when 'tags'
|
148
|
+
value.respond_to?(:each) ? contact.add_tags(*value) :
|
149
|
+
contact.add_tags(value)
|
147
150
|
# when 'media' # not supported yet due to id brokenness
|
148
151
|
end
|
149
152
|
when 'remove'
|
@@ -156,6 +159,9 @@ module Flapjack
|
|
156
159
|
unless notification_rule.nil?
|
157
160
|
contact.delete_notification_rule(notification_rule)
|
158
161
|
end
|
162
|
+
when 'tags'
|
163
|
+
value.respond_to?(:each) ? contact.delete_tags(*value) :
|
164
|
+
contact.delete_tags(value)
|
159
165
|
# when 'media' # not supported yet due to id brokenness
|
160
166
|
end
|
161
167
|
end
|