sensu 0.8.16 → 0.8.18

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ gem("amqp", "0.7.4")
6
6
  gem("json")
7
7
  gem("hashie")
8
8
  gem("cabin", "0.1.7")
9
- gem("ruby-redis-portertech")
9
+ gem("ruby-redis")
10
10
  gem("rack", "~> 1.3.4")
11
11
  gem("async_sinatra")
12
12
  gem("thin")
data/Gemfile.lock CHANGED
@@ -40,7 +40,7 @@ GEM
40
40
  rspec-expectations (2.6.0)
41
41
  diff-lcs (~> 1.1.2)
42
42
  rspec-mocks (2.6.0)
43
- ruby-redis-portertech (0.0.3)
43
+ ruby-redis (0.0.2)
44
44
  eventmachine
45
45
  sinatra (1.3.1)
46
46
  rack (~> 1.3, >= 1.3.4)
@@ -68,5 +68,5 @@ DEPENDENCIES
68
68
  json
69
69
  rack (~> 1.3.4)
70
70
  rake
71
- ruby-redis-portertech
71
+ ruby-redis
72
72
  thin
data/README.org CHANGED
@@ -9,7 +9,7 @@
9
9
  * Documentation
10
10
  Find it [[https://github.com/sonian/sensu/wiki][HERE]].
11
11
  * Other Projects
12
- - [[https://github.com/sonian/sensu-plugins][Sensu Community Plugins]]
12
+ - [[https://github.com/sonian/sensu-plugin][Sensu Community Plugins]]
13
13
  - [[https://github.com/sonian/sensu-dashboard][Sensu Dashboard]]
14
14
  * License
15
15
  Sensu is released under the [[https://github.com/sonian/sensu/blob/master/MIT-LICENSE.txt][MIT license]].
@@ -34,3 +34,5 @@
34
34
  - [[http://twitter.com/amdprophet][Justin Kolberg]]
35
35
  - [[http://twitter.com/kartar][James Turnbull]]
36
36
  - [[http://twitter.com/joshpasqualetto][Josh Pasqualetto]]
37
+ - Steve Lum
38
+ - [[http://twitter.com/miller_joe][Joe Miller]]
data/lib/sensu/api.rb CHANGED
@@ -3,6 +3,8 @@ require File.join(File.dirname(__FILE__), 'config')
3
3
  require 'sinatra/async'
4
4
  require 'redis'
5
5
 
6
+ require File.join(File.dirname(__FILE__), 'helpers', 'redis')
7
+
6
8
  module Sensu
7
9
  class API < Sinatra::Base
8
10
  register Sinatra::Async
@@ -10,7 +12,7 @@ module Sensu
10
12
  def self.run(options={})
11
13
  EM.run do
12
14
  self.setup(options)
13
- self.run!(:port => @settings.api.port)
15
+ self.run!(:port => $settings.api.port)
14
16
 
15
17
  %w[INT TERM].each do |signal|
16
18
  Signal.trap(signal) do
@@ -22,12 +24,12 @@ module Sensu
22
24
 
23
25
  def self.setup(options={})
24
26
  config = Sensu::Config.new(options)
25
- @settings = config.settings
27
+ $settings = config.settings
26
28
  $logger = config.logger
27
29
  $logger.debug('[setup] -- connecting to redis')
28
- $redis = EM.connect(@settings.redis.host, @settings.redis.port, Redis::Client)
30
+ $redis = EM.connect($settings.redis.host, $settings.redis.port, Redis::Reconnect)
29
31
  $logger.debug('[setup] -- connecting to rabbitmq')
30
- connection = AMQP.connect(@settings.rabbitmq.to_hash.symbolize_keys)
32
+ connection = AMQP.connect($settings.rabbitmq.to_hash.symbolize_keys)
31
33
  $amq = MQ.new(connection)
32
34
  end
33
35
 
@@ -86,6 +88,9 @@ module Sensu
86
88
  $redis.srem('clients', client)
87
89
  $redis.del('events:' + client)
88
90
  $redis.del('client:' + client)
91
+ $settings.checks.each_key do |check_name|
92
+ $redis.del('history:' + client + ':' + check_name)
93
+ end
89
94
  end
90
95
  status 204
91
96
  body nil
@@ -229,16 +234,16 @@ module Sensu
229
234
 
230
235
  def self.test(options={})
231
236
  self.setup(options)
232
- $redis.set('client:' + @settings.client.name, @settings.client.to_json).callback do
233
- $redis.sadd('clients', @settings.client.name).callback do
234
- $redis.hset('events:' + @settings.client.name, 'test', {
237
+ $redis.set('client:' + $settings.client.name, $settings.client.to_json).callback do
238
+ $redis.sadd('clients', $settings.client.name).callback do
239
+ $redis.hset('events:' + $settings.client.name, 'test', {
235
240
  :status => 2,
236
241
  :output => 'CRITICAL',
237
242
  :flapping => false,
238
243
  :occurrences => 1
239
244
  }.to_json).callback do
240
245
  $redis.set('stash:test/test', '{"key": "value"}').callback do
241
- self.run!(:port => @settings.api.port)
246
+ self.run!(:port => $settings.api.port)
242
247
  end
243
248
  end
244
249
  end
data/lib/sensu/client.rb CHANGED
@@ -84,8 +84,12 @@ module Sensu
84
84
  end
85
85
  check.status = $?.exitstatus
86
86
  end
87
- publish = proc do |result|
88
- publish_result(check)
87
+ publish = proc do
88
+ unless check.status.nil?
89
+ publish_result(check)
90
+ else
91
+ @logger.warn('[execute] -- nil exit status code -- ' + check.name)
92
+ end
89
93
  @checks_in_progress.delete(check.name)
90
94
  end
91
95
  EM.defer(execute, publish)
@@ -182,8 +186,8 @@ module Sensu
182
186
  else
183
187
  @logger.warn('[socket] -- a check name, exit status, and output are required -- e.g. {name: x, status: 0, output: "y"}')
184
188
  end
185
- rescue JSON::ParserError
186
- @logger.warn('[socket] -- could not parse check result -- expecting JSON')
189
+ rescue JSON::ParserError => error
190
+ @logger.warn('[socket] -- check result must be valid JSON: ' + error)
187
191
  end
188
192
  close_connection
189
193
  end
data/lib/sensu/config.rb CHANGED
@@ -1,9 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers', 'ruby')
2
+
1
3
  require 'rubygems' if RUBY_VERSION < '1.9.0'
2
4
  require 'bundler'
3
5
  require 'bundler/setup'
4
6
 
5
- require File.join(File.dirname(__FILE__), 'helpers')
6
-
7
7
  gem 'eventmachine', '~> 1.0.0.beta.4'
8
8
 
9
9
  require 'optparse'
@@ -34,12 +34,25 @@ module Sensu
34
34
  if File.readable?(config_file)
35
35
  begin
36
36
  @settings = Hashie::Mash.new(JSON.parse(File.open(config_file, 'r').read))
37
- rescue JSON::ParserError => e
38
- invalid_config('configuration file must be valid JSON: ' + e)
37
+ rescue JSON::ParserError => error
38
+ invalid_config('configuration file (' + config_file + ') must be valid JSON: ' + error)
39
39
  end
40
40
  else
41
41
  invalid_config('configuration file does not exist or is not readable: ' + config_file)
42
42
  end
43
+ config_dir = options[:config_dir] || '/etc/sensu/conf.d'
44
+ if File.exists?(config_dir)
45
+ Dir[config_dir + '/**/*.json'].each do |snippet_file|
46
+ begin
47
+ snippet_hash = JSON.parse(File.open(snippet_file, 'r').read)
48
+ rescue JSON::ParserError => error
49
+ invalid_config('configuration snippet file (' + snippet_file + ') must be valid JSON: ' + error)
50
+ end
51
+ merged_settings = @settings.to_hash.deep_merge(snippet_hash)
52
+ @logger.warn('[settings] configuration snippet (' + snippet_file + ') applied changes: ' + @settings.deep_diff(merged_settings).to_json)
53
+ @settings = Hashie::Mash.new(merged_settings)
54
+ end
55
+ end
43
56
  validate_config(options['type'])
44
57
  end
45
58
 
@@ -122,6 +135,9 @@ module Sensu
122
135
  opts.on('-c', '--config FILE', 'Sensu JSON config FILE (default: /etc/sensu/config.json)') do |file|
123
136
  options[:config_file] = file
124
137
  end
138
+ opts.on('-d', '--config_dir DIR', 'Directory for supplemental Sensu JSON config files (default: /etc/sensu/conf.d/)') do |dir|
139
+ options[:config_dir] = dir
140
+ end
125
141
  opts.on('-l', '--log FILE', 'Sensu log FILE (default: /tmp/sensu.log)') do |file|
126
142
  options[:log_file] = file
127
143
  end
@@ -0,0 +1,25 @@
1
+ module Redis
2
+ class Reconnect < Redis::Client
3
+ def connection_completed
4
+ @connected = true
5
+ @port, @host = Socket.unpack_sockaddr_in(get_peername)
6
+ end
7
+
8
+ def close
9
+ @closing_connection = true
10
+ close_connection_after_writing
11
+ end
12
+
13
+ def unbind
14
+ unless !@connected || @closing_connection
15
+ EM.add_timer(1) do
16
+ reconnect(@host, @port)
17
+ end
18
+ else
19
+ until @queue.empty?
20
+ @queue.shift.fail RuntimeError.new 'connection closed'
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ class Hash
2
+ def symbolize_keys(item=self)
3
+ case item
4
+ when Array
5
+ item.map do |i|
6
+ symbolize_keys(i)
7
+ end
8
+ when Hash
9
+ Hash[
10
+ item.map do |key, value|
11
+ new_key = key.is_a?(String) ? key.to_sym : key
12
+ new_value = symbolize_keys(value)
13
+ [new_key, new_value]
14
+ end
15
+ ]
16
+ else
17
+ item
18
+ end
19
+ end
20
+
21
+ def deep_diff(hash)
22
+ (self.keys | hash.keys).inject(Hash.new) do |diff, key|
23
+ unless self[key] == hash[key]
24
+ if self[key].is_a?(Hash) && hash[key].is_a?(Hash)
25
+ diff[key] = self[key].deep_diff(hash[key])
26
+ else
27
+ diff[key] = [self[key], hash[key]]
28
+ end
29
+ end
30
+ diff
31
+ end
32
+ end
33
+
34
+ def deep_merge(hash)
35
+ merger = proc do |key, value1, value2|
36
+ value1.is_a?(Hash) && value2.is_a?(Hash) ? value1.merge(value2, &merger) : value2
37
+ end
38
+ self.merge(hash, &merger)
39
+ end
40
+ end
41
+
42
+ class String
43
+ def self.unique(chars=32)
44
+ rand(36**chars).to_s(36)
45
+ end
46
+ end
data/lib/sensu/server.rb CHANGED
@@ -2,6 +2,8 @@ require File.join(File.dirname(__FILE__), 'config')
2
2
 
3
3
  require 'redis'
4
4
 
5
+ require File.join(File.dirname(__FILE__), 'helpers', 'redis')
6
+
5
7
  module Sensu
6
8
  class Server
7
9
  attr_accessor :redis, :is_worker
@@ -44,7 +46,7 @@ module Sensu
44
46
 
45
47
  def setup_redis
46
48
  @logger.debug('[redis] -- connecting to redis')
47
- @redis = EM.connect(@settings.redis.host, @settings.redis.port, Redis::Client)
49
+ @redis = EM.connect(@settings.redis.host, @settings.redis.port, Redis::Reconnect)
48
50
  end
49
51
 
50
52
  def setup_amqp
@@ -85,10 +87,14 @@ module Sensu
85
87
  handle = proc do
86
88
  output = ''
87
89
  Bundler.with_clean_env do
88
- IO.popen(@settings.handlers[handler] + ' 2>&1', 'r+') do |io|
89
- io.write(event.to_json)
90
- io.close_write
91
- output = io.read
90
+ begin
91
+ IO.popen(@settings.handlers[handler] + ' 2>&1', 'r+') do |io|
92
+ io.write(event.to_json)
93
+ io.close_write
94
+ output = io.read
95
+ end
96
+ rescue Errno::EPIPE => error
97
+ output = handler + ' -- broken pipe: ' + error
92
98
  end
93
99
  end
94
100
  output
data/lib/sensu.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sensu
2
- VERSION = "0.8.16"
2
+ VERSION = "0.8.18"
3
3
  end
data/sensu.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.add_dependency("json")
19
19
  s.add_dependency("hashie")
20
20
  s.add_dependency("cabin", "0.1.7")
21
- s.add_dependency("ruby-redis-portertech")
21
+ s.add_dependency("ruby-redis")
22
22
  s.add_dependency("rack", "~> 1.3.4")
23
23
  s.add_dependency("async_sinatra")
24
24
  s.add_dependency("thin")
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: 31
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 8
9
- - 16
10
- version: 0.8.16
9
+ - 18
10
+ version: 0.8.18
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: 2011-12-02 00:00:00 -08:00
19
+ date: 2011-12-13 00:00:00 -08:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -112,7 +112,7 @@ dependencies:
112
112
  type: :runtime
113
113
  version_requirements: *id006
114
114
  - !ruby/object:Gem::Dependency
115
- name: ruby-redis-portertech
115
+ name: ruby-redis
116
116
  prerelease: false
117
117
  requirement: &id007 !ruby/object:Gem::Requirement
118
118
  none: false
@@ -238,7 +238,8 @@ files:
238
238
  - lib/sensu/api.rb
239
239
  - lib/sensu/client.rb
240
240
  - lib/sensu/config.rb
241
- - lib/sensu/helpers.rb
241
+ - lib/sensu/helpers/redis.rb
242
+ - lib/sensu/helpers/ruby.rb
242
243
  - lib/sensu/server.rb
243
244
  - sensu.gemspec
244
245
  has_rdoc: true
data/lib/sensu/helpers.rb DELETED
@@ -1,26 +0,0 @@
1
- class Hash
2
- def symbolize_keys(item=self)
3
- case item
4
- when Array
5
- item.map do |i|
6
- symbolize_keys(i)
7
- end
8
- when Hash
9
- Hash[
10
- item.map do |key, value|
11
- new_key = key.is_a?(String) ? key.to_sym : key
12
- new_value = symbolize_keys(value)
13
- [new_key, new_value]
14
- end
15
- ]
16
- else
17
- item
18
- end
19
- end
20
- end
21
-
22
- class String
23
- def self.unique(chars=32)
24
- rand(36**chars).to_s(36)
25
- end
26
- end