flapjack 0.8.10 → 0.8.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -1
- data/bin/flapjack +10 -1
- data/bin/flapjack-nagios-receiver +1 -2
- data/bin/simulate-failed-check +12 -4
- data/etc/flapjack_config.yaml.example +2 -1
- data/flapjack.gemspec +1 -0
- data/lib/flapjack/data/contact.rb +46 -26
- data/lib/flapjack/data/entity.rb +28 -0
- data/lib/flapjack/data/entity_check.rb +52 -11
- data/lib/flapjack/data/event.rb +9 -3
- data/lib/flapjack/data/notification_rule.rb +8 -0
- data/lib/flapjack/gateways/api.rb +0 -1
- data/lib/flapjack/gateways/api/entity_check_presenter.rb +2 -1
- data/lib/flapjack/gateways/email.rb +1 -2
- data/lib/flapjack/gateways/jabber.rb +3 -3
- data/lib/flapjack/gateways/jsonapi.rb +186 -38
- data/lib/flapjack/gateways/jsonapi/check_methods.rb +120 -0
- data/lib/flapjack/gateways/jsonapi/{entity_check_presenter.rb → check_presenter.rb} +7 -6
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +61 -352
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +117 -248
- data/lib/flapjack/gateways/jsonapi/medium_methods.rb +179 -0
- data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +124 -0
- data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +128 -0
- data/lib/flapjack/gateways/jsonapi/rack/json_params_parser.rb +4 -5
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +143 -0
- data/lib/flapjack/gateways/web.rb +1 -0
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +165 -101
- data/lib/flapjack/gateways/web/public/js/contacts.js +34 -46
- data/lib/flapjack/gateways/web/public/js/select2.js +232 -90
- data/lib/flapjack/gateways/web/public/js/select2.min.js +4 -4
- data/lib/flapjack/gateways/web/views/check.html.erb +11 -2
- data/lib/flapjack/processor.rb +6 -6
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/entity_check_spec.rb +1 -1
- data/spec/lib/flapjack/data/event_spec.rb +10 -9
- data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +25 -25
- data/spec/lib/flapjack/gateways/api_spec.rb +23 -1
- data/spec/lib/flapjack/gateways/email_spec.rb +40 -2
- data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +134 -0
- data/spec/lib/flapjack/gateways/jsonapi/{entity_check_presenter_spec.rb → check_presenter_spec.rb} +17 -17
- data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +27 -232
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +217 -687
- data/spec/lib/flapjack/gateways/jsonapi/medium_methods_spec.rb +232 -0
- data/spec/lib/flapjack/gateways/jsonapi/notification_rule_methods_spec.rb +131 -0
- data/spec/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods_spec.rb +113 -0
- data/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +546 -0
- data/spec/lib/flapjack/gateways/jsonapi_spec.rb +10 -1
- data/spec/lib/flapjack/gateways/web_spec.rb +1 -0
- data/spec/support/jsonapi_helper.rb +62 -0
- metadata +36 -8
- data/lib/flapjack/gateways/jsonapi/entity_presenter.rb +0 -75
- data/spec/lib/flapjack/gateways/jsonapi/entity_presenter_spec.rb +0 -108
@@ -12,7 +12,7 @@ module Flapjack
|
|
12
12
|
|
13
13
|
class JSONAPI < Sinatra::Base
|
14
14
|
|
15
|
-
class
|
15
|
+
class CheckPresenter
|
16
16
|
|
17
17
|
def initialize(entity_check)
|
18
18
|
@entity_check = entity_check
|
@@ -24,6 +24,7 @@ module Flapjack
|
|
24
24
|
'enabled' => @entity_check.enabled?,
|
25
25
|
'summary' => @entity_check.summary,
|
26
26
|
'details' => @entity_check.details,
|
27
|
+
'perfdata' => @entity_check.perfdata,
|
27
28
|
'in_unscheduled_maintenance' => @entity_check.in_unscheduled_maintenance?,
|
28
29
|
'in_scheduled_maintenance' => @entity_check.in_scheduled_maintenance?,
|
29
30
|
'last_update' => @entity_check.last_update,
|
@@ -32,7 +33,7 @@ module Flapjack
|
|
32
33
|
'last_acknowledgement_notification' => @entity_check.last_notification_for_state(:acknowledgement)[:timestamp]}
|
33
34
|
end
|
34
35
|
|
35
|
-
def
|
36
|
+
def outage(start_time, end_time, options = {})
|
36
37
|
# hist_states is an array of hashes, with [state, timestamp, summary] keys
|
37
38
|
hist_states = @entity_check.historical_states(start_time, end_time)
|
38
39
|
return hist_states if hist_states.empty?
|
@@ -83,7 +84,7 @@ module Flapjack
|
|
83
84
|
result
|
84
85
|
end
|
85
86
|
|
86
|
-
def
|
87
|
+
def unscheduled_maintenance(start_time, end_time)
|
87
88
|
# unsched_maintenance is an array of hashes, with [duration, timestamp, summary] keys
|
88
89
|
unsched_maintenance = @entity_check.maintenances(start_time, end_time,
|
89
90
|
:scheduled => false)
|
@@ -98,7 +99,7 @@ module Flapjack
|
|
98
99
|
start_in_unsched + unsched_maintenance
|
99
100
|
end
|
100
101
|
|
101
|
-
def
|
102
|
+
def scheduled_maintenance(start_time, end_time)
|
102
103
|
# sched_maintenance is an array of hashes, with [duration, timestamp, summary] keys
|
103
104
|
sched_maintenance = @entity_check.maintenances(start_time, end_time,
|
104
105
|
:scheduled => true)
|
@@ -119,9 +120,9 @@ module Flapjack
|
|
119
120
|
#
|
120
121
|
# TODO test performance with larger data sets
|
121
122
|
def downtime(start_time, end_time)
|
122
|
-
sched_maintenances =
|
123
|
+
sched_maintenances = scheduled_maintenance(start_time, end_time)
|
123
124
|
|
124
|
-
outs =
|
125
|
+
outs = outage(start_time, end_time)
|
125
126
|
|
126
127
|
total_secs = {}
|
127
128
|
percentages = {}
|
@@ -18,28 +18,11 @@ module Flapjack
|
|
18
18
|
|
19
19
|
module Helpers
|
20
20
|
|
21
|
-
def find_contact(contact_id)
|
22
|
-
contact = Flapjack::Data::Contact.find_by_id(contact_id, :logger => logger, :redis => redis)
|
23
|
-
raise Flapjack::Gateways::JSONAPI::ContactNotFound.new(contact_id) if contact.nil?
|
24
|
-
contact
|
25
|
-
end
|
26
|
-
|
27
|
-
def find_rule(rule_id)
|
28
|
-
rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :logger => logger, :redis => redis)
|
29
|
-
raise Flapjack::Gateways::JSONAPI::NotificationRuleNotFound.new(rule_id) if rule.nil?
|
30
|
-
rule
|
31
|
-
end
|
32
|
-
|
33
|
-
def find_tags(tags)
|
34
|
-
halt err(400, "no tags given") if tags.nil? || tags.empty?
|
35
|
-
tags
|
36
|
-
end
|
37
|
-
|
38
21
|
def obtain_semaphore(resource)
|
39
22
|
semaphore = nil
|
40
23
|
strikes = 0
|
41
24
|
begin
|
42
|
-
semaphore = Flapjack::Data::Semaphore.new(resource,
|
25
|
+
semaphore = Flapjack::Data::Semaphore.new(resource, :redis => redis, :expiry => 30)
|
43
26
|
rescue Flapjack::Data::Semaphore::ResourceLocked
|
44
27
|
strikes += 1
|
45
28
|
raise Flapjack::Gateways::JSONAPI::ResourceLocked.new(resource) unless strikes < 3
|
@@ -50,50 +33,32 @@ module Flapjack
|
|
50
33
|
semaphore
|
51
34
|
end
|
52
35
|
|
53
|
-
def
|
54
|
-
|
36
|
+
def bulk_contact_operation(contact_ids, &block)
|
37
|
+
semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
|
55
38
|
|
56
|
-
|
57
|
-
|
39
|
+
contacts_by_id = contact_ids.inject({}) do |memo, contact_id|
|
40
|
+
# can't use find_contact here as that would halt immediately
|
41
|
+
memo[contact_id] = Flapjack::Data::Contact.find_by_id(contact_id, :redis => redis, :logger => logger)
|
42
|
+
memo
|
58
43
|
end
|
59
44
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
op = operation['op']
|
65
|
-
operation['path'] =~ /\A\/#{object_path}\/0\/([^\/]+)(?:\/([^\/]+)(?:\/([^\/]+))?)?\z/
|
66
|
-
if 'links'.eql?($1)
|
67
|
-
linked = $2
|
68
|
-
|
69
|
-
value = case op
|
70
|
-
when 'add'
|
71
|
-
operation['value']
|
72
|
-
when 'remove'
|
73
|
-
$3
|
74
|
-
end
|
75
|
-
elsif 'replace'.eql?(op)
|
76
|
-
property = $1
|
77
|
-
value = $3
|
78
|
-
else
|
79
|
-
next
|
80
|
-
end
|
81
|
-
|
82
|
-
yield(op, property, linked, value)
|
45
|
+
missing_ids = contacts_by_id.select {|k, v| v.nil? }.keys
|
46
|
+
unless missing_ids.empty?
|
47
|
+
semaphore.release
|
48
|
+
halt(404, "Contacts with ids #{missing_ids.join(', ')} were not found")
|
83
49
|
end
|
50
|
+
|
51
|
+
block.call(contacts_by_id.select {|k, v| !v.nil? }.values)
|
52
|
+
semaphore.release
|
84
53
|
end
|
85
54
|
|
86
55
|
end
|
87
56
|
|
88
57
|
def self.registered(app)
|
89
|
-
|
58
|
+
app.helpers Flapjack::Gateways::JSONAPI::Helpers
|
90
59
|
app.helpers Flapjack::Gateways::JSONAPI::ContactMethods::Helpers
|
91
60
|
|
92
61
|
app.post '/contacts' do
|
93
|
-
pass unless is_json_request?
|
94
|
-
content_type :json
|
95
|
-
cors_headers
|
96
|
-
|
97
62
|
contacts_data = params[:contacts]
|
98
63
|
|
99
64
|
if contacts_data.nil? || !contacts_data.is_a?(Enumerable)
|
@@ -126,23 +91,20 @@ module Flapjack
|
|
126
91
|
|
127
92
|
ids = contacts_data.map {|c| c['id']}
|
128
93
|
location(ids)
|
94
|
+
status 201
|
129
95
|
|
130
96
|
contacts_data.map {|cd| cd['id']}.to_json
|
131
97
|
end
|
132
98
|
|
133
|
-
# Returns all (/contacts) or some (/contacts/1,2,3) or one (/
|
99
|
+
# Returns all (/contacts) or some (/contacts/1,2,3) or one (/contacts/2) contact(s)
|
134
100
|
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts
|
135
|
-
app.get %r{
|
136
|
-
content_type 'application/vnd.api+json'
|
137
|
-
cors_headers
|
138
|
-
|
101
|
+
app.get %r{^/contacts(?:/)?([^/]+)?$} do
|
139
102
|
requested_contacts = if params[:captures] && params[:captures][0]
|
140
103
|
params[:captures][0].split(',').uniq
|
141
104
|
else
|
142
105
|
nil
|
143
106
|
end
|
144
107
|
|
145
|
-
#FIXME: do we need to url decode the ids? has rack or some middleware already done this?
|
146
108
|
contacts = if requested_contacts
|
147
109
|
Flapjack::Data::Contact.find_by_ids(requested_contacts, :logger => logger, :redis => redis)
|
148
110
|
else
|
@@ -154,315 +116,62 @@ module Flapjack
|
|
154
116
|
raise Flapjack::Gateways::JSONAPI::ContactsNotFound.new(requested_contacts)
|
155
117
|
end
|
156
118
|
|
157
|
-
|
158
|
-
[[], []]
|
159
|
-
else
|
160
|
-
Flapjack::Data::Contact.entities_jsonapi(contacts.map(&:id), :redis => redis)
|
161
|
-
end
|
162
|
-
|
163
|
-
linked_media_data = []
|
164
|
-
linked_media_ids = {}
|
165
|
-
contacts.each do |contact|
|
166
|
-
contact.media.keys.each do |medium|
|
167
|
-
id = "#{contact.id}_#{medium}"
|
168
|
-
interval = contact.media_intervals[medium].nil? ? nil : contact.media_intervals[medium].to_i
|
169
|
-
rollup_threshold = contact.media_rollup_thresholds[medium].nil? ? nil : contact.media_rollup_thresholds[medium].to_i
|
170
|
-
linked_media_ids[contact.id] = id
|
171
|
-
linked_media_data <<
|
172
|
-
{ "id" => id,
|
173
|
-
"type" => medium,
|
174
|
-
"address" => contact.media[medium],
|
175
|
-
"interval" => interval,
|
176
|
-
"rollup_threshold" => rollup_threshold,
|
177
|
-
"contact_id" => contact.id }
|
178
|
-
end
|
179
|
-
end
|
119
|
+
entity_ids = Flapjack::Data::Contact.entity_ids_for(contacts.map(&:id), :redis => redis)
|
180
120
|
|
181
121
|
contacts_json = contacts.collect {|contact|
|
182
|
-
contact.
|
183
|
-
contact.linked_media_ids = linked_media_ids[contact.id]
|
184
|
-
contact.to_jsonapi
|
122
|
+
contact.to_jsonapi(:entity_ids => entity_ids[contact.id])
|
185
123
|
}.join(", ")
|
186
124
|
|
187
|
-
'{"contacts":[' + contacts_json + ']'
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
halt err(422, "ID, if supplied, must match URL")
|
225
|
-
end
|
226
|
-
|
227
|
-
contact = find_contact(params[:contact_id])
|
228
|
-
#contact_data = hashify('first_name', 'last_name', 'email', 'media', 'tags') {|k| [k, params[k]]}
|
229
|
-
logger.debug("contact_data: #{contact_data}")
|
230
|
-
contact.update(contact_data)
|
231
|
-
|
232
|
-
contact.to_jsonapi
|
233
|
-
end
|
234
|
-
|
235
|
-
# TODO this should build up all data, verify entities exist, etc.
|
236
|
-
# before applying any changes
|
237
|
-
# TODO generalise JSON-Patch data parsing code
|
238
|
-
app.patch '/contacts/:contact_id' do
|
239
|
-
pass unless is_jsonpatch_request?
|
240
|
-
content_type :json
|
241
|
-
cors_headers
|
242
|
-
|
243
|
-
contact = find_contact(params[:contact_id])
|
244
|
-
|
245
|
-
apply_json_patch('contacts') do |op, property, linked, value|
|
246
|
-
case op
|
247
|
-
when 'replace'
|
248
|
-
if ['first_name', 'last_name', 'email'].include?(property)
|
249
|
-
contact.update(property => value)
|
250
|
-
end
|
251
|
-
when 'add'
|
252
|
-
logger.debug "patch add operation. linked: #{linked}"
|
253
|
-
if 'entities'.eql?(linked)
|
254
|
-
entity = Flapjack::Data::Entity.find_by_id(value, :redis => redis)
|
255
|
-
logger.debug "adding this entity: #{entity}"
|
256
|
-
contact.add_entity(entity) unless entity.nil?
|
257
|
-
end
|
258
|
-
when 'remove'
|
259
|
-
if 'entities'.eql?(linked)
|
260
|
-
entity = Flapjack::Data::Entity.find_by_id(value, :redis => redis)
|
261
|
-
contact.remove_entity(entity) unless entity.nil?
|
125
|
+
'{"contacts":[' + contacts_json + ']}'
|
126
|
+
end
|
127
|
+
|
128
|
+
app.patch '/contacts/:id' do
|
129
|
+
bulk_contact_operation(params[:id].split(',')) do |contacts|
|
130
|
+
contacts.each do |contact|
|
131
|
+
apply_json_patch('contacts') do |op, property, linked, value|
|
132
|
+
case op
|
133
|
+
when 'replace'
|
134
|
+
if ['first_name', 'last_name', 'email'].include?(property)
|
135
|
+
contact.update(property => value)
|
136
|
+
end
|
137
|
+
when 'add'
|
138
|
+
case linked
|
139
|
+
when 'entities'
|
140
|
+
entity = Flapjack::Data::Entity.find_by_id(value, :redis => redis)
|
141
|
+
contact.add_entity(entity) unless entity.nil?
|
142
|
+
when 'notification_rules'
|
143
|
+
notification_rule = Flapjack::Data::NotificationRule.find_by_id(value, :redis => redis)
|
144
|
+
unless notification_rule.nil?
|
145
|
+
contact.grab_notification_rule(notification_rule)
|
146
|
+
end
|
147
|
+
# when 'media' # not supported yet due to id brokenness
|
148
|
+
end
|
149
|
+
when 'remove'
|
150
|
+
case linked
|
151
|
+
when 'entities'
|
152
|
+
entity = Flapjack::Data::Entity.find_by_id(value, :redis => redis)
|
153
|
+
contact.remove_entity(entity) unless entity.nil?
|
154
|
+
when 'notification_rules'
|
155
|
+
notification_rule = Flapjack::Data::NotificationRule.find_by_id(value, :redis => redis)
|
156
|
+
unless notification_rule.nil?
|
157
|
+
contact.delete_notification_rule(notification_rule)
|
158
|
+
end
|
159
|
+
# when 'media' # not supported yet due to id brokenness
|
160
|
+
end
|
161
|
+
end
|
262
162
|
end
|
263
163
|
end
|
264
164
|
end
|
265
165
|
|
266
|
-
# will need to be 200 and return contact.to_jsonapi
|
267
|
-
# if updated_at changes, or Etag, when those are introduced
|
268
|
-
status 204
|
269
|
-
end
|
270
|
-
|
271
|
-
# Deletes a contact
|
272
|
-
app.delete '/contacts/:contact_id' do
|
273
|
-
cors_headers
|
274
|
-
semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
|
275
|
-
contact = find_contact(params[:contact_id])
|
276
|
-
contact.delete!
|
277
|
-
semaphore.release
|
278
166
|
status 204
|
279
167
|
end
|
280
168
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
media_data = params[:media]
|
287
|
-
|
288
|
-
if media_data.nil? || !media_data.is_a?(Enumerable)
|
289
|
-
halt err(422, "No valid media were submitted")
|
290
|
-
end
|
291
|
-
|
292
|
-
unless media_data.all? {|m| m['id'].nil? }
|
293
|
-
halt err(422, "Media creation cannot include IDs")
|
169
|
+
# Delete one or more contacts
|
170
|
+
app.delete '/contacts/:id' do
|
171
|
+
bulk_contact_operation(params[:id].split(',')) do |contacts|
|
172
|
+
contacts.each {|contact| contact.delete!}
|
294
173
|
end
|
295
174
|
|
296
|
-
semaphore = obtain_semaphore(SEMAPHORE_CONTACT_MASS_UPDATE)
|
297
|
-
|
298
|
-
contacts = media_data.inject({}) {|memo, medium_data|
|
299
|
-
contact_id = medium_data['contact_id']
|
300
|
-
if contact_id.nil?
|
301
|
-
semaphore.release
|
302
|
-
halt err(422, "Media data must include 'contact_id'")
|
303
|
-
end
|
304
|
-
next memo if memo.has_key?(contact_id)
|
305
|
-
contact = Flapjack::Data::Contact.find_by_id(contact_id, :redis => redis)
|
306
|
-
if contact.nil?
|
307
|
-
semaphore.release
|
308
|
-
halt err(422, "Contact id:'#{contact_id}' could not be loaded")
|
309
|
-
end
|
310
|
-
memo[contact_id] = contact
|
311
|
-
memo
|
312
|
-
}
|
313
|
-
|
314
|
-
media_data.each do |medium_data|
|
315
|
-
contact = contacts[medium_data['contact_id']]
|
316
|
-
type = medium_data['type']
|
317
|
-
contact.set_address_for_media(type, medium_data['address'])
|
318
|
-
contact.set_interval_for_media(type, medium_data['interval'])
|
319
|
-
contact.set_rollup_threshold_for_media(type, medium_data['rollup_threshold'])
|
320
|
-
medium_data['id'] = "#{contact.id}_#{type}"
|
321
|
-
end
|
322
|
-
|
323
|
-
semaphore.release
|
324
|
-
|
325
|
-
'{"media":' + media_data.to_json + '}'
|
326
|
-
end
|
327
|
-
|
328
|
-
app.patch '/media/:media_id' do
|
329
|
-
pass unless is_jsonpatch_request?
|
330
|
-
content_type :json
|
331
|
-
cors_headers
|
332
|
-
|
333
|
-
media_id = params[:media_id]
|
334
|
-
media_id =~ /\A(.+)_(email|sms|jabber)\z/
|
335
|
-
|
336
|
-
contact_id = $1
|
337
|
-
type = $2
|
338
|
-
|
339
|
-
halt err(422, "Could not get contact_id from media_id") if contact_id.nil?
|
340
|
-
halt err(422, "Could not get type from media_id") if type.nil?
|
341
|
-
|
342
|
-
contact = find_contact(contact_id)
|
343
|
-
|
344
|
-
apply_json_patch('media') do |op, property, linked, value|
|
345
|
-
if 'replace'.eql?(op)
|
346
|
-
case property
|
347
|
-
when 'address'
|
348
|
-
contact.set_address_for_media(type, value)
|
349
|
-
when 'interval'
|
350
|
-
contact.set_interval_for_media(type, value)
|
351
|
-
when 'rollup_threshold'
|
352
|
-
contact.set_rollup_threshold_for_media(type, value)
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
status 204
|
358
|
-
end
|
359
|
-
|
360
|
-
app.get '/notification_rules/:id' do
|
361
|
-
content_type :json
|
362
|
-
cors_headers
|
363
|
-
|
364
|
-
'{"notification_rules":[' +
|
365
|
-
find_rule(params[:id]).to_json +
|
366
|
-
']}'
|
367
|
-
end
|
368
|
-
|
369
|
-
# Creates a notification rule or rules for a contact
|
370
|
-
app.post '/notification_rules' do
|
371
|
-
content_type :json
|
372
|
-
cors_headers
|
373
|
-
|
374
|
-
rules_data = params[:notification_rules]
|
375
|
-
|
376
|
-
if rules_data.nil? || !rules_data.is_a?(Enumerable)
|
377
|
-
halt err(422, "No valid notification rules were submitted")
|
378
|
-
end
|
379
|
-
|
380
|
-
errors = []
|
381
|
-
rules_data.each do |rule_data|
|
382
|
-
errors << Flapjack::Data::NotificationRule.prevalidate_data(symbolize(rule_data), {:logger => logger})
|
383
|
-
end
|
384
|
-
errors.compact!
|
385
|
-
|
386
|
-
unless errors.nil? || errors.empty?
|
387
|
-
halt err(422, *errors)
|
388
|
-
end
|
389
|
-
|
390
|
-
rules = []
|
391
|
-
errors = []
|
392
|
-
rules_data.each do |rule_data|
|
393
|
-
rule_data = symbolize(rule_data)
|
394
|
-
contact = find_contact(rule_data.delete(:contact_id))
|
395
|
-
rule_or_errors = contact.add_notification_rule(rule_data, :logger => logger)
|
396
|
-
if rule_or_errors.respond_to?(:critical_media)
|
397
|
-
rules << rule_or_errors
|
398
|
-
else
|
399
|
-
errors << rule_or_errors
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
if rules.empty?
|
404
|
-
halt err(422, *errors)
|
405
|
-
else
|
406
|
-
if errors.empty?
|
407
|
-
status 201
|
408
|
-
else
|
409
|
-
logger.warn("Errors during bulk notification rules creation: " + errors.join(', '))
|
410
|
-
status 200
|
411
|
-
end
|
412
|
-
end
|
413
|
-
ids = rules.map {|r| r.id}
|
414
|
-
location(ids)
|
415
|
-
'{"notification_rules":[' +
|
416
|
-
rules.map {|r| r.to_json}.join(',') +
|
417
|
-
']}'
|
418
|
-
end
|
419
|
-
|
420
|
-
# Updates a notification rule
|
421
|
-
app.put('/notification_rules/:id') do
|
422
|
-
content_type :json
|
423
|
-
cors_headers
|
424
|
-
|
425
|
-
rules_data = params[:notification_rules]
|
426
|
-
|
427
|
-
if rules_data.nil? || !rules_data.is_a?(Enumerable)
|
428
|
-
halt err(422, "No valid notification rules were submitted")
|
429
|
-
end
|
430
|
-
|
431
|
-
unless rules_data.length == 1
|
432
|
-
halt err(422, "Exactly one notification rules hash must be supplied.")
|
433
|
-
end
|
434
|
-
|
435
|
-
rule_data = rules_data.first
|
436
|
-
|
437
|
-
if rule_data['id'] && rule_data['id'].to_s != params[:id]
|
438
|
-
halt err(422, "ID, if supplied, must match URL")
|
439
|
-
end
|
440
|
-
|
441
|
-
rule = find_rule(params[:id])
|
442
|
-
contact = find_contact(rule.contact_id)
|
443
|
-
|
444
|
-
supplied_contact = rule_data.delete('contact_id')
|
445
|
-
if supplied_contact && supplied_contact != contact.id
|
446
|
-
halt err(422, "contact_id cannot be modified")
|
447
|
-
end
|
448
|
-
|
449
|
-
errors = rule.update(symbolize(rule_data), :logger => logger)
|
450
|
-
|
451
|
-
unless errors.nil? || errors.empty?
|
452
|
-
halt err(422, *errors)
|
453
|
-
end
|
454
|
-
'{"notification_rules":[' +
|
455
|
-
rule.to_json +
|
456
|
-
']}'
|
457
|
-
end
|
458
|
-
|
459
|
-
# Deletes a notification rule
|
460
|
-
app.delete('/notification_rules/:id') do
|
461
|
-
cors_headers
|
462
|
-
rule = find_rule(params[:id])
|
463
|
-
logger.debug("rule to delete: #{rule.inspect}, contact_id: #{rule.contact_id}")
|
464
|
-
contact = find_contact(rule.contact_id)
|
465
|
-
contact.delete_notification_rule(rule)
|
466
175
|
status 204
|
467
176
|
end
|
468
177
|
|