nagi 0.1.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/.gitignore +2 -0
- data/Gemfile +2 -0
- data/README.md +104 -0
- data/Rakefile +2 -0
- data/lib/nagi/dsl.rb +57 -0
- data/lib/nagi/optionparser.rb +48 -0
- data/lib/nagi/plugin.rb +49 -0
- data/lib/nagi/status.rb +42 -0
- data/lib/nagi/utility.rb +11 -0
- data/lib/nagi/version.rb +3 -0
- data/lib/nagi.rb +16 -0
- data/nagi.gemspec +22 -0
- data/spec/nagi/dsl_spec.rb +109 -0
- data/spec/nagi/optionparser_spec.rb +83 -0
- data/spec/nagi/plugin_spec.rb +86 -0
- data/spec/nagi/status_spec.rb +140 -0
- data/spec/nagi/utility_spec.rb +19 -0
- data/spec/spec_helper.rb +2 -0
- metadata +91 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# Nagi
|
2
|
+
|
3
|
+
A Ruby DSL for writing Nagios plugins. It handles the tedium of argument
|
4
|
+
parsing, exit statuses, output formatting and such, and lets you focus on
|
5
|
+
writing the actual check.
|
6
|
+
|
7
|
+
Written by Erik Grinaker <erik@bengler.no>, and licensed under the
|
8
|
+
GNU GPL v3.
|
9
|
+
|
10
|
+
## Example
|
11
|
+
|
12
|
+
A typical plugin looks like this:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
#!/usr/bin/env ruby
|
16
|
+
|
17
|
+
require 'nagi'
|
18
|
+
require Resolv
|
19
|
+
|
20
|
+
Nagi do
|
21
|
+
name 'check_dns'
|
22
|
+
version '0.1'
|
23
|
+
prefix 'DNS'
|
24
|
+
argument :hostname
|
25
|
+
switch :ip, '-i', '--ip IP', 'Expected IP address'
|
26
|
+
|
27
|
+
check do |args|
|
28
|
+
begin
|
29
|
+
ip = Resolv.getaddress(args[:hostname])
|
30
|
+
rescue Resolv::ResolvError => e
|
31
|
+
critical e.message
|
32
|
+
end
|
33
|
+
|
34
|
+
if args[:ip] and ip != args[:ip]
|
35
|
+
critical "#{args[:hostname]} resolves to #{ip}, expected #{args[:ip]}
|
36
|
+
else
|
37
|
+
ok "#{args[:hostname]} resolves to #{ip}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
Here we first set up some basic info like name and version, and specify a few
|
44
|
+
command-line options. Then we write a block of code containing the actual
|
45
|
+
check, which is given the parsed command-line options as a hash, and returns a
|
46
|
+
status via methods like `ok` and `critical`.
|
47
|
+
|
48
|
+
To run the plugin, type `./check_dns.rb --ip 127.0.0.1 localhost`, or try
|
49
|
+
`./check_dns.rb --help` for more info.
|
50
|
+
|
51
|
+
## Reference
|
52
|
+
|
53
|
+
### Metadata
|
54
|
+
|
55
|
+
These describe the program, and are usually given first, if necessary.
|
56
|
+
|
57
|
+
* `name` *name*: the program name.
|
58
|
+
* `version` *version*: the program version.
|
59
|
+
* `prefix` *prefix*: a prefix for the check output.
|
60
|
+
|
61
|
+
### Command-line arguments
|
62
|
+
|
63
|
+
Command-line arguments can be specified, and will be parsed automatically and
|
64
|
+
passed to the `check` method as a hash, with keys given by the argument name.
|
65
|
+
|
66
|
+
* `argument` *name*: a mandatory, positional argument.
|
67
|
+
* `switch` *name*, *args*: an optional switch. *args* are passed directory to
|
68
|
+
the standard Ruby OptionParser class - see its documentation for details.
|
69
|
+
|
70
|
+
Command-line arguments for -h/--help and -V/--version are added and handled
|
71
|
+
automatically.
|
72
|
+
|
73
|
+
### Check
|
74
|
+
|
75
|
+
The check is given as a code block to the `check` method, and is passed the
|
76
|
+
parsed command-line arguments as a hash. It should use one of the methods `ok`,
|
77
|
+
`warning`, `critical`, or `unknown` to return a status. If no status is given,
|
78
|
+
or the block raises an unhandled exception, an Unknown status will be returned.
|
79
|
+
|
80
|
+
* `check` *block*: the code block the the check. Parsed command-line arguments
|
81
|
+
are passed as a hash.
|
82
|
+
* `ok` *message*: returns an OK status.
|
83
|
+
* `warning` *message*: returns a Warning status.
|
84
|
+
* `critical` *message*: returns a Critical status.
|
85
|
+
* `unknown` *message*: returns an Unknown status.
|
86
|
+
* `execute` *command*: executes a shell command, and returns any output (both
|
87
|
+
stdout and stderr). If the command exits with a non-zero status, it will
|
88
|
+
throw an exception. The shell is set to use the `pipefail` option, so non-zero
|
89
|
+
exit statuses in pipelines are detected as well.
|
90
|
+
|
91
|
+
## License
|
92
|
+
|
93
|
+
This program is free software: you can redistribute it and/or modify
|
94
|
+
it under the terms of the GNU General Public License as published by
|
95
|
+
the Free Software Foundation, either version 3 of the License, or
|
96
|
+
(at your option) any later version.
|
97
|
+
|
98
|
+
This program is distributed in the hope that it will be useful,
|
99
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
100
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
101
|
+
GNU General Public License for more details.
|
102
|
+
|
103
|
+
You should have received a copy of the GNU General Public License
|
104
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
data/lib/nagi/dsl.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Nagi
|
2
|
+
class DSL
|
3
|
+
attr_reader :plugin
|
4
|
+
|
5
|
+
def initialize(&block)
|
6
|
+
@plugin = Nagi::Plugin.new
|
7
|
+
instance_eval &block
|
8
|
+
end
|
9
|
+
|
10
|
+
def argument(name)
|
11
|
+
@plugin.optionparser.argument(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def check(&block)
|
15
|
+
p = class << @plugin; self; end
|
16
|
+
p.send(:define_method, :check) do |options|
|
17
|
+
return catch(:status) { block.call(options) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def critical(message)
|
22
|
+
throw :status, Nagi::Status::Critical.new(message)
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute(command)
|
26
|
+
return Nagi::Utility.execute(command)
|
27
|
+
end
|
28
|
+
|
29
|
+
def name(name)
|
30
|
+
@plugin.name = name
|
31
|
+
end
|
32
|
+
|
33
|
+
def ok(message)
|
34
|
+
throw :status, Nagi::Status::OK.new(message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def prefix(prefix)
|
38
|
+
@plugin.prefix = prefix
|
39
|
+
end
|
40
|
+
|
41
|
+
def switch(name, *args)
|
42
|
+
@plugin.optionparser.switch(name, *args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def unknown(message)
|
46
|
+
throw :status, Nagi::Status::Unknown.new(message)
|
47
|
+
end
|
48
|
+
|
49
|
+
def version(version)
|
50
|
+
@plugin.version = version
|
51
|
+
end
|
52
|
+
|
53
|
+
def warning(message)
|
54
|
+
throw :status, Nagi::Status::Warning.new(message)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Nagi
|
2
|
+
class OptionParser < ::OptionParser
|
3
|
+
|
4
|
+
def initialize(*args, &block)
|
5
|
+
@arguments = []
|
6
|
+
@options = {}
|
7
|
+
|
8
|
+
super(*args, &block)
|
9
|
+
|
10
|
+
self.banner = "Usage: #{$0} [options]"
|
11
|
+
|
12
|
+
self.on_tail('-h', '--help', 'Display this help message') do
|
13
|
+
puts help
|
14
|
+
exit 0
|
15
|
+
end
|
16
|
+
|
17
|
+
self.on_tail('-V', '--version', 'Display version information') do
|
18
|
+
puts "#{program_name} #{version or "(unknown version)"}".strip
|
19
|
+
exit 0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def argument(name)
|
24
|
+
@arguments.push(name)
|
25
|
+
self.banner += " <#{name}>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse!(args)
|
29
|
+
begin
|
30
|
+
@options.clear
|
31
|
+
super(args)
|
32
|
+
@arguments.each do |a|
|
33
|
+
@options[a] = args.shift or raise ArgumentError.new("Argument '#{a}' not given")
|
34
|
+
end
|
35
|
+
raise ArgumentError.new("Too many arguments") if args.length > 0
|
36
|
+
rescue ::OptionParser::ParseError => e
|
37
|
+
raise ArgumentError.new(e.message)
|
38
|
+
end
|
39
|
+
return @options
|
40
|
+
end
|
41
|
+
|
42
|
+
def switch(name, *args)
|
43
|
+
on(*args) do |value|
|
44
|
+
@options[name] = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/nagi/plugin.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Nagi
|
2
|
+
class Plugin
|
3
|
+
attr_accessor :name, :optionparser, :prefix, :version
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@optionparser = Nagi::OptionParser.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def check(options)
|
10
|
+
raise NotImplementedError.new('No check defined')
|
11
|
+
end
|
12
|
+
|
13
|
+
def name=(value)
|
14
|
+
@name = value
|
15
|
+
@optionparser.program_name = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def run(args)
|
19
|
+
options = @optionparser.parse(args)
|
20
|
+
begin
|
21
|
+
status = self.check(options)
|
22
|
+
rescue StandardError => e
|
23
|
+
status = Nagi::Status::Unknown.new(e.message)
|
24
|
+
end
|
25
|
+
if not status.is_a?Nagi::Status::Status
|
26
|
+
status = Nagi::Status::Unknown.new('Check did not provide a status')
|
27
|
+
end
|
28
|
+
return status
|
29
|
+
end
|
30
|
+
|
31
|
+
def run!
|
32
|
+
begin
|
33
|
+
status = run(ARGV)
|
34
|
+
puts "#{@prefix.upcase if @prefix} #{status}".strip
|
35
|
+
exit status.code
|
36
|
+
rescue ArgumentError => e
|
37
|
+
STDERR.puts("Error: #{e.message}")
|
38
|
+
puts ""
|
39
|
+
puts @optionparser
|
40
|
+
exit 4
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def version=(value)
|
45
|
+
@version = value
|
46
|
+
@optionparser.version = value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/nagi/status.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Nagi
|
2
|
+
module Status
|
3
|
+
class Status
|
4
|
+
attr_accessor :message
|
5
|
+
attr_reader :code, :name
|
6
|
+
|
7
|
+
def initialize(code, name, message)
|
8
|
+
@code = code
|
9
|
+
@name = name
|
10
|
+
@message = message
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
return "#{@name.upcase}: #{@message}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Critical < Status
|
19
|
+
def initialize(message)
|
20
|
+
super(2, 'Critical', message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class OK < Status
|
25
|
+
def initialize(message)
|
26
|
+
super(0, 'OK', message)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Unknown < Status
|
31
|
+
def initialize(message)
|
32
|
+
super(3, 'Unknown', message)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Warning < Status
|
37
|
+
def initialize(message)
|
38
|
+
super(1, 'Warning', message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/nagi/utility.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Nagi
|
2
|
+
module Utility
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def execute(command)
|
6
|
+
output, status = Open3.capture2e("/bin/bash -o pipefail -c '#{command}'")
|
7
|
+
raise "Shell failure, '#{output.gsub(/^\/bin\/bash: /, '').strip}'" if status.exitstatus != 0
|
8
|
+
return output.strip
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/nagi/version.rb
ADDED
data/lib/nagi.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
require 'nagi/dsl'
|
5
|
+
require 'nagi/optionparser'
|
6
|
+
require 'nagi/plugin'
|
7
|
+
require 'nagi/status'
|
8
|
+
require 'nagi/utility'
|
9
|
+
require 'nagi/version'
|
10
|
+
|
11
|
+
module Nagi
|
12
|
+
end
|
13
|
+
|
14
|
+
def Nagi(&block)
|
15
|
+
Nagi::DSL.new(&block).plugin.run!
|
16
|
+
end
|
data/nagi.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'nagi/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'nagi'
|
7
|
+
s.version = Nagi::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Erik Grinaker']
|
10
|
+
s.email = ['erik@bengler.no']
|
11
|
+
s.homepage = 'http://github.com/bengler/nagi'
|
12
|
+
s.summary = 'A DSL for writing Nagios plugins'
|
13
|
+
s.description = 'A DSL for writing Nagios plugins'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.add_development_dependency 'rake'
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagi::DSL do
|
4
|
+
before(:each) do
|
5
|
+
@dsl = Nagi::DSL.new do
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#plugin' do
|
10
|
+
it 'contains a Nagi::Plugin' do
|
11
|
+
@dsl.plugin.class.should eq Nagi::Plugin
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'is read-only' do
|
15
|
+
lambda { @sdl.plugin = nil }.should raise_error NoMethodError
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.argument' do
|
20
|
+
it 'sends argument to parser.optionparser' do
|
21
|
+
@dsl.argument(:name)
|
22
|
+
@dsl.plugin.optionparser.help.should match /<name>/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '.check' do
|
27
|
+
it 'sets the code block on plugin.check' do
|
28
|
+
@dsl.check do |options|
|
29
|
+
$nagi = options
|
30
|
+
end
|
31
|
+
@dsl.plugin.check({'a' => 1})
|
32
|
+
$nagi.should eq Hash['a' => 1]
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'catches throwns :status and returns payload' do
|
36
|
+
@dsl.check do |options|
|
37
|
+
throw :status, 'status'
|
38
|
+
end
|
39
|
+
@dsl.plugin.check({}).should eq 'status'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.critical' do
|
44
|
+
it 'throws :status with critical status' do
|
45
|
+
catch(:status) do
|
46
|
+
@dsl.critical('message')
|
47
|
+
end.class.should eq Nagi::Status::Critical
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.execute' do
|
52
|
+
it 'executes a command with Nagi::Utility.execute' do
|
53
|
+
@dsl.execute('echo test >&2').should eq 'test'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.name' do
|
58
|
+
it 'sets plugin name' do
|
59
|
+
@dsl.name('name')
|
60
|
+
@dsl.plugin.name.should eq 'name'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '.ok' do
|
65
|
+
it 'throws :status with ok status' do
|
66
|
+
catch(:status) do
|
67
|
+
@dsl.ok('message')
|
68
|
+
end.class.should eq Nagi::Status::OK
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '.prefix' do
|
73
|
+
it 'sets plugin prefix' do
|
74
|
+
@dsl.prefix('prefix')
|
75
|
+
@dsl.plugin.prefix.should eq 'prefix'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '.switch' do
|
80
|
+
it 'adds optionparser switch' do
|
81
|
+
@dsl.switch(:switch, '-s', '--switch', 'Test switch')
|
82
|
+
@dsl.plugin.optionparser.top.list[-1].short[0].should eq '-s'
|
83
|
+
@dsl.plugin.optionparser.top.list[-1].long[0].should eq '--switch'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '.unknown' do
|
88
|
+
it 'throws :status with unknown status' do
|
89
|
+
catch(:status) do
|
90
|
+
@dsl.unknown('message')
|
91
|
+
end.class.should eq Nagi::Status::Unknown
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '.version' do
|
96
|
+
it 'sets plugin version' do
|
97
|
+
@dsl.version('version')
|
98
|
+
@dsl.plugin.version.should eq 'version'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '.warning' do
|
103
|
+
it 'throws :status with warning status' do
|
104
|
+
catch(:status) do
|
105
|
+
@dsl.warning('message')
|
106
|
+
end.class.should eq Nagi::Status::Warning
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagi::OptionParser do
|
4
|
+
before(:each) do
|
5
|
+
@parser = Nagi::OptionParser.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'subclasses OptionParser' do
|
9
|
+
@parser.is_a?(::OptionParser).should eq true
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.initialize' do
|
13
|
+
it 'set proper banner' do
|
14
|
+
@parser.banner.should eq "Usage: #{$0} [options]"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'sets up -h, --help' do
|
18
|
+
@parser.base.list[-2].short[0].should eq '-h'
|
19
|
+
@parser.base.list[-2].long[0].should eq '--help'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'sets up -V, --version' do
|
23
|
+
@parser.base.list[-1].short[0].should eq '-V'
|
24
|
+
@parser.base.list[-1].long[0].should eq '--version'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.argument' do
|
29
|
+
it 'modifies banner' do
|
30
|
+
@parser.argument('test')
|
31
|
+
@parser.banner.should eq "Usage: #{$0} [options] <test>"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.parse!' do
|
36
|
+
it 'parses arguments' do
|
37
|
+
@parser.argument(:test)
|
38
|
+
@parser.parse!(['testvalue']).should eq Hash[:test => 'testvalue']
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'parses switches' do
|
42
|
+
@parser.switch(:test, '-t', '--test', 'Test switch')
|
43
|
+
@parser.parse!(['-t']).should eq Hash[:test => true]
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'parses switches with value' do
|
47
|
+
@parser.switch(:test, '-t', '--test VALUE', 'Test switch')
|
48
|
+
@parser.parse!(['-t', 'testvalue']).should eq Hash[:test => 'testvalue']
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'modifies input array' do
|
52
|
+
args = ['-t', 'testvalue', 'argument']
|
53
|
+
@parser.argument(:arg)
|
54
|
+
@parser.switch(:test, '-t', '--test VALUE', 'Test switch')
|
55
|
+
@parser.parse!(args)
|
56
|
+
args.should eq []
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raises ArgumentError on invalid switch' do
|
60
|
+
lambda { @parser.parse!(['-x']) }.should raise_error ArgumentError
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'raises ArgumentError on too few arguments' do
|
64
|
+
@parser.argument(:test)
|
65
|
+
lambda { @parser.parse!([]) }.should raise_error ArgumentError
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'raises ArgumentError on too many arguments' do
|
69
|
+
@parser.argument(:test)
|
70
|
+
lambda { @parser.parse!(['x', 'y']) }.should raise_error ArgumentError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '.switch' do
|
75
|
+
it 'adds a switch' do
|
76
|
+
@parser.switch('name', '-t', '--test TEST',) do |value|
|
77
|
+
end
|
78
|
+
|
79
|
+
@parser.top.list[-1].short[0].should eq '-t'
|
80
|
+
@parser.top.list[-1].long[0].should eq '--test'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagi::Plugin do
|
4
|
+
before(:each) do
|
5
|
+
@plugin = Nagi::Plugin.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#optionparser' do
|
9
|
+
it 'contains OptionParser' do
|
10
|
+
@plugin.optionparser.class.should eq Nagi::OptionParser
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#name' do
|
15
|
+
it 'sets name' do
|
16
|
+
@plugin.name = 'name'
|
17
|
+
@plugin.name.should eq 'name'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'sets optionparser.program_name' do
|
21
|
+
@plugin.name = 'name'
|
22
|
+
@plugin.optionparser.program_name.should eq 'name'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#prefix' do
|
27
|
+
it 'sets prefix' do
|
28
|
+
@plugin.prefix = 'prefix'
|
29
|
+
@plugin.prefix.should eq 'prefix'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#version' do
|
34
|
+
it 'sets version' do
|
35
|
+
@plugin.version = 'version'
|
36
|
+
@plugin.version.should eq 'version'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'sets optionparser.version' do
|
40
|
+
@plugin.version = 'version'
|
41
|
+
@plugin.optionparser.version.should eq 'version'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '.check' do
|
46
|
+
it 'raises NotImplementedError' do
|
47
|
+
lambda { @plugin.check({}) }.should raise_error NotImplementedError
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.run' do
|
52
|
+
it 'passes parsed options to check' do
|
53
|
+
class << @plugin
|
54
|
+
def check(options)
|
55
|
+
$nagi = options
|
56
|
+
end
|
57
|
+
end
|
58
|
+
@plugin.optionparser.argument(:arg)
|
59
|
+
@plugin.optionparser.switch(:switch, '-s', '--switch VALUE', 'Test switch')
|
60
|
+
@plugin.run(['-s', 'value', 'argument'])
|
61
|
+
$nagi.should eq Hash[:arg => 'argument', :switch => 'value']
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns check status' do
|
65
|
+
class << @plugin
|
66
|
+
def check(options)
|
67
|
+
return Nagi::Status::OK.new('ok')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@plugin.run([]).class.should eq Nagi::Status::OK
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns unknown status on check exception' do
|
74
|
+
class << @plugin
|
75
|
+
def check(options)
|
76
|
+
raise StandardError.new('error')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
@plugin.run([]).class.should eq Nagi::Status::Unknown
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'doesnt catch errors from optionparser' do
|
83
|
+
lambda { @plugin.run(['--invalid']) }.should raise_error ArgumentError
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Nagi::Status::Status do
|
4
|
+
before(:each) do
|
5
|
+
@status = Nagi::Status::Status.new(0, 'name', 'message')
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.code' do
|
9
|
+
it 'contains status code' do
|
10
|
+
@status.code.should eq 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'is read-only' do
|
14
|
+
lambda { @status.code = 1 }.should raise_error NoMethodError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.message' do
|
19
|
+
it 'contains message' do
|
20
|
+
@status.message.should eq 'message'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'is writable' do
|
24
|
+
@status.message = 'test'
|
25
|
+
@status.message.should eq 'test'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.name' do
|
30
|
+
it 'contains name' do
|
31
|
+
@status.name.should eq 'name'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'is read-only' do
|
35
|
+
lambda { @status.name = 'test' }.should raise_error NoMethodError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '.to_s' do
|
40
|
+
it 'formats the status' do
|
41
|
+
@status.to_s.should eq 'NAME: message'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe Nagi::Status::Critical do
|
47
|
+
before(:each) do
|
48
|
+
@status = Nagi::Status::Critical.new('message')
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.code' do
|
52
|
+
it 'is 2' do
|
53
|
+
@status.code.should eq 2
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '.message' do
|
58
|
+
it 'contains message' do
|
59
|
+
@status.message.should eq 'message'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '.name' do
|
64
|
+
it 'is Critical' do
|
65
|
+
@status.name.should eq 'Critical'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe Nagi::Status::OK do
|
71
|
+
before(:each) do
|
72
|
+
@status = Nagi::Status::OK.new('message')
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '.code' do
|
76
|
+
it 'is 0' do
|
77
|
+
@status.code.should eq 0
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '.message' do
|
82
|
+
it 'contains message' do
|
83
|
+
@status.message.should eq 'message'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '.name' do
|
88
|
+
it 'is OK' do
|
89
|
+
@status.name.should eq 'OK'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe Nagi::Status::Unknown do
|
95
|
+
before(:each) do
|
96
|
+
@status = Nagi::Status::Unknown.new('message')
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '.code' do
|
100
|
+
it 'is 3' do
|
101
|
+
@status.code.should eq 3
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '.message' do
|
106
|
+
it 'contains message' do
|
107
|
+
@status.message.should eq 'message'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '.name' do
|
112
|
+
it 'is Unknown' do
|
113
|
+
@status.name.should eq 'Unknown'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe Nagi::Status::Warning do
|
119
|
+
before(:each) do
|
120
|
+
@status = Nagi::Status::Warning.new('message')
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '.code' do
|
124
|
+
it 'is 1' do
|
125
|
+
@status.code.should eq 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '.message' do
|
130
|
+
it 'contains message' do
|
131
|
+
@status.message.should eq 'message'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '.name' do
|
136
|
+
it 'is Warning' do
|
137
|
+
@status.name.should eq 'Warning'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Nagi::Utility::execute' do
|
4
|
+
it 'raises exception on non-zero status' do
|
5
|
+
lambda { Nagi::Utility.execute('exit 1') }.should raise_error StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'raises exception on non-zero status in pipelines' do
|
9
|
+
lambda { Nagi::Utility.execute('false | true') }.should raise_error StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns command stdout' do
|
13
|
+
Nagi::Utility.execute('echo test').should eq 'test'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns command stderr' do
|
17
|
+
Nagi::Utility.execute('echo test >&2').should eq 'test'
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nagi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Erik Grinaker
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70154071720240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70154071720240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70154071719820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70154071719820
|
36
|
+
description: A DSL for writing Nagios plugins
|
37
|
+
email:
|
38
|
+
- erik@bengler.no
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- README.md
|
46
|
+
- Rakefile
|
47
|
+
- lib/nagi.rb
|
48
|
+
- lib/nagi/dsl.rb
|
49
|
+
- lib/nagi/optionparser.rb
|
50
|
+
- lib/nagi/plugin.rb
|
51
|
+
- lib/nagi/status.rb
|
52
|
+
- lib/nagi/utility.rb
|
53
|
+
- lib/nagi/version.rb
|
54
|
+
- nagi.gemspec
|
55
|
+
- spec/nagi/dsl_spec.rb
|
56
|
+
- spec/nagi/optionparser_spec.rb
|
57
|
+
- spec/nagi/plugin_spec.rb
|
58
|
+
- spec/nagi/status_spec.rb
|
59
|
+
- spec/nagi/utility_spec.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
homepage: http://github.com/bengler/nagi
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.11
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: A DSL for writing Nagios plugins
|
85
|
+
test_files:
|
86
|
+
- spec/nagi/dsl_spec.rb
|
87
|
+
- spec/nagi/optionparser_spec.rb
|
88
|
+
- spec/nagi/plugin_spec.rb
|
89
|
+
- spec/nagi/status_spec.rb
|
90
|
+
- spec/nagi/utility_spec.rb
|
91
|
+
- spec/spec_helper.rb
|