sensu 0.11.3 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 0.12.0 - 2013-10-28
2
+
3
+ ### Non-backwards compatible changes
4
+
5
+ Deprecated API endpoints, `/check/request` and `/event/resolve`, have been
6
+ removed. Please use `/request` and `/resolve`.
7
+
8
+ ### Features
9
+
10
+ API stashes can now expire, automatically removing themselves after `N`
11
+ seconds, eg. '{"path": "foo", "content":{"bar": "baz"}, "expire": 600}'.
12
+
13
+ ### Other
14
+
15
+ Added additional AMQP library version constraints.
16
+
17
+ Improved API POST data validation.
18
+
1
19
  ## 0.11.3 - 2013-10-23
2
20
 
3
21
  ### Other
data/lib/sensu/api.rb CHANGED
@@ -137,26 +137,6 @@ module Sensu
137
137
  env['rack.input'].rewind
138
138
  end
139
139
 
140
- def integer_parameter(parameter)
141
- parameter =~ /^[0-9]+$/ ? parameter.to_i : nil
142
- end
143
-
144
- def pagination(items)
145
- limit = integer_parameter(params[:limit])
146
- offset = integer_parameter(params[:offset]) || 0
147
- unless limit.nil?
148
- headers['X-Pagination'] = Oj.dump(
149
- :limit => limit,
150
- :offset => offset,
151
- :total => items.size
152
- )
153
- paginated = items.slice(offset, limit)
154
- Array(paginated)
155
- else
156
- items
157
- end
158
- end
159
-
160
140
  def bad_request!
161
141
  ahalt 400
162
142
  end
@@ -188,6 +168,42 @@ module Sensu
188
168
  body ''
189
169
  end
190
170
 
171
+ def read_data(rules={}, &block)
172
+ begin
173
+ data = Oj.load(env['rack.input'].read)
174
+ valid = rules.all? do |key, rule|
175
+ data[key].is_a?(rule[:type]) || (rule[:nil_ok] && data[key].nil?)
176
+ end
177
+ if valid
178
+ block.call(data)
179
+ else
180
+ bad_request!
181
+ end
182
+ rescue Oj::ParseError
183
+ bad_request!
184
+ end
185
+ end
186
+
187
+ def integer_parameter(parameter)
188
+ parameter =~ /^[0-9]+$/ ? parameter.to_i : nil
189
+ end
190
+
191
+ def pagination(items)
192
+ limit = integer_parameter(params[:limit])
193
+ offset = integer_parameter(params[:offset]) || 0
194
+ unless limit.nil?
195
+ headers['X-Pagination'] = Oj.dump(
196
+ :limit => limit,
197
+ :offset => offset,
198
+ :total => items.size
199
+ )
200
+ paginated = items.slice(offset, limit)
201
+ Array(paginated)
202
+ else
203
+ items
204
+ end
205
+ end
206
+
191
207
  def rabbitmq_info(&block)
192
208
  info = {
193
209
  :keepalives => {
@@ -389,38 +405,31 @@ module Sensu
389
405
  end
390
406
  end
391
407
 
392
- apost %r{/(?:check/)?request$} do
393
- begin
394
- post_body = Oj.load(request.body.read)
395
- check_name = post_body[:check]
396
- subscribers = post_body[:subscribers]
397
- if check_name.is_a?(String) && subscribers.is_a?(Array)
398
- if $settings.check_exists?(check_name)
399
- check = $settings[:checks][check_name]
400
- if subscribers.empty?
401
- subscribers = check[:subscribers] || Array.new
402
- end
403
- payload = {
404
- :name => check_name,
405
- :command => check[:command],
406
- :issued => Time.now.to_i
407
- }
408
- $logger.info('publishing check request', {
409
- :payload => payload,
410
- :subscribers => subscribers
411
- })
412
- subscribers.uniq.each do |exchange_name|
413
- $amq.fanout(exchange_name).publish(Oj.dump(payload))
414
- end
415
- issued!
416
- else
417
- not_found!
408
+ apost '/request' do
409
+ rules = {
410
+ :check => {:type => String, :nil_ok => false},
411
+ :subscribers => {:type => Array, :nil_ok => true}
412
+ }
413
+ read_data(rules) do |data|
414
+ if $settings.check_exists?(data[:check])
415
+ check = $settings[:checks][data[:check]]
416
+ subscribers = data[:subscribers] || check[:subscribers] || Array.new
417
+ payload = {
418
+ :name => data[:check],
419
+ :command => check[:command],
420
+ :issued => Time.now.to_i
421
+ }
422
+ $logger.info('publishing check request', {
423
+ :payload => payload,
424
+ :subscribers => subscribers
425
+ })
426
+ subscribers.uniq.each do |exchange_name|
427
+ $amq.fanout(exchange_name).publish(Oj.dump(payload))
418
428
  end
429
+ issued!
419
430
  else
420
- bad_request!
431
+ not_found!
421
432
  end
422
- rescue Oj::ParseError, TypeError
423
- bad_request!
424
433
  end
425
434
  end
426
435
 
@@ -476,25 +485,20 @@ module Sensu
476
485
  end
477
486
  end
478
487
 
479
- apost %r{/(?:event/)?resolve$} do
480
- begin
481
- post_body = Oj.load(request.body.read)
482
- client_name = post_body[:client]
483
- check_name = post_body[:check]
484
- if client_name.is_a?(String) && check_name.is_a?(String)
485
- $redis.hgetall('events:' + client_name) do |events|
486
- if events.include?(check_name)
487
- resolve_event(event_hash(events[check_name], client_name, check_name))
488
- issued!
489
- else
490
- not_found!
491
- end
488
+ apost '/resolve' do
489
+ rules = {
490
+ :client => {:type => String, :nil_ok => false},
491
+ :check => {:type => String, :nil_ok => false}
492
+ }
493
+ read_data(rules) do |data|
494
+ $redis.hgetall('events:' + data[:client]) do |events|
495
+ if events.include?(data[:check])
496
+ resolve_event(event_hash(events[data[:check]], data[:client], data[:check]))
497
+ issued!
498
+ else
499
+ not_found!
492
500
  end
493
- else
494
- bad_request!
495
501
  end
496
- rescue Oj::ParseError, TypeError
497
- bad_request!
498
502
  end
499
503
  end
500
504
 
@@ -504,12 +508,13 @@ module Sensu
504
508
  unless checks.empty?
505
509
  checks.each_with_index do |check_name, index|
506
510
  $redis.smembers('aggregates:' + check_name) do |aggregates|
511
+ aggregates.reverse!
507
512
  aggregates.map! do |issued|
508
513
  issued.to_i
509
514
  end
510
515
  item = {
511
516
  :check => check_name,
512
- :issued => aggregates.sort.reverse
517
+ :issued => aggregates
513
518
  }
514
519
  response << item
515
520
  if index == checks.size - 1
@@ -526,6 +531,7 @@ module Sensu
526
531
  aget %r{/aggregates/([\w\.-]+)$} do |check_name|
527
532
  $redis.smembers('aggregates:' + check_name) do |aggregates|
528
533
  unless aggregates.empty?
534
+ aggregates.reverse!
529
535
  aggregates.map! do |issued|
530
536
  issued.to_i
531
537
  end
@@ -536,8 +542,7 @@ module Sensu
536
542
  issued > timestamp
537
543
  end
538
544
  end
539
- aggregates = pagination(aggregates.sort.reverse)
540
- body Oj.dump(aggregates)
545
+ body Oj.dump(pagination(aggregates))
541
546
  else
542
547
  not_found!
543
548
  end
@@ -598,15 +603,12 @@ module Sensu
598
603
  end
599
604
 
600
605
  apost %r{/stash(?:es)?/(.*)} do |path|
601
- begin
602
- post_body = Oj.load(request.body.read)
603
- $redis.set('stash:' + path, Oj.dump(post_body)) do
606
+ read_data do |data|
607
+ $redis.set('stash:' + path, Oj.dump(data)) do
604
608
  $redis.sadd('stashes', path) do
605
609
  created!(Oj.dump(:path => path))
606
610
  end
607
611
  end
608
- rescue Oj::ParseError
609
- bad_request!
610
612
  end
611
613
  end
612
614
 
@@ -637,7 +639,6 @@ module Sensu
637
639
  aget '/stashes' do
638
640
  response = Array.new
639
641
  $redis.smembers('stashes') do |stashes|
640
- stashes = pagination(stashes)
641
642
  unless stashes.empty?
642
643
  stashes.each_with_index do |path, index|
643
644
  $redis.get('stash:' + path) do |stash_json|
@@ -647,9 +648,11 @@ module Sensu
647
648
  :content => Oj.load(stash_json)
648
649
  }
649
650
  response << item
651
+ else
652
+ $redis.srem('stashes', path)
650
653
  end
651
654
  if index == stashes.size - 1
652
- body Oj.dump(response)
655
+ body Oj.dump(pagination(response))
653
656
  end
654
657
  end
655
658
  end
@@ -660,21 +663,25 @@ module Sensu
660
663
  end
661
664
 
662
665
  apost '/stashes' do
663
- begin
664
- post_body = Oj.load(request.body.read)
665
- path = post_body[:path]
666
- content = post_body[:content]
667
- if path.is_a?(String) && content.is_a?(Hash)
668
- $redis.set('stash:' + path, Oj.dump(content)) do
669
- $redis.sadd('stashes', path) do
670
- created!(Oj.dump(:path => path))
666
+ rules = {
667
+ :path => {:type => String, :nil_ok => false},
668
+ :content => {:type => Hash, :nil_ok => false},
669
+ :expire => {:type => Integer, :nil_ok => true}
670
+ }
671
+ read_data(rules) do |data|
672
+ stash_key = 'stash:' + data[:path]
673
+ $redis.set(stash_key, Oj.dump(data[:content])) do
674
+ $redis.sadd('stashes', data[:path]) do
675
+ response = Oj.dump(:path => data[:path])
676
+ if data[:expire]
677
+ $redis.expire(stash_key, data[:expire]) do
678
+ created!(response)
679
+ end
680
+ else
681
+ created!(response)
671
682
  end
672
683
  end
673
- else
674
- bad_request!
675
684
  end
676
- rescue Oj::ParseError
677
- bad_request!
678
685
  end
679
686
  end
680
687
  end
@@ -1,6 +1,6 @@
1
1
  module Sensu
2
2
  unless defined?(Sensu::VERSION)
3
- VERSION = '0.11.3'
3
+ VERSION = '0.12.0'
4
4
 
5
5
  LOG_LEVELS = [:debug, :info, :warn, :error, :fatal]
6
6
 
data/sensu.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.add_dependency('oj', '2.0.9')
17
17
  s.add_dependency('eventmachine', '1.0.3')
18
18
  s.add_dependency('amq-protocol', '1.2.0')
19
+ s.add_dependency('amq-client', '1.0.2')
19
20
  s.add_dependency('amqp', '1.0.0')
20
21
  s.add_dependency('em-redis-unified', '0.4.2')
21
22
  s.add_dependency('thin', '1.5.0')
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 53
4
+ hash: 47
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 11
9
- - 3
10
- version: 0.11.3
8
+ - 12
9
+ - 0
10
+ version: 0.12.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sean Porter
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2013-10-23 00:00:00 -07:00
19
+ date: 2013-10-28 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -68,9 +68,25 @@ dependencies:
68
68
  type: :runtime
69
69
  version_requirements: *id003
70
70
  - !ruby/object:Gem::Dependency
71
- name: amqp
71
+ name: amq-client
72
72
  prerelease: false
73
73
  requirement: &id004 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - "="
77
+ - !ruby/object:Gem::Version
78
+ hash: 19
79
+ segments:
80
+ - 1
81
+ - 0
82
+ - 2
83
+ version: 1.0.2
84
+ type: :runtime
85
+ version_requirements: *id004
86
+ - !ruby/object:Gem::Dependency
87
+ name: amqp
88
+ prerelease: false
89
+ requirement: &id005 !ruby/object:Gem::Requirement
74
90
  none: false
75
91
  requirements:
76
92
  - - "="
@@ -82,11 +98,11 @@ dependencies:
82
98
  - 0
83
99
  version: 1.0.0
84
100
  type: :runtime
85
- version_requirements: *id004
101
+ version_requirements: *id005
86
102
  - !ruby/object:Gem::Dependency
87
103
  name: em-redis-unified
88
104
  prerelease: false
89
- requirement: &id005 !ruby/object:Gem::Requirement
105
+ requirement: &id006 !ruby/object:Gem::Requirement
90
106
  none: false
91
107
  requirements:
92
108
  - - "="
@@ -98,11 +114,11 @@ dependencies:
98
114
  - 2
99
115
  version: 0.4.2
100
116
  type: :runtime
101
- version_requirements: *id005
117
+ version_requirements: *id006
102
118
  - !ruby/object:Gem::Dependency
103
119
  name: thin
104
120
  prerelease: false
105
- requirement: &id006 !ruby/object:Gem::Requirement
121
+ requirement: &id007 !ruby/object:Gem::Requirement
106
122
  none: false
107
123
  requirements:
108
124
  - - "="
@@ -114,11 +130,11 @@ dependencies:
114
130
  - 0
115
131
  version: 1.5.0
116
132
  type: :runtime
117
- version_requirements: *id006
133
+ version_requirements: *id007
118
134
  - !ruby/object:Gem::Dependency
119
135
  name: sinatra
120
136
  prerelease: false
121
- requirement: &id007 !ruby/object:Gem::Requirement
137
+ requirement: &id008 !ruby/object:Gem::Requirement
122
138
  none: false
123
139
  requirements:
124
140
  - - "="
@@ -130,11 +146,11 @@ dependencies:
130
146
  - 5
131
147
  version: 1.3.5
132
148
  type: :runtime
133
- version_requirements: *id007
149
+ version_requirements: *id008
134
150
  - !ruby/object:Gem::Dependency
135
151
  name: async_sinatra
136
152
  prerelease: false
137
- requirement: &id008 !ruby/object:Gem::Requirement
153
+ requirement: &id009 !ruby/object:Gem::Requirement
138
154
  none: false
139
155
  requirements:
140
156
  - - "="
@@ -146,11 +162,11 @@ dependencies:
146
162
  - 0
147
163
  version: 1.0.0
148
164
  type: :runtime
149
- version_requirements: *id008
165
+ version_requirements: *id009
150
166
  - !ruby/object:Gem::Dependency
151
167
  name: rake
152
168
  prerelease: false
153
- requirement: &id009 !ruby/object:Gem::Requirement
169
+ requirement: &id010 !ruby/object:Gem::Requirement
154
170
  none: false
155
171
  requirements:
156
172
  - - ">="
@@ -160,11 +176,11 @@ dependencies:
160
176
  - 0
161
177
  version: "0"
162
178
  type: :development
163
- version_requirements: *id009
179
+ version_requirements: *id010
164
180
  - !ruby/object:Gem::Dependency
165
181
  name: rspec
166
182
  prerelease: false
167
- requirement: &id010 !ruby/object:Gem::Requirement
183
+ requirement: &id011 !ruby/object:Gem::Requirement
168
184
  none: false
169
185
  requirements:
170
186
  - - ">="
@@ -174,11 +190,11 @@ dependencies:
174
190
  - 0
175
191
  version: "0"
176
192
  type: :development
177
- version_requirements: *id010
193
+ version_requirements: *id011
178
194
  - !ruby/object:Gem::Dependency
179
195
  name: em-http-request
180
196
  prerelease: false
181
- requirement: &id011 !ruby/object:Gem::Requirement
197
+ requirement: &id012 !ruby/object:Gem::Requirement
182
198
  none: false
183
199
  requirements:
184
200
  - - ">="
@@ -188,7 +204,7 @@ dependencies:
188
204
  - 0
189
205
  version: "0"
190
206
  type: :development
191
- version_requirements: *id011
207
+ version_requirements: *id012
192
208
  description: A monitoring framework that aims to be simple, malleable, and scalable. Uses the publish/subscribe model.
193
209
  email:
194
210
  - portertech@gmail.com