sensu 0.9.5 → 0.9.6.beta
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/README.org +8 -42
- data/bin/sensu-api +5 -2
- data/bin/sensu-client +5 -2
- data/bin/sensu-server +5 -2
- data/lib/sensu/api.rb +125 -95
- data/lib/sensu/base.rb +57 -0
- data/lib/sensu/cli.rb +37 -0
- data/lib/sensu/client.rb +126 -129
- data/lib/sensu/constants.rb +8 -0
- data/lib/sensu/logger.rb +39 -0
- data/lib/sensu/patches/ruby.rb +4 -80
- data/lib/sensu/process.rb +57 -0
- data/lib/sensu/server.rb +229 -163
- data/lib/sensu/settings.rb +280 -0
- data/lib/sensu/socket.rb +52 -0
- data/sensu.gemspec +22 -23
- metadata +171 -185
- data/lib/sensu/config.rb +0 -266
- data/lib/sensu/version.rb +0 -3
data/lib/sensu/config.rb
DELETED
@@ -1,266 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
require 'bundler/setup'
|
4
|
-
|
5
|
-
gem 'eventmachine', '~> 1.0.0.beta.4'
|
6
|
-
|
7
|
-
require 'optparse'
|
8
|
-
require 'time'
|
9
|
-
require 'json'
|
10
|
-
require 'hashie'
|
11
|
-
require 'amqp'
|
12
|
-
require 'cabin'
|
13
|
-
require 'cabin/outputs/em/stdlib-logger'
|
14
|
-
|
15
|
-
require File.join(File.dirname(__FILE__), 'version')
|
16
|
-
require File.join(File.dirname(__FILE__), 'patches', 'ruby')
|
17
|
-
require File.join(File.dirname(__FILE__), 'patches', 'amqp')
|
18
|
-
|
19
|
-
if ENV['RBTRACE']
|
20
|
-
require 'rbtrace'
|
21
|
-
end
|
22
|
-
|
23
|
-
module Sensu
|
24
|
-
class Config
|
25
|
-
attr_accessor :logger, :settings
|
26
|
-
|
27
|
-
DEFAULT_OPTIONS = {
|
28
|
-
:config_file => '/etc/sensu/config.json',
|
29
|
-
:config_dir => '/etc/sensu/conf.d'
|
30
|
-
}
|
31
|
-
|
32
|
-
def initialize(options={})
|
33
|
-
@options = DEFAULT_OPTIONS.merge(options)
|
34
|
-
setup_logging
|
35
|
-
setup_settings
|
36
|
-
end
|
37
|
-
|
38
|
-
def invalid_config(message)
|
39
|
-
puts 'CONFIGURATION INVALID: ' + message
|
40
|
-
puts 'SENSU NOT RUNNING'
|
41
|
-
exit 2
|
42
|
-
end
|
43
|
-
|
44
|
-
def setup_logging
|
45
|
-
if @options[:log_file]
|
46
|
-
if File.writable?(@options[:log_file]) || !File.exist?(@options[:log_file]) && File.writable?(File.dirname(@options[:log_file]))
|
47
|
-
STDOUT.reopen(@options[:log_file], 'a')
|
48
|
-
STDERR.reopen(STDOUT)
|
49
|
-
STDOUT.sync = true
|
50
|
-
else
|
51
|
-
invalid_config('log file is not writable: ' + @options[:log_file])
|
52
|
-
end
|
53
|
-
end
|
54
|
-
@logger = Cabin::Channel.new
|
55
|
-
log_output = File.basename($0) == 'rake' ? '/tmp/sensu-test.log' : STDOUT
|
56
|
-
@logger.subscribe(Cabin::Outputs::EM::StdlibLogger.new(Logger.new(log_output)))
|
57
|
-
@logger.level = @options[:verbose] ? :debug : :info
|
58
|
-
if Signal.list.include?('USR1')
|
59
|
-
Signal.trap('USR1') do
|
60
|
-
@logger.level = @logger.level == :info ? :debug : :info
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def validate_common_settings
|
66
|
-
@settings.checks.each do |name, details|
|
67
|
-
if details.key?('status') || details.key?('output')
|
68
|
-
invalid_config('reserved key (output or status) defined in check ' + name)
|
69
|
-
end
|
70
|
-
unless details.interval.is_a?(Integer) && details.interval > 0
|
71
|
-
invalid_config('missing interval for check ' + name)
|
72
|
-
end
|
73
|
-
unless details.command.is_a?(String)
|
74
|
-
invalid_config('missing command for check ' + name)
|
75
|
-
end
|
76
|
-
unless details.standalone
|
77
|
-
unless details.subscribers.is_a?(Array) && details.subscribers.count > 0
|
78
|
-
invalid_config('missing subscribers for check ' + name)
|
79
|
-
end
|
80
|
-
details.subscribers.each do |subscriber|
|
81
|
-
unless subscriber.is_a?(String) && !subscriber.empty?
|
82
|
-
invalid_config('a check subscriber must be a string (not empty) for check ' + name)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
if details.key?('handler')
|
87
|
-
unless details.handler.is_a?(String)
|
88
|
-
invalid_config('handler must be a string for check ' + name)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
if details.key?('handlers')
|
92
|
-
unless details.handlers.is_a?(Array)
|
93
|
-
invalid_config('handlers must be an array for check ' + name)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def validate_server_settings
|
100
|
-
unless @settings.handlers.include?('default')
|
101
|
-
invalid_config('missing default handler')
|
102
|
-
end
|
103
|
-
@settings.handlers.each do |name, details|
|
104
|
-
unless details.is_a?(Hash)
|
105
|
-
invalid_config('handler details must be a hash for handler ' + name)
|
106
|
-
end
|
107
|
-
unless details['type'].is_a?(String)
|
108
|
-
invalid_config('missing type for handler ' + name)
|
109
|
-
end
|
110
|
-
case details['type']
|
111
|
-
when 'pipe'
|
112
|
-
unless details.command.is_a?(String)
|
113
|
-
invalid_config('missing command for pipe handler ' + name)
|
114
|
-
end
|
115
|
-
when 'amqp'
|
116
|
-
unless details.exchange.is_a?(Hash)
|
117
|
-
invalid_config('missing exchange details for amqp handler ' + name)
|
118
|
-
end
|
119
|
-
unless details.exchange.name.is_a?(String)
|
120
|
-
invalid_config('missing exchange name for amqp handler ' + name)
|
121
|
-
end
|
122
|
-
if details.exchange.key?('type')
|
123
|
-
unless %w[direct fanout topic].include?(details.exchange['type'])
|
124
|
-
invalid_config('invalid exchange type for amqp handler ' + name)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
when 'set'
|
128
|
-
unless details.handlers.is_a?(Array) && details.handlers.count > 0
|
129
|
-
invalid_config('missing handler set for handler ' + name)
|
130
|
-
end
|
131
|
-
else
|
132
|
-
invalid_config('unknown type for handler ' + name)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def validate_api_settings
|
138
|
-
unless @settings.api.port.is_a?(Integer)
|
139
|
-
invalid_config('api port must be an integer')
|
140
|
-
end
|
141
|
-
if @settings.api.key?('user') || @settings.api.key?('password')
|
142
|
-
unless @settings.api.user.is_a?(String)
|
143
|
-
invalid_config('api user must be a string')
|
144
|
-
end
|
145
|
-
unless @settings.api.password.is_a?(String)
|
146
|
-
invalid_config('api password must be a string')
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def validate_client_settings
|
152
|
-
unless @settings.client.name.is_a?(String)
|
153
|
-
invalid_config('client must have a name')
|
154
|
-
end
|
155
|
-
unless @settings.client.address.is_a?(String)
|
156
|
-
invalid_config('client must have an address (ip or hostname)')
|
157
|
-
end
|
158
|
-
unless @settings.client.subscriptions.is_a?(Array) && @settings.client.subscriptions.count > 0
|
159
|
-
invalid_config('client must have subscriptions')
|
160
|
-
end
|
161
|
-
@settings.client.subscriptions.each do |subscription|
|
162
|
-
unless subscription.is_a?(String) && !subscription.empty?
|
163
|
-
invalid_config('a client subscription must be a string (not empty)')
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def has_keys(keys)
|
169
|
-
keys.each do |key|
|
170
|
-
unless @settings.key?(key)
|
171
|
-
invalid_config('missing the following key: ' + key)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def validate_settings
|
177
|
-
@logger.debug('[validate] -- validating configuration')
|
178
|
-
has_keys(%w[checks])
|
179
|
-
validate_common_settings
|
180
|
-
case File.basename($0)
|
181
|
-
when 'rake'
|
182
|
-
has_keys(%w[api handlers client])
|
183
|
-
validate_server_settings
|
184
|
-
validate_api_settings
|
185
|
-
validate_client_settings
|
186
|
-
when 'sensu-server'
|
187
|
-
has_keys(%w[handlers])
|
188
|
-
validate_server_settings
|
189
|
-
when 'sensu-api'
|
190
|
-
has_keys(%w[api])
|
191
|
-
validate_api_settings
|
192
|
-
when 'sensu-client'
|
193
|
-
has_keys(%w[client])
|
194
|
-
validate_client_settings
|
195
|
-
end
|
196
|
-
@logger.info('[validate] -- configuration valid -- running')
|
197
|
-
end
|
198
|
-
|
199
|
-
def setup_settings
|
200
|
-
if File.readable?(@options[:config_file])
|
201
|
-
begin
|
202
|
-
config_hash = JSON.parse(File.open(@options[:config_file], 'r').read)
|
203
|
-
%w[rabbitmq redis].each do |key|
|
204
|
-
config_hash[key] ||= Hash.new
|
205
|
-
end
|
206
|
-
rescue JSON::ParserError => error
|
207
|
-
invalid_config('configuration file (' + @options[:config_file] + ') must be valid json: ' + error.to_s)
|
208
|
-
end
|
209
|
-
@settings = Hashie::Mash.new(config_hash)
|
210
|
-
else
|
211
|
-
invalid_config('configuration file does not exist or is not readable: ' + @options[:config_file])
|
212
|
-
end
|
213
|
-
if File.exists?(@options[:config_dir])
|
214
|
-
Dir[@options[:config_dir] + '/**/*.json'].each do |snippet_file|
|
215
|
-
if File.readable?(snippet_file)
|
216
|
-
begin
|
217
|
-
snippet_hash = JSON.parse(File.open(snippet_file, 'r').read)
|
218
|
-
rescue JSON::ParserError => error
|
219
|
-
invalid_config('configuration snippet file (' + snippet_file + ') must be valid json: ' + error.to_s)
|
220
|
-
end
|
221
|
-
merged_settings = @settings.to_hash.deep_merge(snippet_hash)
|
222
|
-
@logger.warn('[settings] -- configuration snippet (' + snippet_file + ') applied changes: ' + @settings.deep_diff(merged_settings).to_json)
|
223
|
-
@settings = Hashie::Mash.new(merged_settings)
|
224
|
-
else
|
225
|
-
invalid_config('configuration snippet file is not readable: ' + snippet_file)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
229
|
-
validate_settings
|
230
|
-
end
|
231
|
-
|
232
|
-
def self.read_arguments(arguments)
|
233
|
-
options = Hash.new
|
234
|
-
optparse = OptionParser.new do |opts|
|
235
|
-
opts.on('-h', '--help', 'Display this message') do
|
236
|
-
puts opts
|
237
|
-
exit
|
238
|
-
end
|
239
|
-
opts.on('-V', '--version', 'Display version') do
|
240
|
-
puts Sensu::VERSION
|
241
|
-
exit
|
242
|
-
end
|
243
|
-
opts.on('-c', '--config FILE', 'Sensu JSON config FILE. Default is /etc/sensu/config.json') do |file|
|
244
|
-
options[:config_file] = file
|
245
|
-
end
|
246
|
-
opts.on('-d', '--config_dir DIR', 'DIR for supplemental Sensu JSON config files. Default is /etc/sensu/conf.d/') do |dir|
|
247
|
-
options[:config_dir] = dir
|
248
|
-
end
|
249
|
-
opts.on('-l', '--log FILE', 'Log to a given FILE. Default is to log to stdout') do |file|
|
250
|
-
options[:log_file] = file
|
251
|
-
end
|
252
|
-
opts.on('-v', '--verbose', 'Enable verbose logging') do
|
253
|
-
options[:verbose] = true
|
254
|
-
end
|
255
|
-
opts.on('-b', '--background', 'Fork into the background') do
|
256
|
-
options[:daemonize] = true
|
257
|
-
end
|
258
|
-
opts.on('-p', '--pid_file FILE', 'Write the PID to a given FILE') do |file|
|
259
|
-
options[:pid_file] = file
|
260
|
-
end
|
261
|
-
end
|
262
|
-
optparse.parse!(arguments)
|
263
|
-
DEFAULT_OPTIONS.merge(options)
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
data/lib/sensu/version.rb
DELETED