flapjack 0.9.6 → 1.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +6 -0
  4. data/.travis.yml +20 -16
  5. data/CHANGELOG.md +11 -25
  6. data/Dockerfile +8 -0
  7. data/Gemfile +2 -5
  8. data/bin/flapjack +24 -213
  9. data/etc/flapjack_config.yaml.example +6 -30
  10. data/features/cli.feature +16 -14
  11. data/features/cli_flapjack-feed-events.feature +12 -13
  12. data/features/cli_flapjack-nagios-receiver.feature +14 -15
  13. data/features/cli_flapjack-populator.feature +16 -15
  14. data/features/cli_flapper.feature +12 -12
  15. data/features/cli_receive-events.feature +6 -5
  16. data/features/cli_simulate-failed-check.feature +7 -6
  17. data/features/steps/cli_steps.rb +2 -2
  18. data/features/support/env.rb +1 -0
  19. data/flapjack.gemspec +1 -0
  20. data/lib/flapjack/cli/flapper.rb +200 -0
  21. data/lib/flapjack/cli/import.rb +102 -0
  22. data/lib/flapjack/cli/receiver.rb +656 -0
  23. data/lib/flapjack/cli/server.rb +256 -0
  24. data/lib/flapjack/cli/simulate.rb +180 -0
  25. data/lib/flapjack/configuration.rb +2 -0
  26. data/lib/flapjack/data/entity_check.rb +5 -22
  27. data/lib/flapjack/data/event.rb +7 -12
  28. data/lib/flapjack/gateways/email.rb +4 -1
  29. data/lib/flapjack/gateways/jabber.rb +12 -36
  30. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +6 -6
  31. data/lib/flapjack/gateways/jsonapi/report_methods.rb +5 -3
  32. data/lib/flapjack/gateways/pagerduty.rb +1 -1
  33. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
  34. data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
  35. data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
  36. data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
  37. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
  38. data/lib/flapjack/gateways/web/views/check.html.erb +7 -7
  39. data/lib/flapjack/gateways/web/views/checks.html.erb +2 -3
  40. data/lib/flapjack/gateways/web/views/contact.html.erb +4 -4
  41. data/lib/flapjack/gateways/web/views/contacts.html.erb +2 -2
  42. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +1 -1
  43. data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
  44. data/lib/flapjack/gateways/web/views/entity.html.erb +1 -1
  45. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  46. data/lib/flapjack/gateways/web/views/layout.erb +10 -10
  47. data/lib/flapjack/gateways/web/views/self_stats.html.erb +1 -1
  48. data/lib/flapjack/gateways/web.rb +36 -7
  49. data/lib/flapjack/pikelet.rb +0 -2
  50. data/lib/flapjack/processor.rb +3 -1
  51. data/lib/flapjack/redis_pool.rb +2 -6
  52. data/lib/flapjack/version.rb +1 -1
  53. data/spec/lib/flapjack/coordinator_spec.rb +3 -3
  54. data/spec/lib/flapjack/data/entity_check_spec.rb +2 -6
  55. data/spec/lib/flapjack/data/event_spec.rb +0 -31
  56. data/spec/lib/flapjack/gateways/email_spec.rb +109 -0
  57. data/spec/lib/flapjack/gateways/jabber_spec.rb +18 -16
  58. data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +12 -24
  59. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
  60. data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +2 -0
  61. data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +2 -0
  62. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +2 -0
  63. data/spec/lib/flapjack/gateways/web_spec.rb +194 -145
  64. data/spec/lib/flapjack/redis_pool_spec.rb +0 -1
  65. data/spec/support/profile_all_formatter.rb +44 -0
  66. data/spec/support/uncolored_doc_formatter.rb +9 -0
  67. data/tasks/benchmarks.rake +0 -4
  68. metadata +28 -38
  69. data/.ruby-version +0 -1
  70. data/Gemfile-ruby1.9 +0 -28
  71. data/Gemfile-ruby1.9.lock +0 -227
  72. data/bin/flapjack-feed-events +0 -124
  73. data/bin/flapjack-nagios-receiver +0 -246
  74. data/bin/flapjack-nsca-receiver +0 -246
  75. data/bin/flapjack-populator +0 -132
  76. data/bin/flapper +0 -152
  77. data/bin/receive-events +0 -179
  78. data/bin/simulate-failed-check +0 -151
  79. data/lib/flapjack/data/migration.rb +0 -36
  80. data/lib/flapjack/gateways/api/contact_methods.rb +0 -369
  81. data/lib/flapjack/gateways/api/entity_check_presenter.rb +0 -218
  82. data/lib/flapjack/gateways/api/entity_methods.rb +0 -361
  83. data/lib/flapjack/gateways/api/entity_presenter.rb +0 -75
  84. data/lib/flapjack/gateways/api/rack/json_params_parser.rb +0 -26
  85. data/lib/flapjack/gateways/api.rb +0 -124
  86. data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +0 -772
  87. data/spec/lib/flapjack/gateways/api/entity_check_presenter_spec.rb +0 -211
  88. data/spec/lib/flapjack/gateways/api/entity_methods_spec.rb +0 -863
  89. data/spec/lib/flapjack/gateways/api/entity_presenter_spec.rb +0 -108
  90. data/spec/lib/flapjack/gateways/api_spec.rb +0 -30
@@ -1,218 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Formats entity/check data for presentation by the API methods in Flapjack::Gateways::API.
4
-
5
- require 'sinatra/base'
6
-
7
- require 'flapjack/data/entity_check'
8
-
9
- module Flapjack
10
-
11
- module Gateways
12
-
13
- class API < Sinatra::Base
14
-
15
- class EntityCheckPresenter
16
-
17
- def initialize(entity_check)
18
- @entity_check = entity_check
19
- end
20
-
21
- def status
22
- {'name' => @entity_check.check,
23
- 'state' => @entity_check.state,
24
- 'enabled' => @entity_check.enabled?,
25
- 'summary' => @entity_check.summary,
26
- 'details' => @entity_check.details,
27
- 'perfdata' => @entity_check.perfdata,
28
- 'in_unscheduled_maintenance' => @entity_check.in_unscheduled_maintenance?,
29
- 'in_scheduled_maintenance' => @entity_check.in_scheduled_maintenance?,
30
- 'last_update' => @entity_check.last_update,
31
- 'last_problem_notification' => @entity_check.last_notification_for_state(:problem)[:timestamp],
32
- 'last_recovery_notification' => @entity_check.last_notification_for_state(:recovery)[:timestamp],
33
- 'last_acknowledgement_notification' => @entity_check.last_notification_for_state(:acknowledgement)[:timestamp]}
34
- end
35
-
36
- def outages(start_time, end_time, options = {})
37
- # hist_states is an array of hashes, with [state, timestamp, summary] keys
38
- hist_states = @entity_check.historical_states(start_time, end_time)
39
- return hist_states if hist_states.empty?
40
-
41
- initial = @entity_check.historical_state_before(hist_states.first[:timestamp])
42
- hist_states.unshift(initial) if initial
43
-
44
- # TODO the following works, but isn't the neatest
45
- num_states = hist_states.size
46
-
47
- index = 0
48
- result = []
49
- obj = nil
50
-
51
- while index < num_states do
52
- last_obj = obj
53
- obj = hist_states[index]
54
- index += 1
55
-
56
- next if obj[:state] == 'ok'
57
-
58
- if last_obj && (last_obj[:state] == obj[:state])
59
- # TODO maybe build up arrays of these instead, and leave calling
60
- # classes to join them together if needed?
61
- result.last[:summary] << " / #{obj[:summary]}"
62
- result.last[:details] << " / #{obj[:details]}"
63
- next
64
- end
65
-
66
- ts = obj[:timestamp]
67
-
68
- obj_st = (last_obj || !start_time) ? ts : [ts, start_time].max
69
-
70
- next_ts_obj = hist_states[index..-1].detect {|hs| hs[:state] != obj[:state] }
71
- obj_et = next_ts_obj ? next_ts_obj[:timestamp] : end_time
72
-
73
- obj_dur = obj_et ? obj_et - obj_st : nil
74
-
75
- result << {:state => obj[:state],
76
- :start_time => obj_st,
77
- :end_time => obj_et,
78
- :duration => obj_dur,
79
- :summary => obj[:summary] || '',
80
- :details => obj[:details] || ''
81
- }
82
- end
83
-
84
- result
85
- end
86
-
87
- def unscheduled_maintenances(start_time, end_time)
88
- # unsched_maintenance is an array of hashes, with [duration, timestamp, summary] keys
89
- unsched_maintenance = @entity_check.maintenances(start_time, end_time,
90
- :scheduled => false)
91
-
92
- # to see if we start in an unscheduled maintenance period, we must check all unscheduled
93
- # maintenances before the period and their durations
94
- start_in_unsched = start_time.nil? ? [] :
95
- @entity_check.maintenances(nil, start_time, :scheduled => false).select {|pu|
96
- pu[:end_time] >= start_time
97
- }
98
-
99
- start_in_unsched + unsched_maintenance
100
- end
101
-
102
- def scheduled_maintenances(start_time, end_time)
103
- # sched_maintenance is an array of hashes, with [duration, timestamp, summary] keys
104
- sched_maintenance = @entity_check.maintenances(start_time, end_time,
105
- :scheduled => true)
106
-
107
- # to see if we start in a scheduled maintenance period, we must check all scheduled
108
- # maintenances before the period and their durations
109
- start_in_sched = start_time.nil? ? [] :
110
- @entity_check.maintenances(nil, start_time, :scheduled => true).select {|ps|
111
- ps[:end_time] >= start_time
112
- }
113
-
114
- start_in_sched + sched_maintenance
115
- end
116
-
117
- # TODO test whether the below overlapping logic is prone to off-by-one
118
- # errors; the numbers may line up more neatly if we consider outages to
119
- # start one second after the maintenance period ends.
120
- #
121
- # TODO test performance with larger data sets
122
- def downtime(start_time, end_time)
123
- sched_maintenances = scheduled_maintenances(start_time, end_time)
124
-
125
- outs = outages(start_time, end_time)
126
-
127
- total_secs = {}
128
- percentages = {}
129
-
130
- outs.collect {|obj| obj[:state]}.uniq.each do |st|
131
- total_secs[st] = 0
132
- percentages[st] = (start_time.nil? || end_time.nil?) ? nil : 0
133
- end
134
-
135
- unless outs.empty?
136
-
137
- # Initially we need to check for cases where a scheduled
138
- # maintenance period is fully covered by an outage period.
139
- # We then create two new outage periods to cover the time around
140
- # the scheduled maintenance period, and remove the original.
141
-
142
- sched_maintenances.each do |sm|
143
-
144
- split_outs = []
145
-
146
- outs.each { |o|
147
- next unless o[:end_time] && (o[:start_time] < sm[:start_time]) &&
148
- (o[:end_time] > sm[:end_time])
149
- o[:delete] = true
150
- split_outs += [{:state => o[:state],
151
- :start_time => o[:start_time],
152
- :end_time => sm[:start_time],
153
- :duration => sm[:start_time] - o[:start_time],
154
- :summary => "#{o[:summary]} [split start]"},
155
- {:state => o[:state],
156
- :start_time => sm[:end_time],
157
- :end_time => o[:end_time],
158
- :duration => o[:end_time] - sm[:end_time],
159
- :summary => "#{o[:summary]} [split finish]"}]
160
- }
161
-
162
- outs.reject! {|o| o[:delete]}
163
- outs += split_outs
164
- # not strictly necessary to keep the data sorted, but
165
- # will make more sense while debgging
166
- outs.sort! {|a,b| a[:start_time] <=> b[:start_time]}
167
- end
168
-
169
- sched_maintenances.each do |sm|
170
-
171
- outs.each do |o|
172
- next unless o[:end_time] && (sm[:start_time] < o[:end_time]) &&
173
- (sm[:end_time] > o[:start_time])
174
-
175
- if sm[:start_time] <= o[:start_time] &&
176
- sm[:end_time] >= o[:end_time]
177
-
178
- # outage is fully overlapped by the scheduled maintenance
179
- o[:delete] = true
180
-
181
- elsif sm[:start_time] <= o[:start_time]
182
- # partially overlapping on the earlier side
183
- o[:start_time] = sm[:end_time]
184
- o[:duration] = o[:end_time] - o[:start_time]
185
- elsif sm[:end_time] >= o[:end_time]
186
- # partially overlapping on the later side
187
- o[:end_time] = sm[:start_time]
188
- o[:duration] = o[:end_time] - o[:start_time]
189
- end
190
- end
191
-
192
- outs.reject! {|o| o[:delete]}
193
- end
194
-
195
- total_secs = outs.inject(total_secs) {|ret, o|
196
- ret[o[:state]] += o[:duration] if o[:duration]
197
- ret
198
- }
199
-
200
- unless (start_time.nil? || end_time.nil?)
201
- total_secs.each_pair do |st, ts|
202
- percentages[st] = (total_secs[st] * 100.0) / (end_time.to_f - start_time.to_f)
203
- end
204
- total_secs['ok'] = (end_time - start_time) - total_secs.values.reduce(:+)
205
- percentages['ok'] = 100 - percentages.values.reduce(:+)
206
- end
207
- end
208
-
209
- {:total_seconds => total_secs, :percentages => percentages, :downtime => outs}
210
- end
211
-
212
- end
213
-
214
- end
215
-
216
- end
217
-
218
- end
@@ -1,361 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'sinatra/base'
4
-
5
- require 'flapjack/data/entity'
6
- require 'flapjack/data/entity_check'
7
-
8
- require 'flapjack/gateways/api/entity_presenter'
9
- require 'flapjack/gateways/api/entity_check_presenter'
10
-
11
- module Flapjack
12
-
13
- module Gateways
14
-
15
- class API < Sinatra::Base
16
-
17
- class EntityCheckNotFound < RuntimeError
18
- attr_reader :entity, :check
19
- def initialize(entity, check)
20
- @entity = entity
21
- @check = check
22
- end
23
- end
24
-
25
- class EntityNotFound < RuntimeError
26
- attr_reader :entity
27
- def initialize(entity)
28
- @entity = entity
29
- end
30
- end
31
-
32
- module EntityMethods
33
-
34
- module Helpers
35
-
36
- def find_entity(entity_name)
37
- entity = Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis)
38
- raise Flapjack::Gateways::API::EntityNotFound.new(entity_name) if entity.nil?
39
- entity
40
- end
41
-
42
- def find_entity_check(entity, check)
43
- entity_check = Flapjack::Data::EntityCheck.for_entity(entity,
44
- check, :redis => redis)
45
- raise Flapjack::Gateways::API::EntityCheckNotFound.new(entity, check) if entity_check.nil?
46
- entity_check
47
- end
48
-
49
- def find_tags(tags)
50
- halt err(403, "no tags") if tags.nil? || tags.empty?
51
- tags
52
- end
53
-
54
- def entities_and_checks(entity_name, check)
55
- if entity_name
56
- # backwards-compatible, single entity or entity&check from route
57
- entities = check ? nil : [entity_name]
58
- checks = check ? {entity_name => check} : nil
59
- else
60
- # new and improved bulk API queries
61
- entities = params[:entity]
62
- checks = params[:check]
63
- entities = [entities] unless entities.nil? || entities.is_a?(Array)
64
- # TODO err if checks isn't a Hash (similar rules as in flapjack-diner)
65
- end
66
- [entities, checks]
67
- end
68
-
69
- def bulk_api_check_action(entities, entity_checks, action, params = {})
70
- unless entities.nil? || entities.empty?
71
- entities.each do |entity_name|
72
- entity = find_entity(entity_name)
73
- checks = entity.check_list.sort
74
- checks.each do |check|
75
- action.call( find_entity_check(entity, check) )
76
- end
77
- end
78
- end
79
-
80
- unless entity_checks.nil? || entity_checks.empty?
81
- entity_checks.each_pair do |entity_name, checks|
82
- entity = find_entity(entity_name)
83
- checks = [checks] unless checks.is_a?(Array)
84
- checks.each do |check|
85
- action.call( find_entity_check(entity, check) )
86
- end
87
- end
88
- end
89
- end
90
-
91
- def present_api_results(entities, entity_checks, result_type, &block)
92
- result = []
93
-
94
- unless entities.nil? || entities.empty?
95
- result += entities.collect {|entity_name|
96
- entity = find_entity(entity_name)
97
- yield(Flapjack::Gateways::API::EntityPresenter.new(entity, :redis => redis))
98
- }.flatten(1)
99
- end
100
-
101
- unless entity_checks.nil? || entity_checks.empty?
102
- result += entity_checks.inject([]) {|memo, (entity_name, checks)|
103
- checks = [checks] unless checks.is_a?(Array)
104
- entity = find_entity(entity_name)
105
- memo += checks.collect {|check|
106
- entity_check = find_entity_check(entity, check)
107
- {:entity => entity_name,
108
- :check => check,
109
- result_type.to_sym => yield(Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check))
110
- }
111
- }
112
- }.flatten(1)
113
- end
114
-
115
- result
116
- end
117
-
118
- # NB: casts to UTC before converting to a timestamp
119
- def validate_and_parsetime(value)
120
- return unless value
121
- Time.iso8601(value).getutc.to_i
122
- rescue ArgumentError => e
123
- logger.error "Couldn't parse time from '#{value}'"
124
- nil
125
- end
126
-
127
- end
128
-
129
- # used for backwards-compatible route matching below
130
- ENTITY_CHECK_FRAGMENT = '(?:/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(.+))?)?'
131
-
132
- def self.registered(app)
133
-
134
- app.helpers Flapjack::Gateways::API::EntityMethods::Helpers
135
-
136
- app.get '/entities' do
137
- content_type :json
138
- ret = Flapjack::Data::Entity.all(:redis => redis).collect {|e|
139
- presenter = Flapjack::Gateways::API::EntityPresenter.new(e, :redis => redis)
140
- {'id' => e.id, 'name' => e.name, 'checks' => presenter.status }
141
- }
142
- ret.to_json
143
- end
144
-
145
- app.get '/checks/:entity' do
146
- content_type :json
147
- entity = find_entity(params[:entity])
148
- entity.check_list.to_json
149
- end
150
-
151
- app.get %r{/status#{ENTITY_CHECK_FRAGMENT}} do
152
- content_type :json
153
-
154
- captures = params[:captures] || []
155
- entity_name = captures[0]
156
- check = captures[1]
157
-
158
- entities, checks = entities_and_checks(entity_name, check)
159
-
160
- results = present_api_results(entities, checks, 'status') {|presenter|
161
- presenter.status
162
- }
163
-
164
- if entity_name
165
- # compatible with previous data format
166
- results = results.collect {|status_h| status_h[:status]}
167
- check ? results.first.to_json : "[" + results.map {|r| r.to_json }.join(',') + "]"
168
- else
169
- # new and improved data format which reflects the request param structure
170
- "[" + results.map {|r| r.to_json }.join(',') + "]"
171
- end
172
- end
173
-
174
- app.get %r{/((?:outages|(?:un)?scheduled_maintenances|downtime))#{ENTITY_CHECK_FRAGMENT}} do
175
- action = params[:captures][0].to_sym
176
- entity_name = params[:captures][1]
177
- check = params[:captures][2]
178
-
179
- entities, checks = entities_and_checks(entity_name, check)
180
-
181
- start_time = validate_and_parsetime(params[:start_time])
182
- end_time = validate_and_parsetime(params[:end_time])
183
-
184
- results = present_api_results(entities, checks, action) {|presenter|
185
- presenter.send(action, start_time, end_time)
186
- }
187
-
188
- if check
189
- # compatible with previous data format
190
- results.first[action].to_json
191
- elsif entity_name
192
- # compatible with previous data format
193
- rename = {:unscheduled_maintenances => :unscheduled_maintenance,
194
- :scheduled_maintenances => :scheduled_maintenance}
195
- drop = [:entity]
196
- results.collect{|r|
197
- r.inject({}) {|memo, (k, v)|
198
- if new_k = rename[k]
199
- memo[new_k] = v
200
- elsif !drop.include?(k)
201
- memo[k] = v
202
- end
203
- memo
204
- }
205
- }.to_json
206
- else
207
- # new and improved data format which reflects the request param structure
208
- results.to_json
209
- end
210
- end
211
-
212
- # create a scheduled maintenance period for a check on an entity
213
- app.post %r{/scheduled_maintenances#{ENTITY_CHECK_FRAGMENT}} do
214
-
215
- captures = params[:captures] || []
216
- entity_name = captures[0]
217
- check = captures[1]
218
-
219
- entities, checks = entities_and_checks(entity_name, check)
220
-
221
- start_time = validate_and_parsetime(params[:start_time])
222
- halt( err(403, "start time must be provided") ) unless start_time
223
-
224
- act_proc = proc {|entity_check|
225
- entity_check.create_scheduled_maintenance(start_time,
226
- params[:duration].to_i, :summary => params[:summary])
227
- }
228
-
229
- bulk_api_check_action(entities, checks, act_proc)
230
- status 204
231
- end
232
-
233
- # create an acknowledgement for a service on an entity
234
- # NB currently, this does not acknowledge a specific failure event, just
235
- # the entity-check as a whole
236
- app.post %r{/acknowledgements#{ENTITY_CHECK_FRAGMENT}} do
237
- captures = params[:captures] || []
238
- entity_name = captures[0]
239
- check = captures[1]
240
-
241
- entities, checks = entities_and_checks(entity_name, check)
242
-
243
- dur = params[:duration] ? params[:duration].to_i : nil
244
- duration = (dur.nil? || (dur <= 0)) ? (4 * 60 * 60) : dur
245
- summary = params[:summary]
246
-
247
- opts = {'duration' => duration}
248
- opts['summary'] = summary if summary
249
-
250
- act_proc = proc {|entity_check|
251
- Flapjack::Data::Event.create_acknowledgement(
252
- entity_check.entity_name, entity_check.check,
253
- :summary => params[:summary],
254
- :duration => duration,
255
- :redis => redis)
256
- }
257
-
258
- bulk_api_check_action(entities, checks, act_proc)
259
- status 204
260
- end
261
-
262
- app.delete %r{/((?:un)?scheduled_maintenances)} do
263
- action = params[:captures][0]
264
-
265
- # no backwards-compatible mode here, it's a new method
266
- entities, checks = entities_and_checks(nil, nil)
267
-
268
- act_proc = case action
269
- when 'scheduled_maintenances'
270
- start_time = validate_and_parsetime(params[:start_time])
271
- halt( err(403, "start time must be provided") ) unless start_time
272
- opts = {}
273
- proc {|entity_check| entity_check.end_scheduled_maintenance(start_time.to_i) }
274
- when 'unscheduled_maintenances'
275
- end_time = validate_and_parsetime(params[:end_time]) || Time.now
276
- proc {|entity_check| entity_check.end_unscheduled_maintenance(end_time.to_i) }
277
- end
278
-
279
- bulk_api_check_action(entities, checks, act_proc)
280
- status 204
281
- end
282
-
283
- app.post %r{/test_notifications#{ENTITY_CHECK_FRAGMENT}} do
284
- captures = params[:captures] || []
285
- entity_name = captures[0]
286
- check = captures[1]
287
-
288
- entities, checks = entities_and_checks(entity_name, check)
289
-
290
- act_proc = proc {|entity_check|
291
- summary = params[:summary] ||
292
- "Testing notifications to all contacts interested in entity #{entity_check.entity.name}"
293
- Flapjack::Data::Event.test_notifications(
294
- entity_check.entity_name, entity_check.check,
295
- :summary => summary,
296
- :redis => redis)
297
- }
298
-
299
- bulk_api_check_action(entities, checks, act_proc)
300
- status 204
301
- end
302
-
303
- app.post '/entities' do
304
- pass unless 'application/json'.eql?(request.content_type)
305
-
306
- errors = []
307
- ret = nil
308
-
309
- # FIXME should scan for invalid records before making any changes, fail early
310
-
311
- entities = params[:entities]
312
- unless entities
313
- logger.debug("no entities object found in the following supplied JSON:")
314
- logger.debug(request.body)
315
- return err(403, "No entities object received")
316
- end
317
- return err(403, "The received entities object is not an Enumerable") unless entities.is_a?(Enumerable)
318
- return err(403, "Entity with a nil id detected") unless entities.any? {|e| !e['id'].nil?}
319
-
320
- entities.each do |entity|
321
- unless entity['id']
322
- errors << "Entity not imported as it has no id: #{entity.inspect}"
323
- next
324
- end
325
- Flapjack::Data::Entity.add(entity, :redis => redis)
326
- end
327
- errors.empty? ? 204 : err(403, *errors)
328
- end
329
-
330
- app.post '/entities/:entity/tags' do
331
- content_type :json
332
-
333
- tags = find_tags(params[:tag])
334
- entity = find_entity(params[:entity])
335
- entity.add_tags(*tags)
336
- entity.tags.to_json
337
- end
338
-
339
- app.delete '/entities/:entity/tags' do
340
- tags = find_tags(params[:tag])
341
- entity = find_entity(params[:entity])
342
- entity.delete_tags(*tags)
343
- status 204
344
- end
345
-
346
- app.get '/entities/:entity/tags' do
347
- content_type :json
348
-
349
- entity = find_entity(params[:entity])
350
- entity.tags.to_json
351
- end
352
-
353
- end
354
-
355
- end
356
-
357
- end
358
-
359
- end
360
-
361
- end
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Formats entity data for presentation by the API methods in Flapjack::Gateways::API.
4
- # Currently this just aggregates all of the check data for an entity, leaving
5
- # clients to make any further calculations for themselves.
6
-
7
- require 'sinatra/base'
8
-
9
- require 'flapjack/gateways/api/entity_check_presenter'
10
- require 'flapjack/data/entity_check'
11
-
12
- module Flapjack
13
-
14
- module Gateways
15
-
16
- class API < Sinatra::Base
17
-
18
- class EntityPresenter
19
-
20
- def initialize(entity, options = {})
21
- @entity = entity
22
- @redis = options[:redis]
23
- end
24
-
25
- def status
26
- checks.collect {|c| {:entity => @entity.name, :check => c,
27
- :status => check_presenter(c).status } }
28
- end
29
-
30
- def outages(start_time, end_time)
31
- checks.collect {|c|
32
- {:entity => @entity.name, :check => c, :outages => check_presenter(c).outages(start_time, end_time)}
33
- }
34
- end
35
-
36
- def unscheduled_maintenances(start_time, end_time)
37
- checks.collect {|c|
38
- {:entity => @entity.name, :check => c, :unscheduled_maintenances =>
39
- check_presenter(c).unscheduled_maintenances(start_time, end_time)}
40
- }
41
- end
42
-
43
- def scheduled_maintenances(start_time, end_time)
44
- checks.collect {|c|
45
- {:entity => @entity.name, :check => c, :scheduled_maintenances =>
46
- check_presenter(c).scheduled_maintenances(start_time, end_time)}
47
- }
48
- end
49
-
50
- def downtime(start_time, end_time)
51
- checks.collect {|c|
52
- {:entity => @entity.name, :check => c, :downtime =>
53
- check_presenter(c).downtime(start_time, end_time)}
54
- }
55
- end
56
-
57
- private
58
-
59
- def checks
60
- @check_list ||= @entity.check_list.sort
61
- end
62
-
63
- def check_presenter(check)
64
- entity_check = Flapjack::Data::EntityCheck.for_entity(@entity, check,
65
- :redis => @redis)
66
- presenter = Flapjack::Gateways::API::EntityCheckPresenter.new(entity_check)
67
- end
68
-
69
- end
70
-
71
- end
72
-
73
- end
74
-
75
- end
@@ -1,26 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rack'
4
-
5
- module Rack
6
- class JsonParamsParser < Struct.new(:app)
7
- def call(env)
8
- if env['rack.input'] and not input_parsed?(env) and type_match?(env)
9
- env['rack.request.form_input'] = env['rack.input']
10
- data = env['rack.input'].read
11
- env['rack.input'].rewind
12
- env['rack.request.form_hash'] = data.empty? ? {} : Oj.load(data)
13
- end
14
- app.call(env)
15
- end
16
-
17
- def input_parsed? env
18
- env['rack.request.form_input'].eql? env['rack.input']
19
- end
20
-
21
- def type_match? env
22
- type = env['CONTENT_TYPE'] and
23
- type.split(/\s*[;,]\s*/, 2).first.downcase == 'application/json'
24
- end
25
- end
26
- end