sensu 0.16.0-java → 0.17.0.beta.1-java

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/lib/sensu/api.rb DELETED
@@ -1,704 +0,0 @@
1
- require 'sensu/daemon'
2
-
3
- gem 'sinatra', '1.3.5'
4
- gem 'async_sinatra', '1.0.0'
5
-
6
- unless RUBY_PLATFORM =~ /java/
7
- gem 'thin', '1.5.0'
8
- require 'thin'
9
- end
10
-
11
- require 'sinatra/async'
12
-
13
- module Sensu
14
- class API < Sinatra::Base
15
- register Sinatra::Async
16
-
17
- class << self
18
- include Daemon
19
-
20
- def run(options={})
21
- bootstrap(options)
22
- setup_process(options)
23
- EM::run do
24
- start
25
- setup_signal_traps
26
- end
27
- end
28
-
29
- def on_reactor_run
30
- EM::next_tick do
31
- setup_redis
32
- set :redis, @redis
33
- setup_transport
34
- set :transport, @transport
35
- end
36
- end
37
-
38
- def bootstrap(options)
39
- setup_logger(options)
40
- set :logger, @logger
41
- load_settings(options)
42
- set :api, @settings[:api]
43
- set :checks, @settings[:checks]
44
- set :all_checks, @settings.checks
45
- set :cors, @settings[:cors] || {
46
- 'Origin' => '*',
47
- 'Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
48
- 'Credentials' => 'true',
49
- 'Headers' => 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
50
- }
51
- on_reactor_run
52
- self
53
- end
54
-
55
- def start_server
56
- Thin::Logging.silent = true
57
- bind = @settings[:api][:bind] || '0.0.0.0'
58
- @thin = Thin::Server.new(bind, @settings[:api][:port], self)
59
- @thin.start
60
- end
61
-
62
- def stop_server(&block)
63
- @thin.stop
64
- retry_until_true do
65
- unless @thin.running?
66
- block.call
67
- true
68
- end
69
- end
70
- end
71
-
72
- def start
73
- start_server
74
- super
75
- end
76
-
77
- def stop
78
- @logger.warn('stopping')
79
- stop_server do
80
- @redis.close
81
- @transport.close
82
- super
83
- end
84
- end
85
-
86
- def test(options={})
87
- bootstrap(options)
88
- start
89
- end
90
- end
91
-
92
- configure do
93
- disable :protection
94
- disable :show_exceptions
95
- end
96
-
97
- not_found do
98
- ''
99
- end
100
-
101
- error do
102
- ''
103
- end
104
-
105
- helpers do
106
- def request_log_line
107
- settings.logger.info([env['REQUEST_METHOD'], env['REQUEST_PATH']].join(' '), {
108
- :remote_address => env['REMOTE_ADDR'],
109
- :user_agent => env['HTTP_USER_AGENT'],
110
- :request_method => env['REQUEST_METHOD'],
111
- :request_uri => env['REQUEST_URI'],
112
- :request_body => env['rack.input'].read
113
- })
114
- env['rack.input'].rewind
115
- end
116
-
117
- def protected!
118
- if settings.api[:user] && settings.api[:password]
119
- return if !(settings.api[:user] && settings.api[:password]) || authorized?
120
- headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
121
- unauthorized!
122
- end
123
- end
124
-
125
- def authorized?
126
- @auth ||= Rack::Auth::Basic::Request.new(request.env)
127
- @auth.provided? &&
128
- @auth.basic? &&
129
- @auth.credentials &&
130
- @auth.credentials == [settings.api[:user], settings.api[:password]]
131
- end
132
-
133
- def bad_request!
134
- ahalt 400
135
- end
136
-
137
- def unauthorized!
138
- throw(:halt, [401, ''])
139
- end
140
-
141
- def not_found!
142
- ahalt 404
143
- end
144
-
145
- def unavailable!
146
- ahalt 503
147
- end
148
-
149
- def created!(response)
150
- status 201
151
- body response
152
- end
153
-
154
- def accepted!(response)
155
- status 202
156
- body response
157
- end
158
-
159
- def issued!
160
- accepted!(MultiJson.dump(:issued => Time.now.to_i))
161
- end
162
-
163
- def no_content!
164
- status 204
165
- body ''
166
- end
167
-
168
- def read_data(rules={}, &block)
169
- begin
170
- data = MultiJson.load(env['rack.input'].read)
171
- valid = rules.all? do |key, rule|
172
- data[key].is_a?(rule[:type]) || (rule[:nil_ok] && data[key].nil?)
173
- end
174
- if valid
175
- block.call(data)
176
- else
177
- bad_request!
178
- end
179
- rescue MultiJson::ParseError
180
- bad_request!
181
- end
182
- end
183
-
184
- def integer_parameter(parameter)
185
- parameter =~ /^[0-9]+$/ ? parameter.to_i : nil
186
- end
187
-
188
- def pagination(items)
189
- limit = integer_parameter(params[:limit])
190
- offset = integer_parameter(params[:offset]) || 0
191
- unless limit.nil?
192
- headers['X-Pagination'] = MultiJson.dump(
193
- :limit => limit,
194
- :offset => offset,
195
- :total => items.size
196
- )
197
- paginated = items.slice(offset, limit)
198
- Array(paginated)
199
- else
200
- items
201
- end
202
- end
203
-
204
- def transport_info(&block)
205
- info = {
206
- :keepalives => {
207
- :messages => nil,
208
- :consumers => nil
209
- },
210
- :results => {
211
- :messages => nil,
212
- :consumers => nil
213
- },
214
- :connected => settings.transport.connected?
215
- }
216
- if settings.transport.connected?
217
- settings.transport.stats('keepalives') do |stats|
218
- info[:keepalives] = stats
219
- settings.transport.stats('results') do |stats|
220
- info[:results] = stats
221
- block.call(info)
222
- end
223
- end
224
- else
225
- block.call(info)
226
- end
227
- end
228
-
229
- def resolve_event(event_json)
230
- event = MultiJson.load(event_json)
231
- check = event[:check].merge(
232
- :output => 'Resolving on request of the API',
233
- :status => 0,
234
- :issued => Time.now.to_i,
235
- :executed => Time.now.to_i,
236
- :force_resolve => true
237
- )
238
- check.delete(:history)
239
- payload = {
240
- :client => event[:client][:name],
241
- :check => check
242
- }
243
- settings.logger.info('publishing check result', {
244
- :payload => payload
245
- })
246
- settings.transport.publish(:direct, 'results', MultiJson.dump(payload)) do |info|
247
- if info[:error]
248
- settings.logger.error('failed to publish check result', {
249
- :payload => payload,
250
- :error => info[:error].to_s
251
- })
252
- end
253
- end
254
- end
255
- end
256
-
257
- before do
258
- request_log_line
259
- content_type 'application/json'
260
- settings.cors.each do |header, value|
261
- headers['Access-Control-Allow-' + header] = value
262
- end
263
- protected! unless env['REQUEST_METHOD'] == 'OPTIONS'
264
- end
265
-
266
- aoptions '/*' do
267
- body ''
268
- end
269
-
270
- aget '/info/?' do
271
- transport_info do |info|
272
- response = {
273
- :sensu => {
274
- :version => VERSION
275
- },
276
- :transport => info,
277
- :redis => {
278
- :connected => settings.redis.connected?
279
- }
280
- }
281
- body MultiJson.dump(response)
282
- end
283
- end
284
-
285
- aget '/health/?' do
286
- if settings.redis.connected? && settings.transport.connected?
287
- healthy = Array.new
288
- min_consumers = integer_parameter(params[:consumers])
289
- max_messages = integer_parameter(params[:messages])
290
- transport_info do |info|
291
- if min_consumers
292
- healthy << (info[:keepalives][:consumers] >= min_consumers)
293
- healthy << (info[:results][:consumers] >= min_consumers)
294
- end
295
- if max_messages
296
- healthy << (info[:keepalives][:messages] <= max_messages)
297
- healthy << (info[:results][:messages] <= max_messages)
298
- end
299
- healthy.all? ? no_content! : unavailable!
300
- end
301
- else
302
- unavailable!
303
- end
304
- end
305
-
306
- aget '/clients/?' do
307
- response = Array.new
308
- settings.redis.smembers('clients') do |clients|
309
- clients = pagination(clients)
310
- unless clients.empty?
311
- clients.each_with_index do |client_name, index|
312
- settings.redis.get('client:' + client_name) do |client_json|
313
- response << MultiJson.load(client_json)
314
- if index == clients.size - 1
315
- body MultiJson.dump(response)
316
- end
317
- end
318
- end
319
- else
320
- body MultiJson.dump(response)
321
- end
322
- end
323
- end
324
-
325
- aget %r{/clients?/([\w\.-]+)/?$} do |client_name|
326
- settings.redis.get('client:' + client_name) do |client_json|
327
- unless client_json.nil?
328
- body client_json
329
- else
330
- not_found!
331
- end
332
- end
333
- end
334
-
335
- aget %r{/clients/([\w\.-]+)/history/?$} do |client_name|
336
- response = Array.new
337
- settings.redis.smembers('history:' + client_name) do |checks|
338
- unless checks.empty?
339
- checks.each_with_index do |check_name, index|
340
- history_key = 'history:' + client_name + ':' + check_name
341
- settings.redis.lrange(history_key, -21, -1) do |history|
342
- history.map! do |status|
343
- status.to_i
344
- end
345
- execution_key = 'execution:' + client_name + ':' + check_name
346
- settings.redis.get(execution_key) do |last_execution|
347
- unless history.empty? || last_execution.nil?
348
- item = {
349
- :check => check_name,
350
- :history => history,
351
- :last_execution => last_execution.to_i,
352
- :last_status => history.last
353
- }
354
- response << item
355
- end
356
- if index == checks.size - 1
357
- body MultiJson.dump(response)
358
- end
359
- end
360
- end
361
- end
362
- else
363
- body MultiJson.dump(response)
364
- end
365
- end
366
- end
367
-
368
- adelete %r{/clients?/([\w\.-]+)/?$} do |client_name|
369
- settings.redis.get('client:' + client_name) do |client_json|
370
- unless client_json.nil?
371
- settings.redis.hgetall('events:' + client_name) do |events|
372
- events.each do |check_name, event_json|
373
- resolve_event(event_json)
374
- end
375
- EM::Timer.new(5) do
376
- client = MultiJson.load(client_json)
377
- settings.logger.info('deleting client', {
378
- :client => client
379
- })
380
- settings.redis.srem('clients', client_name) do
381
- settings.redis.del('client:' + client_name)
382
- settings.redis.del('events:' + client_name)
383
- settings.redis.smembers('history:' + client_name) do |checks|
384
- checks.each do |check_name|
385
- settings.redis.del('history:' + client_name + ':' + check_name)
386
- settings.redis.del('execution:' + client_name + ':' + check_name)
387
- end
388
- settings.redis.del('history:' + client_name)
389
- end
390
- end
391
- end
392
- issued!
393
- end
394
- else
395
- not_found!
396
- end
397
- end
398
- end
399
-
400
- aget '/checks/?' do
401
- body MultiJson.dump(settings.all_checks)
402
- end
403
-
404
- aget %r{/checks?/([\w\.-]+)/?$} do |check_name|
405
- if settings.checks[check_name]
406
- response = settings.checks[check_name].merge(:name => check_name)
407
- body MultiJson.dump(response)
408
- else
409
- not_found!
410
- end
411
- end
412
-
413
- apost '/request/?' do
414
- rules = {
415
- :check => {:type => String, :nil_ok => false},
416
- :subscribers => {:type => Array, :nil_ok => true}
417
- }
418
- read_data(rules) do |data|
419
- if settings.checks[data[:check]]
420
- check = settings.checks[data[:check]]
421
- subscribers = data[:subscribers] || check[:subscribers] || Array.new
422
- payload = {
423
- :name => data[:check],
424
- :command => check[:command],
425
- :issued => Time.now.to_i
426
- }
427
- settings.logger.info('publishing check request', {
428
- :payload => payload,
429
- :subscribers => subscribers
430
- })
431
- subscribers.uniq.each do |exchange_name|
432
- settings.transport.publish(:fanout, exchange_name, MultiJson.dump(payload)) do |info|
433
- if info[:error]
434
- settings.logger.error('failed to publish check request', {
435
- :exchange_name => exchange_name,
436
- :payload => payload,
437
- :error => info[:error].to_s
438
- })
439
- end
440
- end
441
- end
442
- issued!
443
- else
444
- not_found!
445
- end
446
- end
447
- end
448
-
449
- aget '/events/?' do
450
- response = Array.new
451
- settings.redis.smembers('clients') do |clients|
452
- unless clients.empty?
453
- clients.each_with_index do |client_name, index|
454
- settings.redis.hgetall('events:' + client_name) do |events|
455
- events.each do |check_name, event_json|
456
- response << MultiJson.load(event_json)
457
- end
458
- if index == clients.size - 1
459
- body MultiJson.dump(response)
460
- end
461
- end
462
- end
463
- else
464
- body MultiJson.dump(response)
465
- end
466
- end
467
- end
468
-
469
- aget %r{/events/([\w\.-]+)/?$} do |client_name|
470
- response = Array.new
471
- settings.redis.hgetall('events:' + client_name) do |events|
472
- events.each do |check_name, event_json|
473
- response << MultiJson.load(event_json)
474
- end
475
- body MultiJson.dump(response)
476
- end
477
- end
478
-
479
- aget %r{/events?/([\w\.-]+)/([\w\.-]+)/?$} do |client_name, check_name|
480
- settings.redis.hgetall('events:' + client_name) do |events|
481
- event_json = events[check_name]
482
- unless event_json.nil?
483
- body event_json
484
- else
485
- not_found!
486
- end
487
- end
488
- end
489
-
490
- adelete %r{/events?/([\w\.-]+)/([\w\.-]+)/?$} do |client_name, check_name|
491
- settings.redis.hgetall('events:' + client_name) do |events|
492
- if events.include?(check_name)
493
- resolve_event(events[check_name])
494
- issued!
495
- else
496
- not_found!
497
- end
498
- end
499
- end
500
-
501
- apost '/resolve/?' do
502
- rules = {
503
- :client => {:type => String, :nil_ok => false},
504
- :check => {:type => String, :nil_ok => false}
505
- }
506
- read_data(rules) do |data|
507
- settings.redis.hgetall('events:' + data[:client]) do |events|
508
- if events.include?(data[:check])
509
- resolve_event(events[data[:check]])
510
- issued!
511
- else
512
- not_found!
513
- end
514
- end
515
- end
516
- end
517
-
518
- aget '/aggregates/?' do
519
- response = Array.new
520
- settings.redis.smembers('aggregates') do |checks|
521
- unless checks.empty?
522
- checks.each_with_index do |check_name, index|
523
- settings.redis.smembers('aggregates:' + check_name) do |aggregates|
524
- aggregates.reverse!
525
- aggregates.map! do |issued|
526
- issued.to_i
527
- end
528
- item = {
529
- :check => check_name,
530
- :issued => aggregates
531
- }
532
- response << item
533
- if index == checks.size - 1
534
- body MultiJson.dump(response)
535
- end
536
- end
537
- end
538
- else
539
- body MultiJson.dump(response)
540
- end
541
- end
542
- end
543
-
544
- aget %r{/aggregates/([\w\.-]+)/?$} do |check_name|
545
- settings.redis.smembers('aggregates:' + check_name) do |aggregates|
546
- unless aggregates.empty?
547
- aggregates.reverse!
548
- aggregates.map! do |issued|
549
- issued.to_i
550
- end
551
- age = integer_parameter(params[:age])
552
- if age
553
- timestamp = Time.now.to_i - age
554
- aggregates.reject! do |issued|
555
- issued > timestamp
556
- end
557
- end
558
- body MultiJson.dump(pagination(aggregates))
559
- else
560
- not_found!
561
- end
562
- end
563
- end
564
-
565
- adelete %r{/aggregates/([\w\.-]+)/?$} do |check_name|
566
- settings.redis.smembers('aggregates:' + check_name) do |aggregates|
567
- unless aggregates.empty?
568
- aggregates.each do |check_issued|
569
- result_set = check_name + ':' + check_issued
570
- settings.redis.del('aggregation:' + result_set)
571
- settings.redis.del('aggregate:' + result_set)
572
- end
573
- settings.redis.del('aggregates:' + check_name) do
574
- settings.redis.srem('aggregates', check_name) do
575
- no_content!
576
- end
577
- end
578
- else
579
- not_found!
580
- end
581
- end
582
- end
583
-
584
- aget %r{/aggregates?/([\w\.-]+)/([\w\.-]+)/?$} do |check_name, check_issued|
585
- result_set = check_name + ':' + check_issued
586
- settings.redis.hgetall('aggregate:' + result_set) do |aggregate|
587
- unless aggregate.empty?
588
- response = aggregate.inject(Hash.new) do |totals, (status, count)|
589
- totals[status] = Integer(count)
590
- totals
591
- end
592
- settings.redis.hgetall('aggregation:' + result_set) do |results|
593
- parsed_results = results.inject(Array.new) do |parsed, (client_name, check_json)|
594
- check = MultiJson.load(check_json)
595
- parsed << check.merge(:client => client_name)
596
- end
597
- if params[:summarize]
598
- options = params[:summarize].split(',')
599
- if options.include?('output')
600
- outputs = Hash.new(0)
601
- parsed_results.each do |result|
602
- outputs[result[:output]] += 1
603
- end
604
- response[:outputs] = outputs
605
- end
606
- end
607
- if params[:results]
608
- response[:results] = parsed_results
609
- end
610
- body MultiJson.dump(response)
611
- end
612
- else
613
- not_found!
614
- end
615
- end
616
- end
617
-
618
- apost %r{/stash(?:es)?/(.*)/?} do |path|
619
- read_data do |data|
620
- settings.redis.set('stash:' + path, MultiJson.dump(data)) do
621
- settings.redis.sadd('stashes', path) do
622
- created!(MultiJson.dump(:path => path))
623
- end
624
- end
625
- end
626
- end
627
-
628
- aget %r{/stash(?:es)?/(.*)/?} do |path|
629
- settings.redis.get('stash:' + path) do |stash_json|
630
- unless stash_json.nil?
631
- body stash_json
632
- else
633
- not_found!
634
- end
635
- end
636
- end
637
-
638
- adelete %r{/stash(?:es)?/(.*)/?} do |path|
639
- settings.redis.exists('stash:' + path) do |stash_exists|
640
- if stash_exists
641
- settings.redis.srem('stashes', path) do
642
- settings.redis.del('stash:' + path) do
643
- no_content!
644
- end
645
- end
646
- else
647
- not_found!
648
- end
649
- end
650
- end
651
-
652
- aget '/stashes/?' do
653
- response = Array.new
654
- settings.redis.smembers('stashes') do |stashes|
655
- unless stashes.empty?
656
- stashes.each_with_index do |path, index|
657
- settings.redis.get('stash:' + path) do |stash_json|
658
- settings.redis.ttl('stash:' + path) do |ttl|
659
- unless stash_json.nil?
660
- item = {
661
- :path => path,
662
- :content => MultiJson.load(stash_json),
663
- :expire => ttl
664
- }
665
- response << item
666
- else
667
- settings.redis.srem('stashes', path)
668
- end
669
- if index == stashes.size - 1
670
- body MultiJson.dump(pagination(response))
671
- end
672
- end
673
- end
674
- end
675
- else
676
- body MultiJson.dump(response)
677
- end
678
- end
679
- end
680
-
681
- apost '/stashes/?' do
682
- rules = {
683
- :path => {:type => String, :nil_ok => false},
684
- :content => {:type => Hash, :nil_ok => false},
685
- :expire => {:type => Integer, :nil_ok => true}
686
- }
687
- read_data(rules) do |data|
688
- stash_key = 'stash:' + data[:path]
689
- settings.redis.set(stash_key, MultiJson.dump(data[:content])) do
690
- settings.redis.sadd('stashes', data[:path]) do
691
- response = MultiJson.dump(:path => data[:path])
692
- if data[:expire]
693
- settings.redis.expire(stash_key, data[:expire]) do
694
- created!(response)
695
- end
696
- else
697
- created!(response)
698
- end
699
- end
700
- end
701
- end
702
- end
703
- end
704
- end