sensu-plugin 0.1.3 → 0.1.4.beta

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-handler.rb CHANGED
@@ -2,6 +2,14 @@ require 'net/http'
2
2
  require 'json'
3
3
 
4
4
  module Sensu
5
+
6
+ NET_HTTP_REQ_CLASS = {
7
+ 'GET' => Net::HTTP::Get,
8
+ 'POST' => Net::HTTP::Post,
9
+ 'DELETE' => Net::HTTP::Delete,
10
+ 'PUT' => Net::HTTP::Put,
11
+ }
12
+
5
13
  class Handler
6
14
 
7
15
  # Implementing classes should override this.
@@ -15,8 +23,9 @@ module Sensu
15
23
 
16
24
  def filter
17
25
  filter_disabled
18
- filter_repeated unless @event['action'] == 'resolve'
26
+ filter_repeated
19
27
  filter_silenced
28
+ filter_dependencies
20
29
  end
21
30
 
22
31
  # This works just like Plugin::CLI's autorun.
@@ -30,27 +39,30 @@ module Sensu
30
39
  end
31
40
  end
32
41
 
33
- # Unfortunately, we need to reimplement config loading. I'm not sure there's
34
- # a good way to allow overriding these paths.
35
-
36
- CONFIGS = ['/etc/sensu/config.json'] + Dir['/etc/sensu/conf.d/*.json']
42
+ def config_files
43
+ if ENV['SENSU_CONFIG_FILES']
44
+ ENV['SENSU_CONFIG_FILES'].split(':')
45
+ else
46
+ ['/etc/sensu/config.json'] + Dir['/etc/sensu/conf.d/*.json']
47
+ end
48
+ end
37
49
 
38
50
  def load_config(filename)
39
51
  JSON.parse(File.open(filename, 'r').read) rescue Hash.new
40
52
  end
41
53
 
42
54
  def settings
43
- @settings ||= CONFIGS.map {|f| load_config(f) }.reduce {|a, b| a.deep_merge(b) }
55
+ @settings ||= config_files.map {|f| load_config(f) }.reduce {|a, b| a.deep_merge(b) }
44
56
  end
45
57
 
46
58
  def read_event(file)
47
59
  begin
48
60
  @event = ::JSON.parse(file.read)
49
61
  @event['occurrences'] ||= 1
50
- @event['check'] ||= Hash.new
51
- @event['client'] ||= Hash.new
52
- rescue => e
53
- puts 'Error reading event: ' + e.message
62
+ @event['check'] ||= Hash.new
63
+ @event['client'] ||= Hash.new
64
+ rescue => error
65
+ puts 'error reading event: ' + error.message
54
66
  exit 0
55
67
  end
56
68
  end
@@ -62,7 +74,7 @@ module Sensu
62
74
  handler.handle
63
75
  end
64
76
 
65
- # Helpers and filters
77
+ # Helpers and filters.
66
78
 
67
79
  def bail(msg)
68
80
  puts msg + ': ' + @event['client']['name'] + '/' + @event['check']['name']
@@ -71,15 +83,9 @@ module Sensu
71
83
 
72
84
  def api_request(method, path, &blk)
73
85
  http = Net::HTTP.new(settings['api']['host'], settings['api']['port'])
74
- req = case method.to_s.upcase
75
- when 'GET'
76
- Net::HTTP::Get.new(path)
77
- when 'POST'
78
- Net::HTTP::Post.new(path)
79
- when 'DELETE'
80
- Net::HTTP::Delete.new(path)
81
- when 'PUT'
82
- Net::HTTP::Put.new(path)
86
+ req = NET_HTTP_REQ_CLASS[method.to_s.upcase].new(path)
87
+ if settings['api']['user'] && settings['api']['password']
88
+ req.basic_auth(settings['api']['user'], settings['api']['password'])
83
89
  end
84
90
  yield(req) if block_given?
85
91
  http.request(req)
@@ -93,50 +99,79 @@ module Sensu
93
99
 
94
100
  def filter_repeated
95
101
  occurrences = @event['check']['occurrences'] || 1
96
- interval = @event['check']['interval'] || 30
97
- refresh = @event['check']['refresh'] || 1800
102
+ interval = @event['check']['interval'] || 30
103
+ refresh = @event['check']['refresh'] || 1800
98
104
  if @event['occurrences'] < occurrences
99
105
  bail 'not enough occurrences'
100
106
  end
101
- if @event['occurrences'] > occurrences
102
- n = refresh.fdiv(interval).to_i
103
- bail 'only repeating alert every ' + n.to_s + ' occurrences' unless @event['occurrences'] % n == 0
107
+ if @event['occurrences'] > occurrences && @event['action'] == 'create'
108
+ number = refresh.fdiv(interval).to_i
109
+ unless @event['occurrences'] % number == 0
110
+ bail 'only handling every ' + number.to_s + ' occurrences'
111
+ end
104
112
  end
105
113
  end
106
114
 
115
+ def stash_exists?(path)
116
+ api_request(:GET, '/stash' + path).code == '200'
117
+ end
118
+
107
119
  def filter_silenced
108
- begin
109
- timeout(3) do
110
- if stash_exists?('/silence/' + @event['client']['name'])
111
- bail 'client alerts silenced'
112
- end
113
- if stash_exists?('/silence/' + @event['client']['name'] + '/' + @event['check']['name'])
114
- bail 'check alerts silenced'
120
+ stashes = {
121
+ 'client' => '/silence/' + @event['client']['name'],
122
+ 'check' => '/silence/' + @event['client']['name'] + '/' + @event['check']['name']
123
+ }
124
+ stashes.each do |scope, path|
125
+ begin
126
+ timeout(2) do
127
+ if stash_exists?(path)
128
+ bail scope + ' alerts silenced'
129
+ end
115
130
  end
131
+ rescue Timeout::Error
132
+ puts 'timed out while attempting to query the sensu api for a stash'
116
133
  end
117
- rescue Timeout::Error
118
- puts 'Timed out while attempting to query the Sensu API for stashes'
119
134
  end
120
135
  end
121
136
 
122
- def stash_exists?(path)
123
- api_request(:GET, '/stash' + path).code == '200'
137
+ def event_exists?(client, check)
138
+ api_request(:GET, '/event/' + client + '/' + check).code == '200'
139
+ end
140
+
141
+ def filter_dependencies
142
+ if @event['check'].has_key?('dependencies')
143
+ if @event['check']['dependencies'].is_a?(Array)
144
+ @event['check']['dependencies'].each do |check|
145
+ begin
146
+ timeout(2) do
147
+ if event_exists?(@event['client']['name'], check)
148
+ bail 'check dependency event exists'
149
+ end
150
+ end
151
+ rescue Timeout::Error
152
+ puts 'timed out while attempting to query the sensu api for an event'
153
+ end
154
+ end
155
+ end
156
+ end
124
157
  end
125
158
 
126
159
  end
160
+
127
161
  end
128
162
 
129
- # Copied from Sensu (0.9.3)
163
+ # Monkey Patching.
130
164
 
131
165
  class Array
132
166
  def deep_merge(other_array, &merger)
133
167
  concat(other_array).uniq
134
168
  end
135
169
  end
170
+
136
171
  class Hash
137
172
  def deep_merge(other_hash, &merger)
138
- merger ||= proc do |k, oldval, newval|
139
- oldval.deep_merge(newval, &merger) rescue newval
173
+ merger ||= proc do |key, old_value, new_value|
174
+ old_value.deep_merge(new_value, &merger) rescue new_value
140
175
  end
141
176
  merge(other_hash, &merger)
142
177
  end
data/lib/sensu-plugin.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Sensu
2
2
  module Plugin
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4.beta"
4
4
  EXIT_CODES = {
5
5
  'OK' => 0,
6
6
  'WARNING' => 1,
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ require 'json'
4
+
5
+ class TestFilterExternal < MiniTest::Unit::TestCase
6
+ include SensuPluginTestHelper
7
+
8
+ def setup
9
+ set_script 'external/handle-filter'
10
+ end
11
+
12
+ def test_resolve_not_enough_occurrences
13
+ event = {
14
+ 'client' => { 'name' => 'test' },
15
+ 'check' => { 'name' => 'test', 'occurrences' => 2},
16
+ 'occurrences' => 1
17
+ }
18
+ output = run_script_with_input(JSON.generate(event))
19
+ assert_equal(0, $?.exitstatus)
20
+ assert_match(/^not enough occurrences/, output)
21
+ end
22
+
23
+ def test_resolve_enough_occurrences
24
+ event = {
25
+ 'client' => { 'name' => 'test' },
26
+ 'check' => { 'name' => 'test', 'occurrences' => 2},
27
+ 'occurrences' => 3
28
+ }
29
+ output = run_script_with_input(JSON.generate(event))
30
+ assert_equal(0, $?.exitstatus)
31
+ assert_match(/^Event:/, output)
32
+ end
33
+
34
+ def test_resolve_enough_occurrences_exactly
35
+ event = {
36
+ 'client' => { 'name' => 'test' },
37
+ 'check' => { 'name' => 'test', 'occurrences' => 2},
38
+ 'occurrences' => 2
39
+ }
40
+ output = run_script_with_input(JSON.generate(event))
41
+ assert_equal(0, $?.exitstatus)
42
+ assert_match(/^Event:/, output)
43
+ end
44
+
45
+ def test_dependency_event_exists
46
+ event = {
47
+ 'client' => { 'name' => 'test' },
48
+ 'check' => { 'name' => 'test', 'dependencies' => ['foo', 'bar'] },
49
+ 'occurrences' => 1
50
+ }
51
+ output = run_script_with_input(JSON.generate(event))
52
+ assert_equal(0, $?.exitstatus)
53
+ assert_match(/dependency event exists/, output)
54
+ end
55
+ end
metadata CHANGED
@@ -1,82 +1,115 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: sensu-plugin
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.3
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31098201
5
+ prerelease: true
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 4
10
+ - beta
11
+ version: 0.1.4.beta
6
12
  platform: ruby
7
- authors:
13
+ authors:
8
14
  - Decklin Foster
15
+ - Sean Porter
9
16
  autorequire:
10
17
  bindir: bin
11
18
  cert_chain: []
12
- date: 2012-02-10 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
19
+
20
+ date: 2012-07-09 00:00:00 -07:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
15
24
  name: json
16
- requirement: &70113831789080 !ruby/object:Gem::Requirement
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
17
27
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
22
35
  type: :runtime
23
- prerelease: false
24
- version_requirements: *70113831789080
25
- - !ruby/object:Gem::Dependency
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
26
38
  name: mixlib-cli
27
- requirement: &70113831788560 !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
28
41
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 19
46
+ segments:
47
+ - 1
48
+ - 1
49
+ - 0
32
50
  version: 1.1.0
33
51
  type: :runtime
34
- prerelease: false
35
- version_requirements: *70113831788560
52
+ version_requirements: *id002
36
53
  description: Plugins and helper libraries for Sensu, a monitoring framework
37
- email:
54
+ email:
38
55
  - decklin@red-bean.com
56
+ - portertech@gmail.com
39
57
  executables: []
58
+
40
59
  extensions: []
60
+
41
61
  extra_rdoc_files: []
42
- files:
62
+
63
+ files:
43
64
  - lib/sensu-handler.rb
44
65
  - lib/sensu-plugin/check/cli.rb
45
66
  - lib/sensu-plugin/cli.rb
46
67
  - lib/sensu-plugin/metric/cli.rb
47
- - lib/sensu-plugin/util/procs.rb
48
68
  - lib/sensu-plugin.rb
49
69
  - test/external_check_test.rb
50
70
  - test/external_handler_test.rb
51
71
  - test/external_metric_test.rb
72
+ - test/handle_filter_test.rb
52
73
  - test/helper.rb
74
+ has_rdoc: true
53
75
  homepage: https://github.com/sonian/sensu-plugin
54
- licenses:
76
+ licenses:
55
77
  - MIT
56
78
  post_install_message:
57
79
  rdoc_options: []
58
- require_paths:
80
+
81
+ require_paths:
59
82
  - lib
60
- required_ruby_version: !ruby/object:Gem::Requirement
83
+ required_ruby_version: !ruby/object:Gem::Requirement
61
84
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
66
- required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
93
  none: false
68
- requirements:
69
- - - ! '>='
70
- - !ruby/object:Gem::Version
71
- version: '0'
94
+ requirements:
95
+ - - ">"
96
+ - !ruby/object:Gem::Version
97
+ hash: 25
98
+ segments:
99
+ - 1
100
+ - 3
101
+ - 1
102
+ version: 1.3.1
72
103
  requirements: []
104
+
73
105
  rubyforge_project:
74
- rubygems_version: 1.8.11
106
+ rubygems_version: 1.3.7
75
107
  signing_key:
76
108
  specification_version: 3
77
109
  summary: Sensu Plugins
78
- test_files:
110
+ test_files:
79
111
  - test/external_check_test.rb
80
112
  - test/external_handler_test.rb
81
113
  - test/external_metric_test.rb
114
+ - test/handle_filter_test.rb
82
115
  - test/helper.rb
@@ -1,14 +0,0 @@
1
- require 'sensu-plugin/check/cli'
2
-
3
- module Sensu
4
- module Plugin
5
- module Util
6
- module Procs
7
-
8
- class << self
9
- end
10
-
11
- end
12
- end
13
- end
14
- end