nsca 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/nsca/check.rb +67 -45
- data/nsca.gemspec +2 -2
- data/test/test_nsca.rb +159 -24
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/nsca/check.rb
CHANGED
@@ -1,29 +1,45 @@
|
|
1
1
|
module NSCA
|
2
2
|
module PerformanceData
|
3
|
+
class TimeUnitExpected < Exception
|
4
|
+
end
|
5
|
+
|
3
6
|
class Base
|
4
7
|
extend Timeout
|
5
8
|
extend Benchmark
|
6
9
|
|
7
10
|
class <<self
|
8
11
|
attr_reader :label, :unit, :warn, :crit, :min, :max
|
9
|
-
def init
|
10
|
-
|
12
|
+
def init *args
|
13
|
+
a, o = args, args.last.is_a?( Hash) ? args.pop : {}
|
14
|
+
@label, @unit = a[0]||o[:label], a[1]||o[:unit]
|
15
|
+
@warn, @crit = a[2]||o[:warn], a[3]||o[:crit]
|
16
|
+
@min, @max = a[4]||o[:min], a[5]||o[:max]
|
17
|
+
raise ArgumentError, "Label expected" unless @label
|
18
|
+
@label = @label.to_s
|
11
19
|
self
|
12
20
|
end
|
13
21
|
|
14
22
|
def measure &block
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
f = case unit.to_s.to_sym
|
24
|
+
when :s then 1
|
25
|
+
when :ms then 1000
|
26
|
+
else raise TimeUnitExpected, "Unit must be seconds (s) or miliseconds (ms) not (#{unit})"
|
27
|
+
end
|
28
|
+
exception = ::Class.new Timeout::Error
|
29
|
+
timeout = max
|
19
30
|
m = realtime do
|
20
31
|
begin
|
21
32
|
timeout timeout, exception, &block
|
22
33
|
rescue exception
|
23
34
|
end
|
24
35
|
end
|
25
|
-
new m
|
36
|
+
new f * m
|
26
37
|
end
|
38
|
+
|
39
|
+
def to_sym() label.to_sym end
|
40
|
+
def to_h() {label: @label, unit: @unit, warn: @warn, crit: @crit, min: @min, max: @max } end
|
41
|
+
def to_a() [label, unit, warn, crit, min, max] end
|
42
|
+
def clone( opts = nil) ::Class.new( self).init opts ? to_h.merge( opts) : to_h end
|
27
43
|
end
|
28
44
|
|
29
45
|
attr_reader :value
|
@@ -34,8 +50,13 @@ module NSCA
|
|
34
50
|
def crit() self.class.crit end
|
35
51
|
def min() self.class.min end
|
36
52
|
def max() self.class.max end
|
53
|
+
def to_a() [label, value, unit, warn, crit, min, max] end
|
37
54
|
def to_s() "#{label}=#{value}#{unit},#{warn},#{crit},#{min},#{max}" end
|
38
|
-
def to_sym() self.class.
|
55
|
+
def to_sym() self.class.to_sym end
|
56
|
+
|
57
|
+
def to_h
|
58
|
+
{label: @label, value: @value, unit: @unit, warn: @warn, crit: @crit, min: @min, max: @max}
|
59
|
+
end
|
39
60
|
|
40
61
|
def return_code
|
41
62
|
if @value.nil? then 3
|
@@ -47,13 +68,9 @@ module NSCA
|
|
47
68
|
end
|
48
69
|
|
49
70
|
class <<self
|
50
|
-
def new
|
51
|
-
|
52
|
-
cl
|
53
|
-
end
|
54
|
-
|
55
|
-
def create label, unit = nil, warn = nil, crit = nil, min = nil, max = nil
|
56
|
-
cl = new label, unit, warn, crit, min, max
|
71
|
+
def new( *args) ::Class.new( Base).init *args end
|
72
|
+
def create label, *args
|
73
|
+
cl = new label, *args
|
57
74
|
clname = NSCA::Helper.class_name_gen label
|
58
75
|
self.const_set clname, cl if clname
|
59
76
|
cl
|
@@ -63,8 +80,10 @@ module NSCA
|
|
63
80
|
|
64
81
|
module Check
|
65
82
|
class Base
|
66
|
-
|
67
|
-
|
83
|
+
attr_accessor :return_code, :status, :timestamp
|
84
|
+
attr_reader :perfdatas
|
85
|
+
|
86
|
+
def initialize return_code = nil, status = nil, perfdatas = nil, timestamp = nil
|
68
87
|
@perfdatas = {}
|
69
88
|
init return_code, status, perfdatas, timestamp || Time.now
|
70
89
|
end
|
@@ -92,46 +111,37 @@ module NSCA
|
|
92
111
|
@perfdatas
|
93
112
|
end
|
94
113
|
|
114
|
+
def perfdata_for label
|
115
|
+
if label.is_a? PerformanceData::Base
|
116
|
+
label
|
117
|
+
else
|
118
|
+
label = label.to_sym
|
119
|
+
self.class.perfdatas[label] || PerformanceData::Base.new( label)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
95
123
|
def []= perfdata_label, value
|
96
124
|
return push value if value.is_a? PerformanceData::Base
|
97
|
-
perfdata_label = perfdata_label.
|
98
|
-
cl = self.class.perfdatas[perfdata_label]
|
99
|
-
cl ||= PerformanceData::Base.new perfdata_label
|
100
|
-
@perfdatas[perfdata_label] = cl.new value
|
125
|
+
@perfdatas[perfdata_label] = perfdata_for( perfdata_label).new value
|
101
126
|
end
|
102
127
|
|
103
128
|
def text
|
104
|
-
r = "#{status || ReturnCode.find(
|
129
|
+
r = "#{status || ReturnCode.find(retcode)}"
|
105
130
|
r += " | #{perfdatas.each_value.map( &:to_s).join ' '}" unless perfdatas.empty?
|
106
131
|
r
|
107
132
|
end
|
108
133
|
|
109
134
|
def measure perfdata_label, &block
|
110
|
-
|
135
|
+
push perfdata_for( perfdata_label).measure( &block)
|
111
136
|
end
|
112
137
|
def send() NSCA::send self end
|
113
138
|
|
114
|
-
def ok
|
115
|
-
|
116
|
-
send
|
117
|
-
end
|
118
|
-
|
119
|
-
def warning status = nil, perfdatas = nil
|
120
|
-
init ReturnCode::WARNING, status, perfdatas
|
121
|
-
send
|
122
|
-
end
|
139
|
+
def ok( *args) init ReturnCode::OK, *args end
|
140
|
+
def warning( *args) init ReturnCode::WARNING, *args end
|
123
141
|
alias warn warning
|
124
|
-
|
125
|
-
def critical status = nil, perfdatas = nil
|
126
|
-
init ReturnCode::CRITICAL, status, perfdatas
|
127
|
-
send
|
128
|
-
end
|
142
|
+
def critical( *args) init ReturnCode::CRITICAL, *args end
|
129
143
|
alias crit critical
|
130
|
-
|
131
|
-
def unknown status = nil, perfdatas = nil
|
132
|
-
init ReturnCode::UNKNOWN, status, perfdatas
|
133
|
-
send
|
134
|
-
end
|
144
|
+
def unknown( *args) init ReturnCode::UNKNOWN, *args end
|
135
145
|
|
136
146
|
def determine_return_code
|
137
147
|
self.class.perfdatas.map do |label, pdc|
|
@@ -151,12 +161,19 @@ module NSCA
|
|
151
161
|
|
152
162
|
def service() self.class.service end
|
153
163
|
def hostname() self.class.hostname end
|
164
|
+
def to_a() [timestamp, retcode, hostname, service, text] end
|
165
|
+
def to_h
|
166
|
+
{timestamp: timestamp, return_code: retcode, hostname: hostname, server: service, status: text}
|
167
|
+
end
|
154
168
|
|
155
169
|
class <<self
|
156
170
|
attr_reader :service, :hostname, :perfdatas
|
157
|
-
def init
|
158
|
-
|
159
|
-
|
171
|
+
def init *args
|
172
|
+
a, o = args, args.last.is_a?( Hash) ? args.pop : {}
|
173
|
+
service, hostname = nil, perfdatas = nil
|
174
|
+
@service, @hostname, @perfdatas = a[0]||o[:service], a[1]||o[:hostname]||`hostname`.chomp, {}
|
175
|
+
perfdatas = a[2]||o[:perfdatas]
|
176
|
+
perfdatas.each {|pd| @perfdatas[pd.to_sym] = pd } if perfdatas
|
160
177
|
self
|
161
178
|
end
|
162
179
|
|
@@ -166,6 +183,11 @@ module NSCA
|
|
166
183
|
def critical( status = nil, perfdatas = nil) new.warning status, perfdatas end
|
167
184
|
alias crit critical
|
168
185
|
def unknown( status = nil, perfdatas = nil) new.unknown status, perfdatas end
|
186
|
+
|
187
|
+
def to_a() [service, hostname, perfdatas.dup] end
|
188
|
+
def to_h() {service: service, hostname: hostname, perfdatas: perfdatas.values} end
|
189
|
+
def to_sym() "#{hostname}|#{service}".to_sym end
|
190
|
+
def clone( opts = nil) ::Class.new( self).init opts ? to_h.merge( opts) : to_h end
|
169
191
|
end
|
170
192
|
end
|
171
193
|
|
data/nsca.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "nsca"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Denis Knauf"]
|
12
|
-
s.date = "2013-04-
|
12
|
+
s.date = "2013-04-11"
|
13
13
|
s.description = "Create your alerts easily and send it to Nagios"
|
14
14
|
s.email = "Denis.Knauf@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
data/test/test_nsca.rb
CHANGED
@@ -1,35 +1,79 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'dummy_server'
|
3
|
+
require 'securerandom'
|
2
4
|
|
3
5
|
class TestNSCA < Test::Unit::TestCase
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
context 'xor' do
|
7
|
+
should 'return a if a (random) will xored double with random key. (1000 rounds)' do
|
8
|
+
1000.times do
|
9
|
+
key_len = SecureRandom.random_number 1000
|
10
|
+
a_len = SecureRandom.random_number 1000
|
11
|
+
key = SecureRandom.random_bytes key_len
|
12
|
+
a = SecureRandom.random_bytes a_len
|
13
|
+
assert_equal a, NSCA.xor( key, NSCA.xor(key, a))
|
14
|
+
end
|
15
|
+
end
|
12
16
|
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestNSCACommunication < Test::Unit::TestCase
|
20
|
+
Port = 5787
|
21
|
+
|
22
|
+
include NSCA::Checks
|
23
|
+
|
24
|
+
context "our dummy test server on localhost:#{Port} with random password" do
|
25
|
+
should 'receive data' do
|
26
|
+
password = SecureRandom.random_bytes
|
27
|
+
timestamp = Time.now
|
13
28
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
T1 = TestChecks::T1
|
21
|
-
T2 = TestChecks::T2
|
29
|
+
PD1 = perfdata :pd1_in_sec, :s, 10, 20, 0, 30
|
30
|
+
PD2 = perfdata :pd2_in_1, 1, 0.99, 0.98, 0, 1
|
31
|
+
PD3 = perfdata :pd3_count, :c, 3, 5, 0
|
32
|
+
T0 = check 'TestNSCA0', 'uxnags01-sbe.net.mobilkom.at'
|
33
|
+
T1 = check 'TestNSCA1', 'uxnags01-sbe.net.mobilkom.at', [PD1, PD2]
|
34
|
+
T2 = check :TestNSCA2, 'uxnags01-sbe.net.mobilkom.at', [PD1, PD2, PD3]
|
22
35
|
|
23
36
|
checks = []
|
24
|
-
|
37
|
+
t0 = T0.new( 1, "0123456789"*51+"AB", nil, timestamp) # oversized service name
|
38
|
+
checks << t0
|
25
39
|
|
26
40
|
pd1 = PD1.new 3
|
27
41
|
pd2 = PD2.new 0.9996
|
28
42
|
pd3 = PD3.new 2
|
29
|
-
|
43
|
+
t1 = T1.new( nil, "Should be OK", [pd1, pd2, pd3], timestamp)
|
44
|
+
checks << t1
|
30
45
|
|
31
|
-
NSCA::destinations
|
46
|
+
NSCA::destinations.clear
|
47
|
+
NSCA::destinations << NSCA::Client.new( 'localhost', Port, password: password)
|
48
|
+
|
49
|
+
server = Thread.new { NSCA.dummy_server Port, password: password }
|
50
|
+
sleep 1 # server needs time to start...
|
32
51
|
NSCA::send *checks
|
52
|
+
pc0, pc1 = server.value
|
53
|
+
|
54
|
+
[[t0, pc0], [t1, pc1]].each do |(test, packet)|
|
55
|
+
assert_equal test.hostname, packet.hostname
|
56
|
+
assert_equal test.service, packet.service
|
57
|
+
assert_equal timestamp.to_i, packet.timestamp.to_i
|
58
|
+
assert_equal test.retcode, packet.return_code
|
59
|
+
end
|
60
|
+
# original with B, but B is char 512 and will be replaced by \0
|
61
|
+
assert_equal pc0.status, "0123456789"*51+"A"
|
62
|
+
assert_equal pc1.status, "Should be OK | pd1_in_sec=3s,10,20,0,30 pd2_in_1=0.99961,0.99,0.98,0,1 pd3_count=2c,3,5,0,"
|
63
|
+
end
|
64
|
+
|
65
|
+
should 'fail crc32 if wrong password' do
|
66
|
+
password = SecureRandom.random_bytes
|
67
|
+
timestamp = Time.now
|
68
|
+
T3 = check 'TestNSCA0', 'uxnags01-sbe.net.mobilkom.at'
|
69
|
+
NSCA::destinations.clear
|
70
|
+
NSCA::destinations << NSCA::Client.new( 'localhost', Port, password: password+'a')
|
71
|
+
server = Thread.new { NSCA.dummy_server Port, password: password }
|
72
|
+
sleep 1 # server needs time to start...
|
73
|
+
NSCA::send T3.new( 1, 'status', nil, timestamp)
|
74
|
+
assert_raise NSCA::Packet::CSC32CheckFailed do
|
75
|
+
server.join
|
76
|
+
end
|
33
77
|
end
|
34
78
|
end
|
35
79
|
end
|
@@ -69,8 +113,14 @@ class TestNSCA::PerformanceData < Test::Unit::TestCase
|
|
69
113
|
|
70
114
|
context 'Created NSCA::PerformanceData-subclasses' do
|
71
115
|
should 'be the same like returned' do
|
72
|
-
|
73
|
-
|
116
|
+
PA = NSCA::PerformanceData.create 'returned and subclass the same test'
|
117
|
+
assert_equal PA, NSCA::PerformanceData::Returned_and_subclass_the_same_test
|
118
|
+
end
|
119
|
+
should 'not exists, if #new used' do
|
120
|
+
pb = NSCA::PerformanceData.new 'no subclass'
|
121
|
+
assert_raise NameError do
|
122
|
+
NSCA::PerformanceData::No_subclass
|
123
|
+
end
|
74
124
|
end
|
75
125
|
should 'have a unit if given' do
|
76
126
|
assert :s == perfdata( 'have an unit test', :s).unit, "Not s as unit"
|
@@ -85,11 +135,96 @@ class TestNSCA::PerformanceData < Test::Unit::TestCase
|
|
85
135
|
assert nil == perfdata( 'have not a warn test', nil, nil).warn, "Not nil as warn"
|
86
136
|
end
|
87
137
|
end
|
138
|
+
|
139
|
+
context 'Measure' do
|
140
|
+
should 'work with s' do
|
141
|
+
PC = perfdata 'something in seconds', :s
|
142
|
+
assert PC.measure { true }.is_a?( PC), 'can not be created?'
|
143
|
+
end
|
144
|
+
|
145
|
+
should 'work with ms' do
|
146
|
+
PD = perfdata 'something in mili seconds', :ms
|
147
|
+
assert PD.measure { true }.is_a?( PD), 'can not be created?'
|
148
|
+
end
|
149
|
+
|
150
|
+
should 'not work with something else' do
|
151
|
+
PE = perfdata 'something else than time', :c
|
152
|
+
assert_raise NSCA::PerformanceData::TimeUnitExpected do
|
153
|
+
PE.measure { true }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
should 'measure something between 1s..3s if i sleep 2 seconds' do
|
158
|
+
PF = perfdata 'wait 2 seconds', :s
|
159
|
+
pf = PF.measure { sleep 2 }
|
160
|
+
assert (1..3).include?( pf.value), "Not in range 1s..3s: #{pf.value}s"
|
161
|
+
end
|
162
|
+
|
163
|
+
should 'measure something between 1000ms..3000ms if i sleep 2 seconds' do
|
164
|
+
PG = perfdata 'wait 2000 mili second', :ms
|
165
|
+
pf = PG.measure { sleep 2 }
|
166
|
+
assert (1000..3000).include?( pf.value), "Not in range 1000ms..3000ms: #{pf.value}ms"
|
167
|
+
end
|
168
|
+
end
|
88
169
|
end
|
89
170
|
|
171
|
+
class TestNSCA::Check < Test::Unit::TestCase
|
172
|
+
context 'Data' do
|
173
|
+
should 'also be empty' do
|
174
|
+
CF = NSCA::Check.new 'empty data'
|
175
|
+
cf = CF.new
|
176
|
+
hostname = `hostname`.chomp
|
177
|
+
assert_equal [cf.timestamp, 3, hostname, 'empty data', 'UNKNOWN'], cf.to_a
|
178
|
+
end
|
179
|
+
|
180
|
+
should 'have default a timestamp. ~ -10s..10s' do
|
181
|
+
CG = NSCA::Check.new 'default timestamp'
|
182
|
+
cg = CG.new
|
183
|
+
now = Time.now
|
184
|
+
range = Time.at(now-10) .. Time.at(now+10)
|
185
|
+
assert range.begin <= cg.timestamp && cg.timestamp <= range.end,
|
186
|
+
"Not a valid timestamp ~now: #{cg.timestamp}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'Subclasses' do
|
191
|
+
should 'be created by NSCA::Check.create' do
|
192
|
+
CA = NSCA::Check.create 'a uniq name'
|
193
|
+
assert_same CA, NSCA::Check::A_uniq_name
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'No Subclasses' do
|
198
|
+
should 'be created by NSCA::Check.new' do
|
199
|
+
CB = NSCA::Check.new 'a uniq name, too'
|
200
|
+
assert_raise NameError, 'A class named NSCA::Check::A_uniq_name_too exists' do
|
201
|
+
CB == NSCA::Check::A_uniq_name_too
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
90
205
|
|
91
|
-
|
92
|
-
|
93
|
-
|
206
|
+
context 'Clones' do
|
207
|
+
should 'have old class as superclass' do
|
208
|
+
CC1 = NSCA::Check.new( 'a check which will be for cloning')
|
209
|
+
CC2 = CC1.clone
|
210
|
+
assert_equal CC2.superclass, CC1
|
211
|
+
end
|
212
|
+
|
213
|
+
should 'have the same data' do
|
214
|
+
CD1 = NSCA::Check.new 'a check for same data after cloning'
|
215
|
+
CD2 = CD1.clone
|
216
|
+
assert_equal CD2.to_a, CD2.to_a
|
217
|
+
end
|
218
|
+
|
219
|
+
should 'have the same data, except specific data' do
|
220
|
+
CE1 = NSCA::Check.new 'a check for same data after cloning again, but...'
|
221
|
+
CE2 = CE1.clone service: '... but the service will be changed.'
|
222
|
+
assert_not_equal CE1.service, CE2.service
|
223
|
+
assert_equal 'a check for same data after cloning again, but...', CE1.service
|
224
|
+
assert_equal '... but the service will be changed.', CE2.service
|
225
|
+
ce1_data, ce2_data = CE1.to_a, CE2.to_a
|
226
|
+
ce1_data[0] = ce2_data[0] = 'dummy'
|
227
|
+
assert_equal ce1_data, ce2_data
|
228
|
+
end
|
94
229
|
end
|
95
230
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nsca
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: enum
|
@@ -162,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
162
|
version: '0'
|
163
163
|
segments:
|
164
164
|
- 0
|
165
|
-
hash: -
|
165
|
+
hash: -843459889
|
166
166
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
167
|
none: false
|
168
168
|
requirements:
|