sensu 0.12.6 → 0.13.0.alpha
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +41 -0
- data/lib/sensu/api.rb +145 -205
- data/lib/sensu/cli.rb +2 -1
- data/lib/sensu/client.rb +51 -119
- data/lib/sensu/constants.rb +1 -7
- data/lib/sensu/daemon.rb +221 -0
- data/lib/sensu/server.rb +105 -202
- data/lib/sensu/socket.rb +4 -4
- data/lib/sensu/utilities.rb +6 -29
- data/sensu.gemspec +10 -6
- metadata +223 -228
- data/lib/sensu/base.rb +0 -75
- data/lib/sensu/extensions.rb +0 -162
- data/lib/sensu/extensions/handlers/debug.rb +0 -17
- data/lib/sensu/extensions/mutators/only_check_output.rb +0 -17
- data/lib/sensu/io.rb +0 -98
- data/lib/sensu/logstream.rb +0 -93
- data/lib/sensu/process.rb +0 -48
- data/lib/sensu/rabbitmq.rb +0 -106
- data/lib/sensu/settings.rb +0 -483
data/lib/sensu/process.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
module Sensu
|
2
|
-
class Process
|
3
|
-
def initialize
|
4
|
-
@logger = Logger.get
|
5
|
-
end
|
6
|
-
|
7
|
-
def write_pid(file)
|
8
|
-
begin
|
9
|
-
File.open(file, 'w') do |pid_file|
|
10
|
-
pid_file.puts(::Process.pid)
|
11
|
-
end
|
12
|
-
rescue
|
13
|
-
@logger.fatal('could not write to pid file', {
|
14
|
-
:pid_file => file
|
15
|
-
})
|
16
|
-
@logger.fatal('SENSU NOT RUNNING!')
|
17
|
-
exit 2
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def daemonize
|
22
|
-
srand
|
23
|
-
if fork
|
24
|
-
exit
|
25
|
-
end
|
26
|
-
unless ::Process.setsid
|
27
|
-
@logger.fatal('cannot detach from controlling terminal')
|
28
|
-
@logger.fatal('SENSU NOT RUNNING!')
|
29
|
-
exit 2
|
30
|
-
end
|
31
|
-
Signal.trap('SIGHUP', 'IGNORE')
|
32
|
-
if fork
|
33
|
-
exit
|
34
|
-
end
|
35
|
-
Dir.chdir('/')
|
36
|
-
ObjectSpace.each_object(IO) do |io|
|
37
|
-
unless [STDIN, STDOUT, STDERR].include?(io)
|
38
|
-
begin
|
39
|
-
unless io.closed?
|
40
|
-
io.close
|
41
|
-
end
|
42
|
-
rescue
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
data/lib/sensu/rabbitmq.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
gem 'amqp', '1.0.0'
|
2
|
-
|
3
|
-
require 'amqp'
|
4
|
-
|
5
|
-
module AMQ
|
6
|
-
module Client
|
7
|
-
module Async
|
8
|
-
module Adapter
|
9
|
-
def send_heartbeat
|
10
|
-
if tcp_connection_established? && !reconnecting?
|
11
|
-
if !@handling_skipped_hearbeats && @last_server_heartbeat
|
12
|
-
send_frame(Protocol::HeartbeatFrame)
|
13
|
-
if @last_server_heartbeat < (Time.now - (self.heartbeat_interval * 2))
|
14
|
-
logger.error('detected missing amqp heartbeats')
|
15
|
-
self.handle_skipped_hearbeats
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
module Sensu
|
26
|
-
class RabbitMQError < StandardError; end
|
27
|
-
|
28
|
-
class RabbitMQ
|
29
|
-
attr_reader :channel
|
30
|
-
|
31
|
-
def initialize
|
32
|
-
@on_error = Proc.new {}
|
33
|
-
@before_reconnect = Proc.new {}
|
34
|
-
@after_reconnect = Proc.new {}
|
35
|
-
end
|
36
|
-
|
37
|
-
def on_error(&block)
|
38
|
-
@on_error = block
|
39
|
-
end
|
40
|
-
|
41
|
-
def before_reconnect(&block)
|
42
|
-
@before_reconnect = block
|
43
|
-
end
|
44
|
-
|
45
|
-
def after_reconnect(&block)
|
46
|
-
@after_reconnect = block
|
47
|
-
end
|
48
|
-
|
49
|
-
def connect(options={})
|
50
|
-
timeout = EM::Timer.new(20) do
|
51
|
-
error = RabbitMQError.new('timed out while attempting to connect')
|
52
|
-
@on_error.call(error)
|
53
|
-
end
|
54
|
-
on_failure = Proc.new do
|
55
|
-
error = RabbitMQError.new('failed to connect')
|
56
|
-
@on_error.call(error)
|
57
|
-
end
|
58
|
-
@connection = AMQP.connect(options, {
|
59
|
-
:on_tcp_connection_failure => on_failure,
|
60
|
-
:on_possible_authentication_failure => on_failure
|
61
|
-
})
|
62
|
-
@connection.logger = Logger.get
|
63
|
-
@connection.on_open do
|
64
|
-
timeout.cancel
|
65
|
-
end
|
66
|
-
reconnect = Proc.new do
|
67
|
-
unless @connection.reconnecting?
|
68
|
-
@before_reconnect.call
|
69
|
-
@connection.periodically_reconnect(5)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
@connection.on_tcp_connection_loss(&reconnect)
|
73
|
-
@connection.on_skipped_heartbeats(&reconnect)
|
74
|
-
@channel = AMQP::Channel.new(@connection)
|
75
|
-
@channel.auto_recovery = true
|
76
|
-
@channel.on_error do |channel, channel_close|
|
77
|
-
error = RabbitMQError.new('rabbitmq channel closed')
|
78
|
-
@on_error.call(error)
|
79
|
-
end
|
80
|
-
prefetch = 1
|
81
|
-
if options.is_a?(Hash)
|
82
|
-
prefetch = options[:prefetch] || 1
|
83
|
-
end
|
84
|
-
@channel.on_recovery do
|
85
|
-
@after_reconnect.call
|
86
|
-
@channel.prefetch(prefetch)
|
87
|
-
end
|
88
|
-
@channel.prefetch(prefetch)
|
89
|
-
end
|
90
|
-
|
91
|
-
def connected?
|
92
|
-
@connection.connected?
|
93
|
-
end
|
94
|
-
|
95
|
-
def close
|
96
|
-
@connection.close
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.connect(options={})
|
100
|
-
options ||= Hash.new
|
101
|
-
rabbitmq = self.new
|
102
|
-
rabbitmq.connect(options)
|
103
|
-
rabbitmq
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
data/lib/sensu/settings.rb
DELETED
@@ -1,483 +0,0 @@
|
|
1
|
-
module Sensu
|
2
|
-
class Settings
|
3
|
-
include Utilities
|
4
|
-
|
5
|
-
attr_reader :indifferent_access, :loaded_env, :loaded_files
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@logger = Logger.get
|
9
|
-
@settings = Hash.new
|
10
|
-
SETTINGS_CATEGORIES.each do |category|
|
11
|
-
@settings[category] = Hash.new
|
12
|
-
end
|
13
|
-
@indifferent_access = false
|
14
|
-
@loaded_env = false
|
15
|
-
@loaded_files = Array.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def indifferent_access!
|
19
|
-
@settings = with_indifferent_access(@settings)
|
20
|
-
@indifferent_access = true
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_hash
|
24
|
-
unless @indifferent_access
|
25
|
-
indifferent_access!
|
26
|
-
end
|
27
|
-
@settings
|
28
|
-
end
|
29
|
-
|
30
|
-
def [](key)
|
31
|
-
to_hash[key]
|
32
|
-
end
|
33
|
-
|
34
|
-
SETTINGS_CATEGORIES.each do |category|
|
35
|
-
define_method(category) do
|
36
|
-
@settings[category].map do |name, details|
|
37
|
-
details.merge(:name => name.to_s)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
type = category.to_s.chop
|
42
|
-
|
43
|
-
define_method((type + '_exists?').to_sym) do |name|
|
44
|
-
@settings[category].has_key?(name.to_sym)
|
45
|
-
end
|
46
|
-
|
47
|
-
define_method(('invalid_' + type).to_sym) do |details, reason|
|
48
|
-
invalid(reason, {
|
49
|
-
type => details
|
50
|
-
})
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def load_env
|
55
|
-
if ENV['RABBITMQ_URL']
|
56
|
-
@settings[:rabbitmq] = ENV['RABBITMQ_URL']
|
57
|
-
@logger.warn('using rabbitmq url environment variable', {
|
58
|
-
:rabbitmq_url => ENV['RABBITMQ_URL']
|
59
|
-
})
|
60
|
-
end
|
61
|
-
ENV['REDIS_URL'] ||= ENV['REDISTOGO_URL']
|
62
|
-
if ENV['REDIS_URL']
|
63
|
-
@settings[:redis] = ENV['REDIS_URL']
|
64
|
-
@logger.warn('using redis url environment variable', {
|
65
|
-
:redis_url => ENV['REDIS_URL']
|
66
|
-
})
|
67
|
-
end
|
68
|
-
ENV['API_PORT'] ||= ENV['PORT']
|
69
|
-
if ENV['API_PORT']
|
70
|
-
@settings[:api] ||= Hash.new
|
71
|
-
@settings[:api][:port] = ENV['API_PORT']
|
72
|
-
@logger.warn('using api port environment variable', {
|
73
|
-
:api_port => ENV['API_PORT']
|
74
|
-
})
|
75
|
-
end
|
76
|
-
@indifferent_access = false
|
77
|
-
@loaded_env = true
|
78
|
-
end
|
79
|
-
|
80
|
-
def load_file(file)
|
81
|
-
@logger.debug('loading config file', {
|
82
|
-
:config_file => file
|
83
|
-
})
|
84
|
-
if File.file?(file) && File.readable?(file)
|
85
|
-
begin
|
86
|
-
contents = File.open(file, 'r').read
|
87
|
-
config = Oj.load(contents, :mode => :strict)
|
88
|
-
merged = deep_merge(@settings, config)
|
89
|
-
unless @loaded_files.empty?
|
90
|
-
changes = deep_diff(@settings, merged)
|
91
|
-
@logger.warn('config file applied changes', {
|
92
|
-
:config_file => file,
|
93
|
-
:changes => redact_sensitive(changes)
|
94
|
-
})
|
95
|
-
end
|
96
|
-
@settings = merged
|
97
|
-
@indifferent_access = false
|
98
|
-
@loaded_files << file
|
99
|
-
rescue Oj::ParseError => error
|
100
|
-
@logger.error('config file must be valid json', {
|
101
|
-
:config_file => file,
|
102
|
-
:error => error.to_s
|
103
|
-
})
|
104
|
-
@logger.warn('ignoring config file', {
|
105
|
-
:config_file => file
|
106
|
-
})
|
107
|
-
end
|
108
|
-
else
|
109
|
-
@logger.error('config file does not exist or is not readable', {
|
110
|
-
:config_file => file
|
111
|
-
})
|
112
|
-
@logger.warn('ignoring config file', {
|
113
|
-
:config_file => file
|
114
|
-
})
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def load_directory(directory)
|
119
|
-
path = directory.gsub(/\\(?=\S)/, '/')
|
120
|
-
Dir.glob(File.join(path, '**/*.json')).each do |file|
|
121
|
-
load_file(file)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def set_env
|
126
|
-
ENV['SENSU_CONFIG_FILES'] = @loaded_files.join(':')
|
127
|
-
end
|
128
|
-
|
129
|
-
def validate
|
130
|
-
@logger.debug('validating settings')
|
131
|
-
SETTINGS_CATEGORIES.each do |category|
|
132
|
-
unless @settings[category].is_a?(Hash)
|
133
|
-
invalid(category.to_s + ' must be a hash')
|
134
|
-
end
|
135
|
-
send(category).each do |details|
|
136
|
-
send(('validate_' + category.to_s.chop).to_sym, details)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
case File.basename($0)
|
140
|
-
when 'sensu-client'
|
141
|
-
validate_client
|
142
|
-
when 'sensu-api'
|
143
|
-
validate_api
|
144
|
-
when 'rspec'
|
145
|
-
validate_client
|
146
|
-
validate_api
|
147
|
-
end
|
148
|
-
@logger.debug('settings are valid')
|
149
|
-
end
|
150
|
-
|
151
|
-
private
|
152
|
-
|
153
|
-
def invalid(reason, data={})
|
154
|
-
@logger.fatal('invalid settings', {
|
155
|
-
:reason => reason
|
156
|
-
}.merge(data))
|
157
|
-
@logger.fatal('SENSU NOT RUNNING!')
|
158
|
-
exit 2
|
159
|
-
end
|
160
|
-
|
161
|
-
def validate_subdue(type, details)
|
162
|
-
condition = details[:subdue]
|
163
|
-
data = {
|
164
|
-
type => details
|
165
|
-
}
|
166
|
-
unless condition.is_a?(Hash)
|
167
|
-
invalid(type + ' subdue must be a hash', data)
|
168
|
-
end
|
169
|
-
if condition.has_key?(:at)
|
170
|
-
unless %w[handler publisher].include?(condition[:at])
|
171
|
-
invalid(type + ' subdue at must be either handler or publisher', data)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
if condition.has_key?(:begin) || condition.has_key?(:end)
|
175
|
-
begin
|
176
|
-
Time.parse(condition[:begin])
|
177
|
-
Time.parse(condition[:end])
|
178
|
-
rescue
|
179
|
-
invalid(type + ' subdue begin & end times must be valid', data)
|
180
|
-
end
|
181
|
-
end
|
182
|
-
if condition.has_key?(:days)
|
183
|
-
unless condition[:days].is_a?(Array)
|
184
|
-
invalid(type + ' subdue days must be an array', data)
|
185
|
-
end
|
186
|
-
condition[:days].each do |day|
|
187
|
-
days = %w[sunday monday tuesday wednesday thursday friday saturday]
|
188
|
-
unless day.is_a?(String) && days.include?(day.downcase)
|
189
|
-
invalid(type + ' subdue days must be valid days of the week', data)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
if condition.has_key?(:exceptions)
|
194
|
-
unless condition[:exceptions].is_a?(Array)
|
195
|
-
invalid(type + ' subdue exceptions must be an array', data)
|
196
|
-
end
|
197
|
-
condition[:exceptions].each do |exception|
|
198
|
-
unless exception.is_a?(Hash)
|
199
|
-
invalid(type + ' subdue exceptions must each be a hash', data)
|
200
|
-
end
|
201
|
-
if exception.has_key?(:begin) || exception.has_key?(:end)
|
202
|
-
begin
|
203
|
-
Time.parse(exception[:begin])
|
204
|
-
Time.parse(exception[:end])
|
205
|
-
rescue
|
206
|
-
invalid(type + ' subdue exception begin & end times must be valid', data)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def validate_check(check)
|
214
|
-
unless check[:name] =~ /^[\w\.-]+$/
|
215
|
-
invalid_check(check, 'check name cannot contain spaces or special characters')
|
216
|
-
end
|
217
|
-
unless (check[:interval].is_a?(Integer) && check[:interval] > 0) || !check[:publish]
|
218
|
-
invalid_check(check, 'check is missing interval')
|
219
|
-
end
|
220
|
-
unless check[:command].is_a?(String)
|
221
|
-
invalid_check(check, 'check is missing command')
|
222
|
-
end
|
223
|
-
if check.has_key?(:standalone)
|
224
|
-
unless !!check[:standalone] == check[:standalone]
|
225
|
-
invalid_check(check, 'check standalone must be boolean')
|
226
|
-
end
|
227
|
-
end
|
228
|
-
unless check[:standalone]
|
229
|
-
unless check[:subscribers].is_a?(Array)
|
230
|
-
invalid_check(check, 'check is missing subscribers')
|
231
|
-
end
|
232
|
-
check[:subscribers].each do |subscriber|
|
233
|
-
unless subscriber.is_a?(String) && !subscriber.empty?
|
234
|
-
invalid_check(check, 'check subscribers must each be a string')
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
if check.has_key?(:timeout)
|
239
|
-
unless check[:timeout].is_a?(Numeric)
|
240
|
-
invalid_check(check, 'check timeout must be numeric')
|
241
|
-
end
|
242
|
-
end
|
243
|
-
if check.has_key?(:handler)
|
244
|
-
unless check[:handler].is_a?(String)
|
245
|
-
invalid_check(check, 'check handler must be a string')
|
246
|
-
end
|
247
|
-
end
|
248
|
-
if check.has_key?(:handlers)
|
249
|
-
unless check[:handlers].is_a?(Array)
|
250
|
-
invalid_check(check, 'check handlers must be an array')
|
251
|
-
end
|
252
|
-
check[:handlers].each do |handler_name|
|
253
|
-
unless handler_name.is_a?(String)
|
254
|
-
invalid_check(check, 'check handlers must each be a string')
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
if check.has_key?(:low_flap_threshold) || check.has_key?(:high_flap_threshold)
|
259
|
-
unless check[:low_flap_threshold].is_a?(Integer)
|
260
|
-
invalid_check(check, 'check low flap threshold must be numeric')
|
261
|
-
end
|
262
|
-
unless check[:high_flap_threshold].is_a?(Integer)
|
263
|
-
invalid_check(check, 'check high flap threshold must be numeric')
|
264
|
-
end
|
265
|
-
end
|
266
|
-
if check.has_key?(:subdue)
|
267
|
-
validate_subdue('check', check)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
def validate_mutator(mutator)
|
272
|
-
unless mutator[:command].is_a?(String)
|
273
|
-
invalid_mutator(mutator, 'mutator is missing command')
|
274
|
-
end
|
275
|
-
if mutator.has_key?(:timeout)
|
276
|
-
unless mutator[:timeout].is_a?(Numeric)
|
277
|
-
invalid_mutator(mutator, 'mutator timeout must be numeric')
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
def validate_filter(filter)
|
283
|
-
unless filter[:attributes].is_a?(Hash)
|
284
|
-
invalid_filter(filter, 'filter attributes must be a hash')
|
285
|
-
end
|
286
|
-
if filter.has_key?(:negate)
|
287
|
-
unless !!filter[:negate] == filter[:negate]
|
288
|
-
invalid_filter(filter, 'filter negate must be boolean')
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def validate_handler(handler)
|
294
|
-
unless handler[:type].is_a?(String)
|
295
|
-
invalid_handler(handler, 'handler is missing type')
|
296
|
-
end
|
297
|
-
case handler[:type]
|
298
|
-
when 'pipe'
|
299
|
-
unless handler[:command].is_a?(String)
|
300
|
-
invalid_handler(handler, 'handler is missing command')
|
301
|
-
end
|
302
|
-
when 'tcp', 'udp'
|
303
|
-
unless handler[:socket].is_a?(Hash)
|
304
|
-
invalid_handler(handler, 'handler is missing socket hash')
|
305
|
-
end
|
306
|
-
unless handler[:socket][:host].is_a?(String)
|
307
|
-
invalid_handler(handler, 'handler is missing socket host')
|
308
|
-
end
|
309
|
-
unless handler[:socket][:port].is_a?(Integer)
|
310
|
-
invalid_handler(handler, 'handler is missing socket port')
|
311
|
-
end
|
312
|
-
when 'amqp'
|
313
|
-
unless handler[:exchange].is_a?(Hash)
|
314
|
-
invalid_handler(handler, 'handler is missing exchange hash')
|
315
|
-
end
|
316
|
-
unless handler[:exchange][:name].is_a?(String)
|
317
|
-
invalid_handler(handler, 'handler is missing exchange name')
|
318
|
-
end
|
319
|
-
if handler[:exchange].has_key?(:type)
|
320
|
-
unless %w[direct fanout topic].include?(handler[:exchange][:type])
|
321
|
-
invalid_handler(handler, 'handler exchange type is invalid')
|
322
|
-
end
|
323
|
-
end
|
324
|
-
when 'set'
|
325
|
-
unless handler[:handlers].is_a?(Array)
|
326
|
-
invalid_handler(handler, 'handler set handlers must be an array')
|
327
|
-
end
|
328
|
-
handler[:handlers].each do |handler_name|
|
329
|
-
unless handler_name.is_a?(String)
|
330
|
-
invalid_handler(handler, 'handler set handlers must each be a string')
|
331
|
-
end
|
332
|
-
if handler_exists?(handler_name) && @settings[:handlers][handler_name.to_sym][:type] == 'set'
|
333
|
-
invalid_handler(handler, 'handler sets cannot be nested')
|
334
|
-
end
|
335
|
-
end
|
336
|
-
else
|
337
|
-
invalid_handler(handler, 'unknown handler type')
|
338
|
-
end
|
339
|
-
if handler.has_key?(:timeout)
|
340
|
-
unless handler[:timeout].is_a?(Numeric)
|
341
|
-
invalid_handler(handler, 'handler timeout must be numeric')
|
342
|
-
end
|
343
|
-
end
|
344
|
-
if handler.has_key?(:filter)
|
345
|
-
unless handler[:filter].is_a?(String)
|
346
|
-
invalid_handler(handler, 'handler filter must be a string')
|
347
|
-
end
|
348
|
-
end
|
349
|
-
if handler.has_key?(:filters)
|
350
|
-
unless handler[:filters].is_a?(Array)
|
351
|
-
invalid_handler(handler, 'handler filters must be an array')
|
352
|
-
end
|
353
|
-
handler[:filters].each do |filter_name|
|
354
|
-
unless filter_name.is_a?(String)
|
355
|
-
invalid_handler(handler, 'handler filters items must be strings')
|
356
|
-
end
|
357
|
-
end
|
358
|
-
end
|
359
|
-
if handler.has_key?(:mutator)
|
360
|
-
unless handler[:mutator].is_a?(String)
|
361
|
-
invalid_handler(handler, 'handler mutator must be a string')
|
362
|
-
end
|
363
|
-
end
|
364
|
-
if handler.has_key?(:handle_flapping)
|
365
|
-
unless !!handler[:handle_flapping] == handler[:handle_flapping]
|
366
|
-
invalid_handler(handler, 'handler handle_flapping must be boolean')
|
367
|
-
end
|
368
|
-
end
|
369
|
-
if handler.has_key?(:severities)
|
370
|
-
unless handler[:severities].is_a?(Array) && !handler[:severities].empty?
|
371
|
-
invalid_handler(handler, 'handler severities must be an array and not empty')
|
372
|
-
end
|
373
|
-
handler[:severities].each do |severity|
|
374
|
-
unless SEVERITIES.include?(severity)
|
375
|
-
invalid_handler(handler, 'handler severities are invalid')
|
376
|
-
end
|
377
|
-
end
|
378
|
-
end
|
379
|
-
if handler.has_key?(:subdue)
|
380
|
-
validate_subdue('handler', handler)
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
def validate_client
|
385
|
-
unless @settings[:client].is_a?(Hash)
|
386
|
-
invalid('missing client configuration')
|
387
|
-
end
|
388
|
-
unless @settings[:client][:name] =~ /^[\w\.-]+$/
|
389
|
-
invalid('client must have a name and it cannot contain spaces or special characters')
|
390
|
-
end
|
391
|
-
unless @settings[:client][:address].is_a?(String)
|
392
|
-
invalid('client must have an address')
|
393
|
-
end
|
394
|
-
unless @settings[:client][:subscriptions].is_a?(Array)
|
395
|
-
invalid('client must have subscriptions')
|
396
|
-
end
|
397
|
-
@settings[:client][:subscriptions].each do |subscription|
|
398
|
-
unless subscription.is_a?(String) && !subscription.empty?
|
399
|
-
invalid('client subscriptions must each be a string')
|
400
|
-
end
|
401
|
-
end
|
402
|
-
if @settings[:client].has_key?(:socket)
|
403
|
-
unless @settings[:client][:socket].is_a?(Hash)
|
404
|
-
invalid('client socket must be a hash')
|
405
|
-
end
|
406
|
-
if @settings[:client][:socket].has_key?(:bind)
|
407
|
-
unless @settings[:client][:socket][:bind].is_a?(String)
|
408
|
-
invalid('client socket bind must be a string')
|
409
|
-
end
|
410
|
-
end
|
411
|
-
if @settings[:client][:socket].has_key?(:port)
|
412
|
-
unless @settings[:client][:socket][:port].is_a?(Integer)
|
413
|
-
invalid('client socket port must be an integer')
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
417
|
-
if @settings[:client].has_key?(:keepalive)
|
418
|
-
unless @settings[:client][:keepalive].is_a?(Hash)
|
419
|
-
invalid('client keepalive must be a hash')
|
420
|
-
end
|
421
|
-
if @settings[:client][:keepalive].has_key?(:handler)
|
422
|
-
unless @settings[:client][:keepalive][:handler].is_a?(String)
|
423
|
-
invalid('client keepalive handler must be a string')
|
424
|
-
end
|
425
|
-
end
|
426
|
-
if @settings[:client][:keepalive].has_key?(:handlers)
|
427
|
-
handlers = @settings[:client][:keepalive][:handlers]
|
428
|
-
unless handlers.is_a?(Array)
|
429
|
-
invalid('client keepalive handlers must be an array')
|
430
|
-
end
|
431
|
-
handlers.each do |handler_name|
|
432
|
-
unless handler_name.is_a?(String)
|
433
|
-
invalid('client keepalive handlers must each be a string')
|
434
|
-
end
|
435
|
-
end
|
436
|
-
end
|
437
|
-
if @settings[:client][:keepalive].has_key?(:thresholds)
|
438
|
-
thresholds = @settings[:client][:keepalive][:thresholds]
|
439
|
-
unless thresholds.is_a?(Hash)
|
440
|
-
invalid('client keepalive thresholds must be a hash')
|
441
|
-
end
|
442
|
-
if thresholds.has_key?(:warning)
|
443
|
-
unless thresholds[:warning].is_a?(Integer)
|
444
|
-
invalid('client keepalive warning threshold must be an integer')
|
445
|
-
end
|
446
|
-
end
|
447
|
-
if thresholds.has_key?(:critical)
|
448
|
-
unless thresholds[:critical].is_a?(Integer)
|
449
|
-
invalid('client keepalive critical threshold must be an integer')
|
450
|
-
end
|
451
|
-
end
|
452
|
-
end
|
453
|
-
end
|
454
|
-
if @settings[:client].has_key?(:redact)
|
455
|
-
unless @settings[:client][:redact].is_a?(Array)
|
456
|
-
invalid('client redact must be an array')
|
457
|
-
end
|
458
|
-
@settings[:client][:redact].each do |key|
|
459
|
-
unless key.is_a?(String) && !key.empty?
|
460
|
-
invalid('client redact keys must each be a string')
|
461
|
-
end
|
462
|
-
end
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
def validate_api
|
467
|
-
unless @settings[:api].is_a?(Hash)
|
468
|
-
invalid('missing api configuration')
|
469
|
-
end
|
470
|
-
unless @settings[:api][:port].is_a?(Integer)
|
471
|
-
invalid('api port must be an integer')
|
472
|
-
end
|
473
|
-
if @settings[:api].has_key?(:user) || @settings[:api].has_key?(:password)
|
474
|
-
unless @settings[:api][:user].is_a?(String)
|
475
|
-
invalid('api user must be a string')
|
476
|
-
end
|
477
|
-
unless @settings[:api][:password].is_a?(String)
|
478
|
-
invalid('api password must be a string')
|
479
|
-
end
|
480
|
-
end
|
481
|
-
end
|
482
|
-
end
|
483
|
-
end
|