flapjack 0.6.61 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/README.md +8 -4
- data/features/events.feature +269 -146
- data/features/notification_rules.feature +93 -0
- data/features/steps/events_steps.rb +162 -21
- data/features/steps/notifications_steps.rb +1 -1
- data/features/steps/time_travel_steps.rb +30 -19
- data/features/support/env.rb +71 -1
- data/flapjack.gemspec +3 -0
- data/lib/flapjack/data/contact.rb +256 -57
- data/lib/flapjack/data/entity.rb +2 -1
- data/lib/flapjack/data/entity_check.rb +22 -7
- data/lib/flapjack/data/global.rb +1 -0
- data/lib/flapjack/data/message.rb +2 -0
- data/lib/flapjack/data/notification_rule.rb +172 -0
- data/lib/flapjack/data/tag.rb +7 -2
- data/lib/flapjack/data/tag_set.rb +16 -0
- data/lib/flapjack/executive.rb +147 -13
- data/lib/flapjack/filters/delays.rb +21 -9
- data/lib/flapjack/gateways/api.rb +407 -27
- data/lib/flapjack/gateways/pagerduty.rb +1 -1
- data/lib/flapjack/gateways/web.rb +50 -22
- data/lib/flapjack/gateways/web/views/self_stats.haml +2 -0
- data/lib/flapjack/utility.rb +10 -0
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/contact_spec.rb +103 -6
- data/spec/lib/flapjack/data/global_spec.rb +2 -0
- data/spec/lib/flapjack/data/message_spec.rb +6 -0
- data/spec/lib/flapjack/data/notification_rule_spec.rb +22 -0
- data/spec/lib/flapjack/data/notification_spec.rb +6 -0
- data/spec/lib/flapjack/gateways/api_spec.rb +727 -4
- data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -0
- data/spec/lib/flapjack/gateways/web_spec.rb +11 -1
- data/spec/spec_helper.rb +10 -0
- data/tmp/notification_rules.rb +73 -0
- data/tmp/test_json_post.rb +16 -0
- data/tmp/test_notification_rules_api.rb +170 -0
- metadata +59 -2
@@ -6,6 +6,12 @@ require 'flapjack/filters/base'
|
|
6
6
|
module Flapjack
|
7
7
|
module Filters
|
8
8
|
|
9
|
+
# * If the service event’s state is a failure, and the time since the last state change
|
10
|
+
# is below a threshold (e.g. 30 seconds), then don't alert
|
11
|
+
# * If the service event’s state is a failure, and the time since the last alert is below a
|
12
|
+
# threshold (5 minutes), and the last notification state is the same as the current state, then don’t alert
|
13
|
+
#
|
14
|
+
# OLD:
|
9
15
|
# * If the service event’s state is a failure, and the time since the ok => failure state change
|
10
16
|
# is below a threshold (e.g. 30 seconds), then don't alert
|
11
17
|
# * If the service event’s state is a failure, and the time since the last alert is below a
|
@@ -26,28 +32,34 @@ module Flapjack
|
|
26
32
|
|
27
33
|
if entity_check.failed?
|
28
34
|
last_problem_alert = entity_check.last_problem_notification
|
35
|
+
last_warning_alert = entity_check.last_warning_notification
|
36
|
+
last_critical_alert = entity_check.last_critical_notification
|
29
37
|
last_change = entity_check.last_change
|
30
38
|
last_notification = entity_check.last_notification
|
31
|
-
|
39
|
+
last_alert_state = last_notification[:type]
|
32
40
|
last_alert_timestamp = last_notification[:timestamp]
|
33
41
|
|
34
|
-
|
42
|
+
current_state_duration = current_time - last_change
|
35
43
|
time_since_last_alert = current_time - last_problem_alert unless last_problem_alert.nil?
|
36
44
|
@log.debug("Filter: Delays: last_problem_alert: #{last_problem_alert.to_s}, " +
|
37
|
-
"last_change: #{last_change.
|
38
|
-
"
|
39
|
-
"time_since_last_alert: #{time_since_last_alert.
|
40
|
-
|
45
|
+
"last_change: #{last_change.inspect}, " +
|
46
|
+
"current_state_duration: #{current_state_duration.inspect}, " +
|
47
|
+
"time_since_last_alert: #{time_since_last_alert.inspect}, " +
|
48
|
+
"last_alert_state: [#{last_alert_state.inspect}], " +
|
49
|
+
"event.state: [#{event.state.inspect}], " +
|
50
|
+
"last_alert_state == event.state ? #{last_alert_state.to_s == event.state}")
|
51
|
+
if (current_state_duration < failure_delay)
|
41
52
|
result = true
|
42
53
|
@log.debug("Filter: Delays: blocking because duration of current failure " +
|
43
|
-
"(#{
|
54
|
+
"(#{current_state_duration}) is less than failure_delay (#{failure_delay})")
|
44
55
|
elsif !last_problem_alert.nil? && (time_since_last_alert < resend_delay) &&
|
45
|
-
(
|
56
|
+
(last_alert_state.to_s == event.state)
|
46
57
|
|
47
58
|
result = true
|
48
59
|
@log.debug("Filter: Delays: blocking because time since last alert for " +
|
49
60
|
"current problem (#{time_since_last_alert}) is less than " +
|
50
|
-
"resend_delay (#{resend_delay}) and last alert
|
61
|
+
"resend_delay (#{resend_delay}) and last alert state (#{last_alert_state}) " +
|
62
|
+
"is equal to current event state (#{event.state})")
|
51
63
|
else
|
52
64
|
@log.debug("Filter: Delays: not blocking because neither of the time comparison " +
|
53
65
|
"conditions were met")
|
@@ -48,22 +48,15 @@ module Flapjack
|
|
48
48
|
module Gateways
|
49
49
|
|
50
50
|
class API < Sinatra::Base
|
51
|
-
|
52
51
|
set :show_exceptions, false
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
@logger.error exception.message
|
61
|
-
@logger.error exception.backtrace.join("\n")
|
62
|
-
[503, {}, {:errors => [exception.message]}.to_json]
|
63
|
-
}
|
53
|
+
rescue_exception = Proc.new { |env, exception|
|
54
|
+
@logger.error exception.message
|
55
|
+
@logger.error exception.backtrace.join("\n")
|
56
|
+
[503, {}, {:errors => [exception.message]}.to_json]
|
57
|
+
}
|
58
|
+
use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
|
64
59
|
|
65
|
-
use Rack::FiberPool, :size => 25, :rescue_exception => rescue_exception
|
66
|
-
end
|
67
60
|
use Rack::MethodOverride
|
68
61
|
use Rack::JsonParamsParser
|
69
62
|
|
@@ -316,24 +309,395 @@ module Flapjack
|
|
316
309
|
content_type :json
|
317
310
|
|
318
311
|
errors = []
|
319
|
-
ret = nil
|
320
312
|
|
321
|
-
|
322
|
-
if
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
313
|
+
contacts_data = params[:contacts]
|
314
|
+
if contacts_data.nil? || !contacts_data.is_a?(Enumerable)
|
315
|
+
errors << "No valid contacts were submitted"
|
316
|
+
else
|
317
|
+
# stringifying as integer string params are automatically integered,
|
318
|
+
# but our redis ids are strings
|
319
|
+
contacts_data_ids = contacts_data.reject {|c| c['id'].nil? }.
|
320
|
+
map {|co| co['id'].to_s }
|
321
|
+
|
322
|
+
if contacts_data_ids.empty?
|
323
|
+
errors << "No contacts with IDs were submitted"
|
324
|
+
else
|
325
|
+
contacts = Flapjack::Data::Contact.all(:redis => redis)
|
326
|
+
contacts_h = hashify(*contacts) {|c| [c.id, c] }
|
327
|
+
contacts_ids = contacts_h.keys
|
328
|
+
|
329
|
+
# delete contacts not found in the bulk list
|
330
|
+
(contacts_ids - contacts_data_ids).each do |contact_to_delete_id|
|
331
|
+
contact_to_delete = contacts.detect {|c| c.id == contact_to_delete_id }
|
332
|
+
contact_to_delete.delete!
|
333
|
+
end
|
334
|
+
|
335
|
+
# add or update contacts found in the bulk list
|
336
|
+
contacts_data.reject {|cd| cd['id'].nil? }.each do |contact_data|
|
337
|
+
if contacts_ids.include?(contact_data['id'].to_s)
|
338
|
+
contacts_h[contact_data['id'].to_s].update(contact_data)
|
339
|
+
else
|
340
|
+
Flapjack::Data::Contact.add(contact_data, :redis => redis)
|
341
|
+
end
|
328
342
|
end
|
329
|
-
Flapjack::Data::Contact.add(contact, :redis => redis)
|
330
343
|
end
|
331
|
-
ret = 200
|
332
|
-
else
|
333
|
-
ret = 403
|
334
|
-
errors << "No valid contacts were submitted"
|
335
344
|
end
|
336
|
-
errors.empty? ?
|
345
|
+
errors.empty? ? 200 : [403, {}, {:errors => [errors]}.to_json]
|
346
|
+
end
|
347
|
+
|
348
|
+
# Returns all the contacts
|
349
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts
|
350
|
+
get '/contacts' do
|
351
|
+
content_type :json
|
352
|
+
Flapjack::Data::Contact.all(:redis => redis).to_json
|
353
|
+
end
|
354
|
+
|
355
|
+
# Returns the core information about the specified contact
|
356
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id
|
357
|
+
get '/contacts/:contact_id' do
|
358
|
+
content_type :json
|
359
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
360
|
+
if contact.nil?
|
361
|
+
logger.warn "contact not found with id #{params[:contact_id]}"
|
362
|
+
status 404
|
363
|
+
return
|
364
|
+
end
|
365
|
+
contact.to_json
|
366
|
+
end
|
367
|
+
|
368
|
+
# Lists this contact's notification rules
|
369
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_notification_rules
|
370
|
+
get '/contacts/:contact_id/notification_rules' do
|
371
|
+
content_type :json
|
372
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
373
|
+
if contact.nil?
|
374
|
+
logger.warn "contact not found with id #{params[:contact_id]}"
|
375
|
+
status 404
|
376
|
+
return
|
377
|
+
end
|
378
|
+
contact.notification_rules.to_json
|
379
|
+
end
|
380
|
+
|
381
|
+
# Get the specified notification rule for this user
|
382
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_notification_rules_id
|
383
|
+
get '/notification_rules/:rule_id' do
|
384
|
+
content_type :json
|
385
|
+
|
386
|
+
rule = Flapjack::Data::NotificationRule.find_by_id(params[:rule_id], :redis => redis)
|
387
|
+
if rule.nil?
|
388
|
+
logger.warn("Unable to find a notification rule with id [#{params[:rule_id]}]")
|
389
|
+
status 404
|
390
|
+
return
|
391
|
+
end
|
392
|
+
rule.to_json
|
393
|
+
end
|
394
|
+
|
395
|
+
# Creates a notification rule for a contact
|
396
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-post_contacts_id_notification_rules
|
397
|
+
post '/notification_rules' do
|
398
|
+
# # NB if parameters are correctly passed, we shouldn't mandate a request format
|
399
|
+
# pass unless 'application/json'.eql?(request.content_type)
|
400
|
+
content_type :json
|
401
|
+
|
402
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
403
|
+
if contact.nil?
|
404
|
+
logger.warn "contact not found with id #{params[:contact_id]}"
|
405
|
+
status 404
|
406
|
+
return
|
407
|
+
end
|
408
|
+
if params[:id]
|
409
|
+
logger.warn "post cannot be used for update, do a put instead"
|
410
|
+
status 403
|
411
|
+
return
|
412
|
+
end
|
413
|
+
|
414
|
+
rule_data = hashify(:entities, :entity_tags,
|
415
|
+
:warning_media, :critical_media, :time_restrictions,
|
416
|
+
:warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
|
417
|
+
rule = contact.add_notification_rule(rule_data)
|
418
|
+
rule.to_json
|
419
|
+
end
|
420
|
+
|
421
|
+
# Updates a notification rule
|
422
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-put_notification_rules_id
|
423
|
+
put('/notification_rules/:id') do
|
424
|
+
# # NB if parameters are correctly passed, we shouldn't mandate a request format
|
425
|
+
# pass unless 'application/json'.eql?(request.content_type)
|
426
|
+
content_type :json
|
427
|
+
|
428
|
+
ret = nil
|
429
|
+
|
430
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
431
|
+
if contact.nil?
|
432
|
+
logger.warn "contact not found with id #{params[:contact_id]}"
|
433
|
+
status 404
|
434
|
+
return
|
435
|
+
end
|
436
|
+
rule = Flapjack::Data::NotificationRule.find_by_id(params[:id], :redis => redis)
|
437
|
+
if rule.nil?
|
438
|
+
logger.warn "rule not found with id #{params[:id]}"
|
439
|
+
status 404
|
440
|
+
return
|
441
|
+
end
|
442
|
+
|
443
|
+
rule_data = hashify(:entities, :entity_tags,
|
444
|
+
:warning_media, :critical_media, :time_restrictions,
|
445
|
+
:warning_blackhole, :critical_blackhole) {|k| [k, params[k]]}
|
446
|
+
rule.update(rule_data)
|
447
|
+
rule.to_json
|
448
|
+
end
|
449
|
+
|
450
|
+
# Deletes a notification rule
|
451
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-put_notification_rules_id
|
452
|
+
delete('/notification_rules/:id') do
|
453
|
+
rule = Flapjack::Data::NotificationRule.find_by_id(params[:id], :redis => redis)
|
454
|
+
if rule.nil?
|
455
|
+
status 404
|
456
|
+
return
|
457
|
+
end
|
458
|
+
contact = Flapjack::Data::Contact.find_by_id(rule.contact_id, :redis => redis)
|
459
|
+
if contact.nil?
|
460
|
+
logger.warn "contact not found with id #{rule.contact_id}"
|
461
|
+
status 404
|
462
|
+
return
|
463
|
+
end
|
464
|
+
contact.delete_notification_rule(rule)
|
465
|
+
status 204
|
466
|
+
end
|
467
|
+
|
468
|
+
# Returns the media of a contact
|
469
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_media
|
470
|
+
get '/contacts/:contact_id/media' do
|
471
|
+
content_type :json
|
472
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
473
|
+
if contact.nil?
|
474
|
+
status 404
|
475
|
+
return
|
476
|
+
end
|
477
|
+
media = contact.media
|
478
|
+
media_intervals = contact.media_intervals
|
479
|
+
media_addr_int = hashify(*media.keys) {|k|
|
480
|
+
[k, {'address' => media[k],
|
481
|
+
'interval' => media_intervals[k] }]
|
482
|
+
}
|
483
|
+
media_addr_int.to_json
|
484
|
+
end
|
485
|
+
|
486
|
+
# Returns the specified media of a contact
|
487
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_media_media
|
488
|
+
get('/contacts/:contact_id/media/:media_id') do
|
489
|
+
content_type :json
|
490
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
491
|
+
if contact.nil?
|
492
|
+
status 404
|
493
|
+
return
|
494
|
+
end
|
495
|
+
if contact.media[params[:media_id]].nil?
|
496
|
+
status 404
|
497
|
+
return
|
498
|
+
end
|
499
|
+
{ 'address' => contact.media[params[:media_id]],
|
500
|
+
'interval' => contact.media_intervals[params[:media_id]] }.to_json
|
501
|
+
end
|
502
|
+
|
503
|
+
# Creates or updates a media of a contact
|
504
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-put_contacts_id_media_media
|
505
|
+
put('/contacts/:contact_id/media/:media_id') do
|
506
|
+
content_type :json
|
507
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
508
|
+
if contact.nil?
|
509
|
+
status 404
|
510
|
+
return
|
511
|
+
end
|
512
|
+
if params[:address].nil? || params[:interval].nil?
|
513
|
+
status 403
|
514
|
+
return
|
515
|
+
end
|
516
|
+
contact.set_address_for_media(params[:media_id], params[:address])
|
517
|
+
contact.set_interval_for_media(params[:media_id], params[:interval])
|
518
|
+
|
519
|
+
{ 'address' => contact.media[params[:media_id]],
|
520
|
+
'interval' => contact.media_intervals[params[:media_id]] }.to_json
|
521
|
+
end
|
522
|
+
|
523
|
+
# delete a media of a contact
|
524
|
+
delete('/contacts/:contact_id/media/:media_id') do
|
525
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
526
|
+
if contact.nil?
|
527
|
+
status 404
|
528
|
+
return
|
529
|
+
end
|
530
|
+
contact.remove_media(params[:media_id])
|
531
|
+
status 204
|
532
|
+
end
|
533
|
+
|
534
|
+
# Returns the timezone of a contact
|
535
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts_id_timezone
|
536
|
+
get('/contacts/:contact_id/timezone') do
|
537
|
+
content_type :json
|
538
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
539
|
+
if contact.nil?
|
540
|
+
status 404
|
541
|
+
return
|
542
|
+
end
|
543
|
+
contact.timezone.name.to_json
|
544
|
+
end
|
545
|
+
|
546
|
+
# Sets the timezone of a contact
|
547
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-put_contacts_id_timezone
|
548
|
+
put('/contacts/:contact_id/timezone') do
|
549
|
+
content_type :json
|
550
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
551
|
+
if contact.nil?
|
552
|
+
status 404
|
553
|
+
return
|
554
|
+
end
|
555
|
+
contact.timezone = params[:timezone]
|
556
|
+
contact.timezone.name.to_json
|
557
|
+
end
|
558
|
+
|
559
|
+
# Removes the timezone of a contact
|
560
|
+
# https://github.com/flpjck/flapjack/wiki/API#wiki-put_contacts_id_timezone
|
561
|
+
delete('/contacts/:contact_id/timezone') do
|
562
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
563
|
+
if contact.nil?
|
564
|
+
status 404
|
565
|
+
return
|
566
|
+
end
|
567
|
+
contact.timezone = nil
|
568
|
+
status 204
|
569
|
+
end
|
570
|
+
|
571
|
+
post '/contacts/:contact_id/tags' do
|
572
|
+
content_type :json
|
573
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
574
|
+
if contact.nil?
|
575
|
+
status 404
|
576
|
+
return
|
577
|
+
end
|
578
|
+
tags = params[:tag]
|
579
|
+
if tags.nil? || tags.empty?
|
580
|
+
status 403
|
581
|
+
return
|
582
|
+
end
|
583
|
+
tags = [tags] unless tags.respond_to?(:each)
|
584
|
+
contact.add_tags(*tags)
|
585
|
+
contact.tags.to_json
|
586
|
+
end
|
587
|
+
|
588
|
+
post '/contacts/:contact_id/entity_tags' do
|
589
|
+
content_type :json
|
590
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
591
|
+
if contact.nil?
|
592
|
+
status 404
|
593
|
+
return
|
594
|
+
end
|
595
|
+
contact.entities.map {|e| e[:entity]}.each do |entity|
|
596
|
+
next unless tags = params[:entity][entity.name]
|
597
|
+
entity.add_tags(*tags)
|
598
|
+
end
|
599
|
+
contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
|
600
|
+
[et[:entity].name, et[:tags]]
|
601
|
+
}
|
602
|
+
contact_ent_tag.to_json
|
603
|
+
end
|
604
|
+
|
605
|
+
delete '/contacts/:contact_id/tags' do
|
606
|
+
content_type :json
|
607
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
608
|
+
if contact.nil?
|
609
|
+
status 404
|
610
|
+
return
|
611
|
+
end
|
612
|
+
tags = params[:tag]
|
613
|
+
if tags.nil? || tags.empty?
|
614
|
+
status 403
|
615
|
+
return
|
616
|
+
end
|
617
|
+
tags = [tags] unless tags.respond_to?(:each)
|
618
|
+
contact.delete_tags(*tags)
|
619
|
+
status 204
|
620
|
+
end
|
621
|
+
|
622
|
+
delete '/contacts/:contact_id/entity_tags' do
|
623
|
+
content_type :json
|
624
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
625
|
+
if contact.nil?
|
626
|
+
status 404
|
627
|
+
return
|
628
|
+
end
|
629
|
+
contact.entities.map {|e| e[:entity]}.each do |entity|
|
630
|
+
next unless tags = params[:entity][entity.name]
|
631
|
+
entity.delete_tags(*tags)
|
632
|
+
end
|
633
|
+
status 204
|
634
|
+
end
|
635
|
+
|
636
|
+
get '/contacts/:contact_id/tags' do
|
637
|
+
content_type :json
|
638
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
639
|
+
if contact.nil?
|
640
|
+
status 404
|
641
|
+
return
|
642
|
+
end
|
643
|
+
contact.tags.to_json
|
644
|
+
end
|
645
|
+
|
646
|
+
get '/contacts/:contact_id/entity_tags' do
|
647
|
+
content_type :json
|
648
|
+
contact = Flapjack::Data::Contact.find_by_id(params[:contact_id], :redis => redis)
|
649
|
+
if contact.nil?
|
650
|
+
status 404
|
651
|
+
return
|
652
|
+
end
|
653
|
+
contact_ent_tag = hashify(*contact.entities(:tags => true)) {|et|
|
654
|
+
[et[:entity].name, et[:tags]]
|
655
|
+
}
|
656
|
+
contact_ent_tag.to_json
|
657
|
+
end
|
658
|
+
|
659
|
+
post '/entities/:entity/tags' do
|
660
|
+
content_type :json
|
661
|
+
entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
|
662
|
+
if entity.nil?
|
663
|
+
status 404
|
664
|
+
return
|
665
|
+
end
|
666
|
+
tags = params[:tag]
|
667
|
+
if tags.nil? || tags.empty?
|
668
|
+
status 403
|
669
|
+
return
|
670
|
+
end
|
671
|
+
tags = [tags] unless tags.respond_to?(:each)
|
672
|
+
entity.add_tags(*tags)
|
673
|
+
entity.tags.to_json
|
674
|
+
end
|
675
|
+
|
676
|
+
delete '/entities/:entity/tags' do
|
677
|
+
content_type :json
|
678
|
+
entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
|
679
|
+
if entity.nil?
|
680
|
+
status 404
|
681
|
+
return
|
682
|
+
end
|
683
|
+
tags = params[:tag]
|
684
|
+
if tags.nil? || tags.empty?
|
685
|
+
status 403
|
686
|
+
return
|
687
|
+
end
|
688
|
+
tags = [tags] unless tags.respond_to?(:each)
|
689
|
+
entity.delete_tags(*tags)
|
690
|
+
status 204
|
691
|
+
end
|
692
|
+
|
693
|
+
get '/entities/:entity/tags' do
|
694
|
+
content_type :json
|
695
|
+
entity = Flapjack::Data::Entity.find_by_name(params[:entity], :redis => redis)
|
696
|
+
if entity.nil?
|
697
|
+
status 404
|
698
|
+
return
|
699
|
+
end
|
700
|
+
entity.tags.to_json
|
337
701
|
end
|
338
702
|
|
339
703
|
not_found do
|
@@ -366,6 +730,22 @@ module Flapjack
|
|
366
730
|
nil
|
367
731
|
end
|
368
732
|
|
733
|
+
# The passed block will be provided each value from the args
|
734
|
+
# and must return array pairs [key, value] representing members of
|
735
|
+
# the hash this method returns. Keys should be unique -- if they're
|
736
|
+
# not, the earlier pair for that key will be overwritten.
|
737
|
+
def hashify(*args, &block)
|
738
|
+
key_value_pairs = args.map {|a| yield(a) }
|
739
|
+
|
740
|
+
# if using Ruby 1.9,
|
741
|
+
# Hash[ key_value_pairs ]
|
742
|
+
# is all that's needed, but for Ruby 1.8 compatability, these must
|
743
|
+
# be flattened and the resulting array unpacked. flatten(1) only
|
744
|
+
# flattens the arrays constructed in the block, it won't mess up
|
745
|
+
# any values (or keys) that are themselves arrays.
|
746
|
+
Hash[ *( key_value_pairs.flatten(1) )]
|
747
|
+
end
|
748
|
+
|
369
749
|
end
|
370
750
|
|
371
751
|
end
|