sensu 0.11.3 → 0.12.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/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