nsca 0.1.4 → 0.2.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.
Files changed (5) hide show
  1. data/VERSION +1 -1
  2. data/lib/nsca/check.rb +67 -45
  3. data/nsca.gemspec +2 -2
  4. data/test/test_nsca.rb +159 -24
  5. metadata +3 -3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.2.0
@@ -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 label, unit = nil, warn = nil, crit = nil, min = nil, max = nil
10
- @label, @unit, @warn, @crit, @min, @max = label.to_s, unit, warn, crit, min, max
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
- timeout ||= 0
16
- exception = Class.new Timeout::Error
17
- pd = perfdatas[perfdata_label.to_sym]
18
- timeout = pd.max
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.label.to_sym end
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 label, unit = nil, warn = nil, crit = nil, min = nil, max = nil
51
- cl = Class.new Base
52
- cl.init label, unit, warn, crit, min, max
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
- attr_reader :perfdatas, :return_code, :status, :timestamp
67
- def initialize return_code = nil, status = nil, perfdatas = nil
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.to_sym
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(return_code)}"
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
- @perfdatas[perfdata_label.to_sym].measure &block
135
+ push perfdata_for( perfdata_label).measure( &block)
111
136
  end
112
137
  def send() NSCA::send self end
113
138
 
114
- def ok status = nil, perfdatas = nil
115
- init ReturnCode::OK, status, perfdatas
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 service, hostname = nil, perfdatas = nil
158
- @service, @hostname, @perfdatas = service, hostname || `hostname -f`, {}
159
- perfdatas.each {|pd| @perfdatas[pd.label.to_sym] = pd }
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
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "nsca"
8
- s.version = "0.1.4"
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-09"
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 = [
@@ -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
- class TestChecks
5
- extend NSCA::Checks
6
- PD1 = perfdata :pd1_in_sec, :s, 10, 20, 0, 30
7
- PD2 = perfdata :pd2_in_1, 1, 0.99, 0.98, 0, 1
8
- PD3 = perfdata :pd3_count, :c, 3, 5, 0
9
- T0 = check 'TestNSCA0', 'uxnags01-sbe.net.mobilkom.at'
10
- T1 = check 'TestNSCA1', 'uxnags01-sbe.net.mobilkom.at', [PD1, PD2]
11
- T2 = check :TestNSCA2, 'uxnags01-sbe.net.mobilkom.at', [PD1, PD2, PD3]
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
- context 'our test server' do
15
- should 'receive data. NSCA-server should run on localhost 5777. if not, ignore this test. password=abcdefghijkl' do
16
- PD1 = TestChecks::PD1
17
- PD2 = TestChecks::PD2
18
- PD3 = TestChecks::PD3
19
- T0 = TestChecks::T0
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
- checks << TestChecks::T0.new( 1, "0123456789"*51+"AB")
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
- checks << TestChecks::T1.new( nil, "Should be OK", [pd1, pd2, pd3])
43
+ t1 = T1.new( nil, "Should be OK", [pd1, pd2, pd3], timestamp)
44
+ checks << t1
30
45
 
31
- NSCA::destinations << NSCA::Client.new( 'localhost', 5667, password: 'abcdefghijkl')
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
- cl = NSCA::PerformanceData.create 'returned and subclass the same test'
73
- assert cl == NSCA::PerformanceData::Returned_and_subclass_the_same_test, 'Classes are not the same.'
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
- class TestNSCA::Client < Test::Unit::TestCase
92
- should '' do
93
- NSCA::Client
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.1.4
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-09 00:00:00.000000000 Z
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: -1034310641
165
+ hash: -843459889
166
166
  required_rubygems_version: !ruby/object:Gem::Requirement
167
167
  none: false
168
168
  requirements: