flapjack 0.8.10 → 0.8.11
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/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
|
|