flapjack 0.6.61 → 0.7.0
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.
- 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
|