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.
- 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
|