nagios-check 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +7 -0
- data/examples/check_file_age.rb +39 -0
- data/examples/check_redis.rb +71 -0
- data/lib/nagios.rb +32 -0
- data/lib/nagios/check/base.rb +95 -0
- data/lib/nagios/check/range.rb +50 -0
- data/lib/nagios/check/threshold.rb +40 -0
- data/lib/nagios/check/version.rb +5 -0
- data/nagios-check.gemspec +23 -0
- data/spec/lib/nagios/check/base_spec.rb +132 -0
- data/spec/lib/nagios/check/range_spec.rb +110 -0
- data/spec/lib/nagios/check/threshold_spec.rb +75 -0
- data/spec/spec_helper.rb +29 -0
- metadata +127 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Max Horbul
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Nagios::Check
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'nagios-check'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install nagios-check
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
30
|
+
|
31
|
+
<a href="http://twitter.com/home/?status=Thanks @mhorbul for making nagios-check: https://github.com/mhorbul/nagios-check"><img src="https://s3.amazonaws.com/github-thank-you-button/thank-you-button.png" alt="Say Thanks" /></a> :)
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env -- ruby
|
2
|
+
#
|
3
|
+
# Usage: check_file_age --file /path/to/file -w 3600 -c 4800
|
4
|
+
#
|
5
|
+
$LOAD_PATH.push './lib'
|
6
|
+
|
7
|
+
require 'nagios'
|
8
|
+
|
9
|
+
module Nagios
|
10
|
+
module Check
|
11
|
+
class FileAge < Base
|
12
|
+
|
13
|
+
def parse(args)
|
14
|
+
option_parser(args) do |opt|
|
15
|
+
opt.on("-f", "--file FILE_PATH", "Path to file") do |value|
|
16
|
+
@options[:file] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def check
|
22
|
+
age = file_age
|
23
|
+
code = check_threshold(age)
|
24
|
+
message = "File is too old."
|
25
|
+
message = "File has been updated #{age} sec. ago" unless code == Nagios::OK
|
26
|
+
nagios_exit(code, message)
|
27
|
+
end
|
28
|
+
|
29
|
+
def file_age
|
30
|
+
nagios_exit(:critical, "File does not exit") unless File.exist?(options[:file].to_s)
|
31
|
+
Time.now - File.mtime(options[:file])
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
nagios = Nagios::Check::FileAge.new
|
39
|
+
nagios.run(ARGV)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env -- ruby
|
2
|
+
#
|
3
|
+
# Usage: check_redis --host domain.com -p 9379 -w 80 -c 90
|
4
|
+
#
|
5
|
+
$LOAD_PATH.push './lib'
|
6
|
+
|
7
|
+
require 'redis'
|
8
|
+
require 'nagios'
|
9
|
+
|
10
|
+
module Nagios
|
11
|
+
module Check
|
12
|
+
class Redis < Base
|
13
|
+
|
14
|
+
def default_options
|
15
|
+
{
|
16
|
+
:host => "127.0.0.1",
|
17
|
+
:port => 6379
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(args)
|
22
|
+
option_parser(args) do |opt|
|
23
|
+
opt.on("-p", "--port PORT", "Redis server port (default: 6379)") do |value|
|
24
|
+
@options[:port] = Integer(value)
|
25
|
+
end
|
26
|
+
opt.on("-H", "--host HOST_OR_IP", "Redis server host or ip address (default: 127.0.0.1)") do |value|
|
27
|
+
@options[:host] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def check
|
33
|
+
begin
|
34
|
+
data = redis.info
|
35
|
+
rescue => e
|
36
|
+
nagios_exit(:critical, "Can't fetch info from redis server.: #{e}")
|
37
|
+
end
|
38
|
+
|
39
|
+
message = "Everything is OK"
|
40
|
+
code = Nagios::OK
|
41
|
+
|
42
|
+
check_slave(data, code, message) if data['role'] == 'slave'
|
43
|
+
|
44
|
+
nagios_exit(code, message)
|
45
|
+
end
|
46
|
+
|
47
|
+
def check_slave(data, code, message)
|
48
|
+
code = check_threshold(data['master_last_io_seconds_ago'])
|
49
|
+
message = "redis replication is late #{data['master_last_io_seconds_ago']} s" unless code == Nagios::OK
|
50
|
+
|
51
|
+
if Integer(data['master_sync_in_progress']) != 0
|
52
|
+
message = "redis replication sync is in progress"
|
53
|
+
code = Nagios::CRITICAL
|
54
|
+
end
|
55
|
+
nagios_exit(code, message)
|
56
|
+
end
|
57
|
+
|
58
|
+
def redis
|
59
|
+
begin
|
60
|
+
@redis ||= ::Redis.new(:host => options[:host], :port => options[:port])
|
61
|
+
rescue => e
|
62
|
+
nagios_exit(:critical, "Can't connection to #{options[:host]}:#{options[:port]}: #{e}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
nagios = Nagios::Check::Redis.new
|
71
|
+
nagios.run(ARGV)
|
data/lib/nagios.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module Nagios
|
5
|
+
|
6
|
+
OK = 0
|
7
|
+
WARNING = 1
|
8
|
+
CRITICAL = 2
|
9
|
+
UNKNOWN = 3
|
10
|
+
|
11
|
+
EXIT_CODE = {
|
12
|
+
:ok => OK,
|
13
|
+
:warning => WARNING,
|
14
|
+
:critical => CRITICAL,
|
15
|
+
:unknown => UNKNOWN
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.logger=(logger)
|
19
|
+
@logger = logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.logger
|
23
|
+
@logger || Logger.new(STDOUT)
|
24
|
+
end
|
25
|
+
|
26
|
+
module Check
|
27
|
+
autoload :Range, "nagios/check/range"
|
28
|
+
autoload :Threshold, "nagios/check/threshold"
|
29
|
+
autoload :Base, "nagios/check/base"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Nagios
|
2
|
+
module Check
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_reader :thresholds, :options
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def shortname(value = nil)
|
9
|
+
@shortname = value if value
|
10
|
+
@shortname
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@thresholds = {}
|
16
|
+
@options = {}.merge!(default_options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(args = [])
|
20
|
+
parse(args)
|
21
|
+
begin
|
22
|
+
check
|
23
|
+
rescue => e
|
24
|
+
nagios_exit(:unknown, "#{e.class}: #{e.to_s}\n#{e.backtrace.join("\n")}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def perfoutput
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_options
|
32
|
+
{}
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse(args)
|
36
|
+
option_parser(args)
|
37
|
+
end
|
38
|
+
|
39
|
+
def nagios_exit(code, message)
|
40
|
+
exit_code = code.is_a?(Symbol) ? Nagios::EXIT_CODE[code] : code
|
41
|
+
reversed_exit_codes = Nagios::EXIT_CODE.to_a.reduce([]) { |r,v| r << v.reverse }
|
42
|
+
exit_status = Hash[reversed_exit_codes][exit_code]
|
43
|
+
unless exit_status
|
44
|
+
puts "UNKNOWN - exit code '#{code}' is not found."
|
45
|
+
exit UNKNOWN
|
46
|
+
end
|
47
|
+
output = exit_status.to_s.upcase
|
48
|
+
output << " - #{message}"
|
49
|
+
output = self.class.shortname.nil? ? output : "#{self.clas.shortname.shortname} #{output}"
|
50
|
+
output << " | #{perfoutput}" if perfoutput
|
51
|
+
puts output
|
52
|
+
exit exit_code
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_threshold(options)
|
56
|
+
if options.is_a?(Hash)
|
57
|
+
name, value = options.to_a.flatten
|
58
|
+
else
|
59
|
+
name = :default
|
60
|
+
value = options
|
61
|
+
end
|
62
|
+
raise Exception, "threshold '#{name}' does not exit" unless self.thresholds[name]
|
63
|
+
self.thresholds[name].get_status(value)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_threshold(name, values = {})
|
67
|
+
@thresholds[name] ||= Threshold.new
|
68
|
+
@thresholds[name].send(:warn, values[:warn]) if values[:warn]
|
69
|
+
@thresholds[name].send(:crit, values[:crit]) if values[:crit]
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def option_parser(args)
|
74
|
+
OptionParser.new do |opt|
|
75
|
+
opt.on_tail("-h", "--help", "Show this message") do
|
76
|
+
puts opt
|
77
|
+
exit
|
78
|
+
end
|
79
|
+
opt.on("-w", "--warning WARNING", "WARNING Threshold") do |value|
|
80
|
+
add_threshold(:default, :warn => value)
|
81
|
+
end
|
82
|
+
opt.on("-c", "--critical CRITICAL", "CRITICAL Threshold") do |value|
|
83
|
+
add_threshold(:default, :crit => value)
|
84
|
+
end
|
85
|
+
yield opt if block_given?
|
86
|
+
end.parse!(args)
|
87
|
+
end
|
88
|
+
|
89
|
+
def check
|
90
|
+
nagios_exit :unknown, "#{self.class.name}#check method should be implemented in the child class"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Nagios
|
2
|
+
module Check
|
3
|
+
class Range
|
4
|
+
|
5
|
+
attr_reader :start_value, :end_value, :start_infinity, :end_infinity, :alert_on
|
6
|
+
|
7
|
+
def initialize(range)
|
8
|
+
@start_value = 0
|
9
|
+
@end_value = 0
|
10
|
+
@start_infinity = false
|
11
|
+
@end_infinity = false
|
12
|
+
@alert_on = :inside
|
13
|
+
parse_range_string(range.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_range(value)
|
17
|
+
value = value.to_f
|
18
|
+
result =
|
19
|
+
if !start_infinity && end_infinity
|
20
|
+
start_value <= value
|
21
|
+
elsif start_infinity && !end_infinity
|
22
|
+
value <= end_value
|
23
|
+
else
|
24
|
+
start_value <= value && value <= end_value
|
25
|
+
end
|
26
|
+
alert_on == :outside ? result : !result
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def parse_range_string(range)
|
31
|
+
@start_infinity = true if range.gsub!(/^~/, '')
|
32
|
+
@alert_on = :outside if range.gsub!(/^@/, '')
|
33
|
+
regexp = '([+\-]?[\d+\.]+)'
|
34
|
+
case range
|
35
|
+
when /^:?(#{regexp})$/ # :10 or 10
|
36
|
+
@end_value = Float($1)
|
37
|
+
when /^#{regexp}:#{regexp}$/ # 10:20
|
38
|
+
@start_value = Float($1)
|
39
|
+
@end_value = Float($2)
|
40
|
+
when /^#{regexp}:$/ # 10:
|
41
|
+
@start_value = Float($1)
|
42
|
+
@end_infinity = true
|
43
|
+
else
|
44
|
+
raise TypeError, "Unknown threshold format. Please check the documentation http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Nagios
|
2
|
+
module Check
|
3
|
+
class Threshold
|
4
|
+
|
5
|
+
def initialize(thresholds = {})
|
6
|
+
set(:warn, thresholds[:warn])
|
7
|
+
set(:crit, thresholds[:crit])
|
8
|
+
end
|
9
|
+
|
10
|
+
def warn(value = nil)
|
11
|
+
set(:warn, value) if value
|
12
|
+
@warn
|
13
|
+
end
|
14
|
+
|
15
|
+
def crit(value = nil)
|
16
|
+
set(:crit, value) if value
|
17
|
+
@crit
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_status(value)
|
21
|
+
return Nagios::CRITICAL if self.crit && self.crit.check_range(value)
|
22
|
+
return Nagios::WARNING if self.warn && self.warn.check_range(value)
|
23
|
+
return Nagios::OK
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def set(attr, value)
|
28
|
+
return unless [:warn, :crit].include?(attr)
|
29
|
+
return unless value
|
30
|
+
begin
|
31
|
+
range = Range.new(value)
|
32
|
+
instance_variable_set("@#{attr}".to_sym, range)
|
33
|
+
rescue => e
|
34
|
+
Nagios.logger.warn("Can't setup a threshold value to: #{value.inspect}. #{e}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'nagios/check/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "nagios-check"
|
7
|
+
spec.version = Nagios::Check::VERSION
|
8
|
+
spec.authors = ["Max Horbul"]
|
9
|
+
spec.email = ["max@gorbul.net"]
|
10
|
+
spec.description = %q{Nagios check written in Ruby}
|
11
|
+
spec.summary = %q{This is a base for Nagios checks development in Ruby}
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency "rspec"
|
23
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagios::Check::Base do
|
4
|
+
|
5
|
+
class TestPlugin < Nagios::Check::Base
|
6
|
+
|
7
|
+
def parse(args)
|
8
|
+
option_parser(args) do |opt|
|
9
|
+
opt.on("-H", "--host HOST", "Hostname or IP address") do |value|
|
10
|
+
@options[:host] = value
|
11
|
+
end
|
12
|
+
opt.on("-P", "--port PORT", "TCP Port of the service") do |value|
|
13
|
+
@options[:port] = value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:plugin) { Nagios::Check::Base.new }
|
21
|
+
let(:threshold) { double }
|
22
|
+
before do
|
23
|
+
Nagios::Check::Threshold.stub(:new).and_return(threshold)
|
24
|
+
threshold.stub(:crit)
|
25
|
+
threshold.stub(:warn)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should check default threshold when name is not provided" do
|
29
|
+
plugin.add_threshold(:default, :warn => "10", :crit => "20")
|
30
|
+
plugin.thresholds[:default].should_receive(:get_status).with(25)
|
31
|
+
plugin.check_threshold(25)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should check threshold by name" do
|
35
|
+
plugin.add_threshold(:custom, :warn => "10", :crit => "20")
|
36
|
+
plugin.thresholds[:custom].should_receive(:get_status).with(25)
|
37
|
+
plugin.check_threshold(:custom => 25)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should raise error when check unknown threshold" do
|
41
|
+
lambda { plugin.check_threshold(:unknown => 25) }.should raise_exception(Exception) { |e| e.to_s.should eq("threshold 'unknown' does not exit") }
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should add threshold" do
|
45
|
+
threshold.should_receive(:warn).with("10")
|
46
|
+
threshold.should_receive(:crit).with("20")
|
47
|
+
plugin.add_threshold(:custom, :warn => "10", :crit => "20")
|
48
|
+
plugin.thresholds[:custom].should eq(threshold)
|
49
|
+
end
|
50
|
+
|
51
|
+
context "#nagios_exit" do
|
52
|
+
|
53
|
+
it "should exit with unknown status when exit code is not found." do
|
54
|
+
begin
|
55
|
+
message = capture_output do
|
56
|
+
plugin.nagios_exit(:foo, "it works!")
|
57
|
+
end
|
58
|
+
rescue SystemExit => e
|
59
|
+
e.status.should eq(Nagios::UNKNOWN)
|
60
|
+
end
|
61
|
+
message.should eq("UNKNOWN - exit code 'foo' is not found.\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should exit with OK status" do
|
65
|
+
begin
|
66
|
+
message = capture_output do
|
67
|
+
plugin.nagios_exit(Nagios::OK, "it works!\n")
|
68
|
+
end
|
69
|
+
rescue SystemExit => e
|
70
|
+
e.status.should eq(Nagios::OK)
|
71
|
+
end
|
72
|
+
message.should eq("OK - it works!\n")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should exit with WARNING status" do
|
76
|
+
begin
|
77
|
+
message = capture_output do
|
78
|
+
plugin.nagios_exit(:warning, "does not work.")
|
79
|
+
end
|
80
|
+
rescue SystemExit => e
|
81
|
+
e.status.should eq(Nagios::WARNING)
|
82
|
+
end
|
83
|
+
message.should eq("WARNING - does not work.\n")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should exit with Unknown status when check method raises error" do
|
87
|
+
begin
|
88
|
+
message = capture_output do
|
89
|
+
plugin.run
|
90
|
+
end
|
91
|
+
rescue SystemExit => e
|
92
|
+
e.status.should eq(Nagios::UNKNOWN)
|
93
|
+
end
|
94
|
+
message.should eq("UNKNOWN - Nagios::Check::Base#check method should be implemented in the child class\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
context "options parser" do
|
100
|
+
|
101
|
+
it "should have default threshold" do
|
102
|
+
plugin.thresholds.should be_empty
|
103
|
+
threshold.stub(:warn)
|
104
|
+
threshold.stub(:crit)
|
105
|
+
plugin.parse(["-w", "10", "-c", "20"])
|
106
|
+
plugin.thresholds[:default].should eq(threshold)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should parse options and setup thresholds" do
|
110
|
+
threshold.should_receive(:crit).with("20")
|
111
|
+
threshold.should_receive(:warn).with("10")
|
112
|
+
plugin.parse(["-w", "10", "-c", "20"])
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should parse long options and setup thresholds" do
|
116
|
+
threshold.should_receive(:crit).with("@20:40")
|
117
|
+
threshold.should_receive(:warn).with("10:20")
|
118
|
+
plugin.parse(["--warning=10:20", "--critical=@20:40"])
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should parse other options defined in the child class" do
|
122
|
+
plugin = TestPlugin.new
|
123
|
+
threshold.should_receive(:crit).with("@20:40")
|
124
|
+
threshold.should_receive(:warn).with("10:20")
|
125
|
+
plugin.parse(["--warning=10:20", "--critical=@20:40", "-H", "domain.com", "--port=80"])
|
126
|
+
plugin.options[:host] = "domain.com"
|
127
|
+
plugin.options[:port] = 80
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagios::Check::Range do
|
4
|
+
|
5
|
+
it "should raise error when range is not a string" do
|
6
|
+
lambda { Nagios::Check::Range.new(:x) }.should raise_error(TypeError)
|
7
|
+
lambda { Nagios::Check::Range.new(nil) }.should raise_error(TypeError)
|
8
|
+
lambda { Nagios::Check::Range.new(true) }.should raise_error(TypeError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise error when range is bad formatted" do
|
12
|
+
lambda { Nagios::Check::Range.new("abc") }.should raise_error(TypeError)
|
13
|
+
lambda { Nagios::Check::Range.new("10::") }.should raise_error(TypeError)
|
14
|
+
lambda { Nagios::Check::Range.new("-10::") }.should raise_error(TypeError)
|
15
|
+
end
|
16
|
+
|
17
|
+
context "parse string value correctly" do
|
18
|
+
|
19
|
+
it "should convert string check value into float" do
|
20
|
+
range = Nagios::Check::Range.new("10") # 0 <= x >= 10
|
21
|
+
range.check_range("10").should eq(false)
|
22
|
+
range.check_range("5.5").should eq(false)
|
23
|
+
range.check_range("0").should eq(false)
|
24
|
+
range.check_range("20").should eq(true) # > 10
|
25
|
+
range.check_range("-10").should eq(true) # < 0
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should convert numeric range value into string" do
|
29
|
+
range = Nagios::Check::Range.new(10) # 0 <= x >= 10
|
30
|
+
range.check_range(10).should eq(false)
|
31
|
+
range.check_range(5).should eq(false)
|
32
|
+
range.check_range(0).should eq(false)
|
33
|
+
range.check_range(20).should eq(true) # > 10
|
34
|
+
range.check_range(-10).should eq(true) # < 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should check range '10'" do
|
38
|
+
range = Nagios::Check::Range.new("10") # 0 <= x >= 10
|
39
|
+
range.check_range(10).should eq(false)
|
40
|
+
range.check_range(5).should eq(false)
|
41
|
+
range.check_range(0).should eq(false)
|
42
|
+
range.check_range(20).should eq(true) # > 10
|
43
|
+
range.check_range(-10).should eq(true) # < 0
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should check range '10:20'" do
|
47
|
+
range = Nagios::Check::Range.new("10:20") # 10 <= x >= 20
|
48
|
+
range.check_range(10).should eq(false)
|
49
|
+
range.check_range(15).should eq(false)
|
50
|
+
range.check_range(20).should eq(false)
|
51
|
+
range.check_range(5).should eq(true) # < 10
|
52
|
+
range.check_range(30).should eq(true) # > 20
|
53
|
+
range.check_range(-10).should eq(true) # < 0
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should check negative range '-10:20'" do
|
57
|
+
range = Nagios::Check::Range.new("-10:20") # 10 <= x >= 20
|
58
|
+
range.check_range(10).should eq(false)
|
59
|
+
range.check_range(15).should eq(false)
|
60
|
+
range.check_range(20).should eq(false)
|
61
|
+
range.check_range(-10).should eq(false)
|
62
|
+
range.check_range(-50).should eq(true) # < -10
|
63
|
+
range.check_range(30).should eq(true) # > 20
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should check range '10:'" do
|
67
|
+
range = Nagios::Check::Range.new("10:") # x >= 10
|
68
|
+
range.check_range(10).should eq(false)
|
69
|
+
range.check_range(20).should eq(false)
|
70
|
+
range.check_range(5).should eq(true) # < 10
|
71
|
+
range.check_range(-10).should eq(true) # < 0
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should check range '~:10'" do
|
75
|
+
range = Nagios::Check::Range.new("~:10") # x <= 10
|
76
|
+
range.check_range(10).should eq(false)
|
77
|
+
range.check_range(0).should eq(false)
|
78
|
+
range.check_range(5).should eq(false)
|
79
|
+
range.check_range(-10).should eq(false)
|
80
|
+
range.check_range(20).should eq(true) # > 10
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should check range '@10:20'" do
|
84
|
+
range = Nagios::Check::Range.new("@10:20") # x < 10 && 20 > x
|
85
|
+
range.check_range(0).should eq(false)
|
86
|
+
range.check_range(5).should eq(false)
|
87
|
+
range.check_range(-10).should eq(false)
|
88
|
+
range.check_range(30).should eq(false)
|
89
|
+
range.check_range(10).should eq(true) # = 10
|
90
|
+
range.check_range(20).should eq(true) # = 20
|
91
|
+
range.check_range(15).should eq(true) # > 10 && < 20
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should check range with float numbers '@10.5:20'" do
|
95
|
+
range = Nagios::Check::Range.new("@10.5:20") # x < 10.5 && 20 > x
|
96
|
+
range.check_range(0).should eq(false)
|
97
|
+
range.check_range(5).should eq(false)
|
98
|
+
range.check_range(-10).should eq(false)
|
99
|
+
range.check_range(30).should eq(false)
|
100
|
+
range.check_range(10).should eq(false)
|
101
|
+
range.check_range(10.4).should eq(false)
|
102
|
+
|
103
|
+
range.check_range(10.5).should eq(true) # = 10.5
|
104
|
+
range.check_range(20).should eq(true) # = 20
|
105
|
+
range.check_range(15).should eq(true) # > 10 && < 20
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagios::Check::Threshold do
|
4
|
+
|
5
|
+
it "should have warn and crit Ranges" do
|
6
|
+
threshold = Nagios::Check::Threshold.new(:warn => "10:20", :crit => "30:40")
|
7
|
+
threshold.warn.should be_a(Nagios::Check::Range)
|
8
|
+
threshold.crit.should be_a(Nagios::Check::Range)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should set thresholds" do
|
12
|
+
threshold = Nagios::Check::Threshold.new
|
13
|
+
threshold.warn.should be_nil
|
14
|
+
threshold.crit.should be_nil
|
15
|
+
threshold.warn("10:20")
|
16
|
+
threshold.warn.should be_a(Nagios::Check::Range)
|
17
|
+
threshold.crit("30:")
|
18
|
+
threshold.crit.should be_a(Nagios::Check::Range)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not set threshold when value is not valid" do
|
22
|
+
threshold = Nagios::Check::Threshold.new
|
23
|
+
threshold.warn.should be_nil
|
24
|
+
threshold.crit.should be_nil
|
25
|
+
threshold.warn("10::")
|
26
|
+
threshold.crit(false)
|
27
|
+
threshold.warn.should be_nil
|
28
|
+
threshold.crit.should be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
context "#get_status" do
|
32
|
+
|
33
|
+
let(:crit_range) { double }
|
34
|
+
let(:warn_range) { double }
|
35
|
+
let(:threshold) { Nagios::Check::Threshold.new(:warn => "10", :crit => "20") }
|
36
|
+
|
37
|
+
before do
|
38
|
+
threshold.stub(:crit).and_return(crit_range)
|
39
|
+
threshold.stub(:warn).and_return(warn_range)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return WARNING status when crit range is not defined" do
|
43
|
+
threshold.stub(:crit).and_return(nil)
|
44
|
+
crit_range.should_not_receive(:check_range)
|
45
|
+
warn_range.should_receive(:check_range).with(15).and_return(true)
|
46
|
+
threshold.get_status(15).should eq(Nagios::WARNING)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return WARNING threshold status" do
|
50
|
+
crit_range.should_receive(:check_range).with(15).and_return(false)
|
51
|
+
warn_range.should_receive(:check_range).with(15).and_return(true)
|
52
|
+
threshold.get_status(15).should eq(Nagios::WARNING)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return CRITICAL threshold status" do
|
56
|
+
crit_range.should_receive(:check_range).with(25).and_return(true)
|
57
|
+
warn_range.should_not_receive(:check_range)
|
58
|
+
threshold.get_status(25).should eq(Nagios::CRITICAL)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should return OK status when neither crit nor warn ranges are defined" do
|
62
|
+
threshold.stub(:warn).and_return(nil)
|
63
|
+
threshold.stub(:crit).and_return(nil)
|
64
|
+
crit_range.should_not_receive(:check_range)
|
65
|
+
warn_range.should_not_receive(:check_range)
|
66
|
+
threshold.get_status(15).should eq(Nagios::OK)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return OK threshold status" do
|
70
|
+
crit_range.should_receive(:check_range).with(5).and_return(false)
|
71
|
+
warn_range.should_receive(:check_range).with(5).and_return(false)
|
72
|
+
threshold.get_status(5).should eq(Nagios::OK)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require 'nagios'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
def capture_output(&block)
|
7
|
+
original_output = STDOUT.clone
|
8
|
+
pipe_r, pipe_w = IO.pipe
|
9
|
+
pipe_r.sync = true
|
10
|
+
output = ""
|
11
|
+
reader = Thread.new do
|
12
|
+
begin
|
13
|
+
loop do
|
14
|
+
output << pipe_r.readpartial(1024)
|
15
|
+
end
|
16
|
+
rescue EOFError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
STDOUT.reopen(pipe_w)
|
20
|
+
yield
|
21
|
+
ensure
|
22
|
+
STDOUT.reopen(original_output)
|
23
|
+
pipe_w.close
|
24
|
+
reader.join
|
25
|
+
return output
|
26
|
+
end
|
27
|
+
|
28
|
+
# prevent output to STDOUT which default logger does
|
29
|
+
Nagios.logger = Logger.new(StringIO.new)
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nagios-check
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Max Horbul
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-10-10 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bundler
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 9
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 3
|
32
|
+
version: "1.3"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rake
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
description: Nagios check written in Ruby
|
64
|
+
email:
|
65
|
+
- max@gorbul.net
|
66
|
+
executables: []
|
67
|
+
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .gitignore
|
74
|
+
- Gemfile
|
75
|
+
- LICENSE.txt
|
76
|
+
- README.md
|
77
|
+
- Rakefile
|
78
|
+
- examples/check_file_age.rb
|
79
|
+
- examples/check_redis.rb
|
80
|
+
- lib/nagios.rb
|
81
|
+
- lib/nagios/check/base.rb
|
82
|
+
- lib/nagios/check/range.rb
|
83
|
+
- lib/nagios/check/threshold.rb
|
84
|
+
- lib/nagios/check/version.rb
|
85
|
+
- nagios-check.gemspec
|
86
|
+
- spec/lib/nagios/check/base_spec.rb
|
87
|
+
- spec/lib/nagios/check/range_spec.rb
|
88
|
+
- spec/lib/nagios/check/threshold_spec.rb
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
homepage: ""
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
|
+
requirements: []
|
117
|
+
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 1.8.25
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: This is a base for Nagios checks development in Ruby
|
123
|
+
test_files:
|
124
|
+
- spec/lib/nagios/check/base_spec.rb
|
125
|
+
- spec/lib/nagios/check/range_spec.rb
|
126
|
+
- spec/lib/nagios/check/threshold_spec.rb
|
127
|
+
- spec/spec_helper.rb
|