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.
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
@@ -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
@@ -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