sensu 0.28.6 → 0.29.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +71 -0
- data/exe/sensu-install +6 -1
- data/lib/sensu/api/http_handler.rb +81 -19
- data/lib/sensu/api/routes.rb +3 -0
- data/lib/sensu/api/routes/clients.rb +11 -3
- data/lib/sensu/api/routes/info.rb +4 -1
- data/lib/sensu/api/routes/request.rb +5 -1
- data/lib/sensu/api/routes/settings.rb +23 -0
- data/lib/sensu/api/utilities/filter_response_content.rb +44 -0
- data/lib/sensu/api/utilities/publish_check_request.rb +51 -1
- data/lib/sensu/cli.rb +8 -2
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +4 -3
- data/lib/sensu/server/process.rb +187 -137
- data/lib/sensu/utilities.rb +4 -3
- data/sensu.gemspec +3 -3
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31731ea9a2311f9aecc12057e03442fb2dffca7e
|
4
|
+
data.tar.gz: ee7b95c65a89a73693717c5220bf7a515ee54634
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1a0e54b2e28998c7653b78f54278ec6f28c2a716fedfc8ab24b59108d33ff9998d60b77776c05e48e556b1decf43c15a2c95ee06842528ae3671cbd7957349a
|
7
|
+
data.tar.gz: d7ed4d7d2cb4794ab2933237d383eb37331dda2adaed120117c25ce36cacb7d4a4cd6e8249439d5f08c1ed52e2e63b5e48e2594603078bcf9f120ca6a52d936b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,74 @@
|
|
1
|
+
## 0.29.0 - 2017-03-29
|
2
|
+
|
3
|
+
### Features
|
4
|
+
|
5
|
+
Sensu server tasks, replacing the Sensu server leader functionality,
|
6
|
+
distributing certain server responsibilities amongst the running Sensu
|
7
|
+
servers. A server task can only run on one Sensu server at a time. Sensu
|
8
|
+
servers partake in an election process to become responsible for one or
|
9
|
+
more tasks. A task can failover to another Sensu server.
|
10
|
+
|
11
|
+
Sensu API response object filtering for any GET request. Filtering is done
|
12
|
+
with one or more dot notation query parameters, beginning with `filter.`,
|
13
|
+
to specify object attributes to filter by, e.g.
|
14
|
+
`/events?filter.client.environment=production&filter.check.contact=ops`.
|
15
|
+
|
16
|
+
Added API endpoint GET `/settings` to provided the APIs running
|
17
|
+
configuration. Sensitive setting values are redacted by default, unless
|
18
|
+
the query parameter `redacted` is set to `false`, e.g.
|
19
|
+
`/settings?redacted=false`.
|
20
|
+
|
21
|
+
Added support for invalidating a Sensu client when deleting it via the
|
22
|
+
Sensu API DELETE `/clients/:name` endpoint, disallowing further client
|
23
|
+
keepalives and check results until the client is either successfully
|
24
|
+
removed from the client registry or for a specified duration of time. To
|
25
|
+
invalidate a Sensu client until it is deleted, the query parameter
|
26
|
+
`invalidate` must be set to `true`, e.g.
|
27
|
+
`/clients/app01.example.com?invalidate=true`. To invalidate the client for
|
28
|
+
a certain amount of time (in seconds), the query parameter
|
29
|
+
`invalidate_expire` must be set as well, e.g.
|
30
|
+
`/clients/app01.example.com?invalidate=true&invalidate_expire=300`.
|
31
|
+
|
32
|
+
Added a Sensu settings hexdigest, exposed via the Sensu API GET `/info`
|
33
|
+
endpoint, providing a means to determine if a Sensu server's configuration
|
34
|
+
differs from the rest.
|
35
|
+
|
36
|
+
Added a proxy argument to `sensu-install`. To use a proxy for Sensu plugin
|
37
|
+
and extension installation with `sensu-install`, use the `-x` or
|
38
|
+
`--proxy` argument, e.g. `sensu-install -e statsd --proxy
|
39
|
+
http://proxy.example.com:8080`.
|
40
|
+
|
41
|
+
Added support for issuing proxy check requests via the Sensu API POST
|
42
|
+
`/request` endpoint.
|
43
|
+
|
44
|
+
The Sensu API now logs response times.
|
45
|
+
|
46
|
+
The Sensu API now returns a 405 (Method Not Allowed) when an API endpoint
|
47
|
+
does not support a HTTP request method, e.g. `PUT`, and sets the HTTP
|
48
|
+
header "Allow" to indicate which HTTP request methods are supported by the
|
49
|
+
requested endpoint.
|
50
|
+
|
51
|
+
Added a built-in filter for check dependencies, `check_dependencies`,
|
52
|
+
which implements the check dependency filtering logic in the Sensu Plugin
|
53
|
+
library.
|
54
|
+
|
55
|
+
Added default values for Sensu CLI options `config_file`
|
56
|
+
(`"/etc/sensu/config.json"`) and `config_dirs` (`["/etc/sensu/conf.d"]`).
|
57
|
+
These defaults are only applied when the associated file and/or directory
|
58
|
+
exist.
|
59
|
+
|
60
|
+
### Other
|
61
|
+
|
62
|
+
Added a Rubocop configuration file and rake tasks for a slow introduction.
|
63
|
+
|
64
|
+
### Fixes
|
65
|
+
|
66
|
+
The built-in filter `occurrences` now supports `refresh` for flapping
|
67
|
+
events (action `flapping`).
|
68
|
+
|
69
|
+
Force the configured Redis port to be an integer, as some users make the
|
70
|
+
mistake of using a string.
|
71
|
+
|
1
72
|
## 0.28.5 - 2017-03-23
|
2
73
|
|
3
74
|
### Fixes
|
data/exe/sensu-install
CHANGED
@@ -10,7 +10,8 @@ module Sensu
|
|
10
10
|
:verbose => false,
|
11
11
|
:plugins => [],
|
12
12
|
:extensions => [],
|
13
|
-
:clean => false
|
13
|
+
:clean => false,
|
14
|
+
:proxy => nil
|
14
15
|
}
|
15
16
|
optparse = OptionParser.new do |opts|
|
16
17
|
opts.on("-h", "--help", "Display this message") do
|
@@ -38,6 +39,9 @@ module Sensu
|
|
38
39
|
opts.on("-c", "--clean", "Clean up (remove) other installed versions of the plugin(s) and/or extension(s)") do
|
39
40
|
options[:clean] = true
|
40
41
|
end
|
42
|
+
opts.on("-x", "--proxy PROXY", "Install Sensu plugins and extensions via a PROXY URL") do |proxy|
|
43
|
+
options[:proxy] = proxy
|
44
|
+
end
|
41
45
|
end
|
42
46
|
optparse.parse!(arguments)
|
43
47
|
options
|
@@ -70,6 +74,7 @@ module Sensu
|
|
70
74
|
gem_command << " --no-ri --no-rdoc"
|
71
75
|
gem_command << " --verbose" if options[:verbose]
|
72
76
|
gem_command << " --source #{options[:source]}" if options[:source]
|
77
|
+
gem_command << " --http-proxy #{options[:proxy]}" if options[:proxy]
|
73
78
|
log gem_command if options[:verbose]
|
74
79
|
unless system(gem_command)
|
75
80
|
log "failed to install Sensu gem '#{gem_name}'"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "sensu/api/routes"
|
2
|
+
require "sensu/api/utilities/filter_response_content"
|
2
3
|
|
3
4
|
gem "em-http-server", "0.1.8"
|
4
5
|
|
@@ -9,6 +10,7 @@ module Sensu
|
|
9
10
|
module API
|
10
11
|
class HTTPHandler < EM::HttpServer::Server
|
11
12
|
include Routes
|
13
|
+
include Utilities::FilterResponseContent
|
12
14
|
|
13
15
|
attr_accessor :logger, :settings, :redis, :transport
|
14
16
|
|
@@ -19,6 +21,7 @@ module Sensu
|
|
19
21
|
# @result [Hash]
|
20
22
|
def request_details
|
21
23
|
return @request_details if @request_details
|
24
|
+
@request_start_time = Time.now.to_f
|
22
25
|
_, remote_address = Socket.unpack_sockaddr_in(get_peername)
|
23
26
|
@request_details = {
|
24
27
|
:remote_address => remote_address,
|
@@ -40,12 +43,14 @@ module Sensu
|
|
40
43
|
@logger.debug("api request", request_details)
|
41
44
|
end
|
42
45
|
|
43
|
-
# Log the HTTP response.
|
46
|
+
# Log the HTTP response. This method calculates the
|
47
|
+
# request/response time.
|
44
48
|
def log_response
|
45
49
|
@logger.info("api response", {
|
46
50
|
:request => request_details,
|
47
51
|
:status => @response.status,
|
48
|
-
:content_length => @response.content.to_s.bytesize
|
52
|
+
:content_length => @response.content.to_s.bytesize,
|
53
|
+
:time => (Time.now.to_f - @request_start_time).round(3)
|
49
54
|
})
|
50
55
|
end
|
51
56
|
|
@@ -61,13 +66,20 @@ module Sensu
|
|
61
66
|
|
62
67
|
# Parse the HTTP request query string for parameters. This
|
63
68
|
# method creates `@params`, a hash of parsed query parameters,
|
64
|
-
# used by the API routes.
|
69
|
+
# used by the API routes. This method also creates
|
70
|
+
# `@filter_params`, a hash of parsed response content filter
|
71
|
+
# parameters.
|
65
72
|
def parse_parameters
|
66
73
|
@params = {}
|
67
74
|
if @http_query_string
|
68
75
|
@http_query_string.split("&").each do |pair|
|
69
76
|
key, value = pair.split("=")
|
70
77
|
@params[key.to_sym] = value
|
78
|
+
if key.start_with?("filter.")
|
79
|
+
filter_param = key.sub(/^filter\./, "")
|
80
|
+
@filter_params ||= {}
|
81
|
+
@filter_params[filter_param] = value
|
82
|
+
end
|
71
83
|
end
|
72
84
|
end
|
73
85
|
end
|
@@ -166,13 +178,17 @@ module Sensu
|
|
166
178
|
# Respond to an HTTP request. The routes set `@response_status`,
|
167
179
|
# `@response_status_string`, and `@response_content`
|
168
180
|
# appropriately. The HTTP response status defaults to `200` with
|
169
|
-
# the status string `OK`.
|
170
|
-
#
|
171
|
-
#
|
181
|
+
# the status string `OK`. If filter params were provided,
|
182
|
+
# `@response_content` is filtered (mutated). The Sensu API only
|
183
|
+
# returns JSON response content, `@response_content` is assumed
|
184
|
+
# to be a Ruby object that can be serialized as JSON.
|
172
185
|
def respond
|
173
186
|
@response.status = @response_status || 200
|
174
187
|
@response.status_string = @response_status_string || "OK"
|
175
188
|
if @response_content && @http_request_method != HEAD_METHOD
|
189
|
+
if @http_request_method == GET_METHOD && @filter_params
|
190
|
+
filter_response_content!
|
191
|
+
end
|
176
192
|
@response.content_type "application/json"
|
177
193
|
@response.content = Sensu::JSON.dump(@response_content)
|
178
194
|
end
|
@@ -281,6 +297,14 @@ module Sensu
|
|
281
297
|
respond
|
282
298
|
end
|
283
299
|
|
300
|
+
# Respond to the HTTP request with a `405` (Method Not Allowed) response.
|
301
|
+
def method_not_allowed!(allowed_http_methods=[])
|
302
|
+
@response.headers["Allow"] = allowed_http_methods.join(", ")
|
303
|
+
@response_status = 405
|
304
|
+
@response_status_string = "Method Not Allowed"
|
305
|
+
respond
|
306
|
+
end
|
307
|
+
|
284
308
|
# Respond to the HTTP request with a `412` (Precondition Failed)
|
285
309
|
# response.
|
286
310
|
def precondition_failed!
|
@@ -297,25 +321,63 @@ module Sensu
|
|
297
321
|
respond
|
298
322
|
end
|
299
323
|
|
324
|
+
# Determine the allowed HTTP methods for a route. The route
|
325
|
+
# regular expressions and associated route method calls are
|
326
|
+
# provided by `ROUTES`. This method returns an array of HTTP
|
327
|
+
# methods that have a route that matches the HTTP request URI.
|
328
|
+
#
|
329
|
+
# @return [Array]
|
330
|
+
def allowed_http_methods?
|
331
|
+
ROUTES.map { |http_method, routes|
|
332
|
+
match = routes.detect do |route|
|
333
|
+
@http_request_uri =~ route[0]
|
334
|
+
end
|
335
|
+
match ? http_method : nil
|
336
|
+
}.flatten.compact
|
337
|
+
end
|
338
|
+
|
339
|
+
# Determine the route method for the HTTP request method and
|
340
|
+
# URI. The route regular expressions and associated route method
|
341
|
+
# calls are provided by `ROUTES`. This method will return the
|
342
|
+
# first route method name (Ruby symbol) that has matching URI
|
343
|
+
# regular expression. If an HTTP method is not supported, or
|
344
|
+
# there is not a matching regular expression, `nil` will be
|
345
|
+
# returned.
|
346
|
+
#
|
347
|
+
# @return [Symbol]
|
348
|
+
def determine_route_method
|
349
|
+
if ROUTES.has_key?(@http_request_method)
|
350
|
+
route = ROUTES[@http_request_method].detect do |route|
|
351
|
+
@http_request_uri =~ route[0]
|
352
|
+
end
|
353
|
+
route ? route[1] : nil
|
354
|
+
else
|
355
|
+
nil
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
300
359
|
# Route the HTTP request. OPTIONS HTTP requests will always
|
301
|
-
# return a `200` with no response content.
|
302
|
-
#
|
303
|
-
#
|
304
|
-
#
|
360
|
+
# return a `200` with no response content. This method uses
|
361
|
+
# `determine_route_method()` to determine the symbolized route
|
362
|
+
# method to send/call. If a route method does not exist for the
|
363
|
+
# HTTP request method and URI, this method uses
|
364
|
+
# `allowed_http_methods?()` to determine if a 404 (Not Found) or
|
365
|
+
# 405 (Method Not Allowed) HTTP response should be used.
|
305
366
|
def route_request
|
306
367
|
if @http_request_method == OPTIONS_METHOD
|
307
368
|
respond
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
unless route.nil?
|
313
|
-
send(route[1])
|
369
|
+
else
|
370
|
+
route_method = determine_route_method
|
371
|
+
if route_method
|
372
|
+
send(route_method)
|
314
373
|
else
|
315
|
-
|
374
|
+
allowed_http_methods = allowed_http_methods?
|
375
|
+
if allowed_http_methods.empty?
|
376
|
+
not_found!
|
377
|
+
else
|
378
|
+
method_not_allowed!(allowed_http_methods)
|
379
|
+
end
|
316
380
|
end
|
317
|
-
else
|
318
|
-
not_found!
|
319
381
|
end
|
320
382
|
end
|
321
383
|
|
data/lib/sensu/api/routes.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "sensu/api/routes/settings"
|
1
2
|
require "sensu/api/routes/info"
|
2
3
|
require "sensu/api/routes/health"
|
3
4
|
require "sensu/api/routes/clients"
|
@@ -13,6 +14,7 @@ require "sensu/api/routes/silenced"
|
|
13
14
|
module Sensu
|
14
15
|
module API
|
15
16
|
module Routes
|
17
|
+
include Settings
|
16
18
|
include Info
|
17
19
|
include Health
|
18
20
|
include Clients
|
@@ -32,6 +34,7 @@ module Sensu
|
|
32
34
|
OPTIONS_METHOD = "OPTIONS".freeze
|
33
35
|
|
34
36
|
GET_ROUTES = [
|
37
|
+
[SETTINGS_URI, :get_settings],
|
35
38
|
[INFO_URI, :get_info],
|
36
39
|
[HEALTH_URI, :get_health],
|
37
40
|
[CLIENTS_URI, :get_clients],
|
@@ -113,8 +113,11 @@ module Sensu
|
|
113
113
|
# DELETE /clients/:client_name
|
114
114
|
def delete_client
|
115
115
|
client_name = parse_uri(CLIENT_URI).first
|
116
|
-
|
116
|
+
client_key = "client:#{client_name}"
|
117
|
+
signature_key = "#{client_key}:signature"
|
118
|
+
@redis.get(client_key) do |client_json|
|
117
119
|
unless client_json.nil?
|
120
|
+
@redis.set(signature_key, "invalidated") if @params[:invalidate]
|
118
121
|
@redis.hgetall("events:#{client_name}") do |events|
|
119
122
|
events.each do |check_name, event_json|
|
120
123
|
resolve_event(event_json)
|
@@ -125,8 +128,13 @@ module Sensu
|
|
125
128
|
if events.empty? || attempts == 5
|
126
129
|
@logger.info("deleting client from registry", :client_name => client_name)
|
127
130
|
@redis.srem("clients", client_name) do
|
128
|
-
@redis.del(
|
129
|
-
@
|
131
|
+
@redis.del(client_key)
|
132
|
+
invalidate_expire = integer_parameter(@params[:invalidate_expire])
|
133
|
+
if @params[:invalidate] && invalidate_expire
|
134
|
+
@redis.expire(signature_key, invalidate_expire)
|
135
|
+
else
|
136
|
+
@redis.del(signature_key)
|
137
|
+
end
|
130
138
|
@redis.del("events:#{client_name}")
|
131
139
|
@redis.smembers("result:#{client_name}") do |checks|
|
132
140
|
checks.each do |check_name|
|
@@ -26,7 +26,11 @@ module Sensu
|
|
26
26
|
:reason => data[:reason],
|
27
27
|
:creator => data[:creator]
|
28
28
|
}
|
29
|
-
|
29
|
+
if check[:proxy_requests]
|
30
|
+
publish_proxy_check_requests(check)
|
31
|
+
else
|
32
|
+
publish_check_request(check)
|
33
|
+
end
|
30
34
|
@response_content = {:issued => Time.now.to_i}
|
31
35
|
accepted!
|
32
36
|
else
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "sensu/utilities"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Settings
|
7
|
+
include Utilities
|
8
|
+
|
9
|
+
SETTINGS_URI = /^\/settings$/
|
10
|
+
|
11
|
+
# GET /settings
|
12
|
+
def get_settings
|
13
|
+
if @params[:redacted] == "false"
|
14
|
+
@response_content = @settings.to_hash
|
15
|
+
else
|
16
|
+
@response_content = redact_sensitive(@settings.to_hash)
|
17
|
+
end
|
18
|
+
respond
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "sensu/utilities"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Utilities
|
6
|
+
module FilterResponseContent
|
7
|
+
include Sensu::Utilities
|
8
|
+
|
9
|
+
# Create a nested hash from a dot notation key and value.
|
10
|
+
#
|
11
|
+
# @param dot_notation [String]
|
12
|
+
# @param value [Object]
|
13
|
+
# @return [Hash]
|
14
|
+
def dot_notation_to_hash(dot_notation, value)
|
15
|
+
hash = {}
|
16
|
+
dot_notation.split(".").reverse.each do |key|
|
17
|
+
if hash.empty?
|
18
|
+
hash = {key.to_sym => value}
|
19
|
+
else
|
20
|
+
hash = {key.to_sym => hash}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
|
26
|
+
# Filter the response content if filter parameters have been
|
27
|
+
# provided. This method mutates `@response_content`, only
|
28
|
+
# retaining array items that match the attributes provided via
|
29
|
+
# filter parameters.
|
30
|
+
def filter_response_content!
|
31
|
+
if @response_content.is_a?(Array) && !@filter_params.empty?
|
32
|
+
attributes = {}
|
33
|
+
@filter_params.each do |key, value|
|
34
|
+
attributes = deep_merge(attributes, dot_notation_to_hash(key, value))
|
35
|
+
end
|
36
|
+
@response_content.select! do |object|
|
37
|
+
attributes_match?(object, attributes, false)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,7 +1,11 @@
|
|
1
|
+
require "sensu/utilities"
|
2
|
+
|
1
3
|
module Sensu
|
2
4
|
module API
|
3
5
|
module Utilities
|
4
6
|
module PublishCheckRequest
|
7
|
+
include Sensu::Utilities
|
8
|
+
|
5
9
|
# Determine the Sensu Transport publish options for a
|
6
10
|
# subscription. If a subscription begins with a Transport pipe
|
7
11
|
# type, either "direct:" or "roundrobin:", the subscription uses
|
@@ -33,7 +37,10 @@ module Sensu
|
|
33
37
|
#
|
34
38
|
# @param check [Hash] definition.
|
35
39
|
def publish_check_request(check)
|
36
|
-
payload = check.
|
40
|
+
payload = check.reject do |key, value|
|
41
|
+
[:subscribers, :interval].include?(key)
|
42
|
+
end
|
43
|
+
payload[:issued] = Time.now.to_i
|
37
44
|
@logger.info("publishing check request", {
|
38
45
|
:payload => payload,
|
39
46
|
:subscribers => check[:subscribers]
|
@@ -51,6 +58,49 @@ module Sensu
|
|
51
58
|
end
|
52
59
|
end
|
53
60
|
end
|
61
|
+
|
62
|
+
# Create and publish one or more proxy check requests. This
|
63
|
+
# method iterates through the Sensu client registry for clients
|
64
|
+
# that matched provided proxy request client attributes. A proxy
|
65
|
+
# check request is created for each client in the registry that
|
66
|
+
# matches the proxy request client attributes. Proxy check
|
67
|
+
# requests have their client tokens subsituted by the associated
|
68
|
+
# client attributes values. The check requests are published to
|
69
|
+
# the Transport via `publish_check_request()`.
|
70
|
+
#
|
71
|
+
# @param check [Hash] definition.
|
72
|
+
def publish_proxy_check_requests(check)
|
73
|
+
client_attributes = check[:proxy_requests][:client_attributes]
|
74
|
+
unless client_attributes.empty?
|
75
|
+
@redis.smembers("clients") do |clients|
|
76
|
+
clients.each do |client_name|
|
77
|
+
@redis.get("client:#{client_name}") do |client_json|
|
78
|
+
unless client_json.nil?
|
79
|
+
client = Sensu::JSON.load(client_json)
|
80
|
+
if attributes_match?(client, client_attributes)
|
81
|
+
@logger.debug("creating a proxy check request", {
|
82
|
+
:client => client,
|
83
|
+
:check => check
|
84
|
+
})
|
85
|
+
proxy_check, unmatched_tokens = object_substitute_tokens(check.dup, client)
|
86
|
+
if unmatched_tokens.empty?
|
87
|
+
proxy_check[:source] ||= client[:name]
|
88
|
+
publish_check_request(proxy_check)
|
89
|
+
else
|
90
|
+
@logger.warn("failed to publish a proxy check request", {
|
91
|
+
:reason => "unmatched client tokens",
|
92
|
+
:unmatched_tokens => unmatched_tokens,
|
93
|
+
:client => client,
|
94
|
+
:check => check
|
95
|
+
})
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
54
104
|
end
|
55
105
|
end
|
56
106
|
end
|
data/lib/sensu/cli.rb
CHANGED
@@ -11,6 +11,12 @@ module Sensu
|
|
11
11
|
# @return [Hash] options
|
12
12
|
def self.read(arguments=ARGV)
|
13
13
|
options = {}
|
14
|
+
if File.exist?("/etc/sensu/config.json")
|
15
|
+
options[:config_file] = "/etc/sensu/config.json"
|
16
|
+
end
|
17
|
+
if Dir.exist?("/etc/sensu/conf.d")
|
18
|
+
options[:config_dirs] = ["/etc/sensu/conf.d"]
|
19
|
+
end
|
14
20
|
optparse = OptionParser.new do |opts|
|
15
21
|
opts.on("-h", "--help", "Display this message") do
|
16
22
|
puts opts
|
@@ -20,10 +26,10 @@ module Sensu
|
|
20
26
|
puts VERSION
|
21
27
|
exit
|
22
28
|
end
|
23
|
-
opts.on("-c", "--config FILE", "Sensu JSON config FILE") do |file|
|
29
|
+
opts.on("-c", "--config FILE", "Sensu JSON config FILE. Default: /etc/sensu/config.json (if exists)") do |file|
|
24
30
|
options[:config_file] = file
|
25
31
|
end
|
26
|
-
opts.on("-d", "--config_dir DIR[,DIR]", "DIR or comma-delimited DIR list for Sensu JSON config files") do |dir|
|
32
|
+
opts.on("-d", "--config_dir DIR[,DIR]", "DIR or comma-delimited DIR list for Sensu JSON config files. Default: /etc/sensu/conf.d (if exists)") do |dir|
|
27
33
|
options[:config_dirs] = dir.split(",")
|
28
34
|
end
|
29
35
|
opts.on("--validate_config", "Validate the compiled configuration and exit") do
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/daemon.rb
CHANGED
@@ -4,12 +4,12 @@ gem "eventmachine", "1.2.2"
|
|
4
4
|
|
5
5
|
gem "sensu-json", "2.1.0"
|
6
6
|
gem "sensu-logger", "1.2.1"
|
7
|
-
gem "sensu-settings", "
|
7
|
+
gem "sensu-settings", "10.0.0"
|
8
8
|
gem "sensu-extension", "1.5.1"
|
9
|
-
gem "sensu-extensions", "1.
|
9
|
+
gem "sensu-extensions", "1.9.0"
|
10
10
|
gem "sensu-transport", "7.0.2"
|
11
11
|
gem "sensu-spawn", "2.2.1"
|
12
|
-
gem "sensu-redis", "2.1.
|
12
|
+
gem "sensu-redis", "2.1.1"
|
13
13
|
|
14
14
|
require "time"
|
15
15
|
require "uri"
|
@@ -142,6 +142,7 @@ module Sensu
|
|
142
142
|
@logger.fatal("SENSU NOT RUNNING!")
|
143
143
|
exit 2
|
144
144
|
end
|
145
|
+
@settings.set_env!
|
145
146
|
end
|
146
147
|
|
147
148
|
# Load Sensu extensions and log any notices. Set the logger and
|
data/lib/sensu/server/process.rb
CHANGED
@@ -11,7 +11,9 @@ module Sensu
|
|
11
11
|
include Mutate
|
12
12
|
include Handle
|
13
13
|
|
14
|
-
attr_reader :
|
14
|
+
attr_reader :tasks, :in_progress
|
15
|
+
|
16
|
+
TASKS = ["check_request_publisher", "client_monitor", "check_result_monitor"]
|
15
17
|
|
16
18
|
STANDARD_CHECK_TYPE = "standard".freeze
|
17
19
|
|
@@ -34,14 +36,17 @@ module Sensu
|
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
37
|
-
# Override Daemon initialize() to support Sensu server
|
38
|
-
#
|
39
|
+
# Override Daemon initialize() to support Sensu server tasks and
|
40
|
+
# the handling event count.
|
39
41
|
#
|
40
42
|
# @param options [Hash]
|
41
43
|
def initialize(options={})
|
42
44
|
super
|
43
|
-
@
|
44
|
-
@timers[:
|
45
|
+
@tasks = []
|
46
|
+
@timers[:tasks] = {}
|
47
|
+
TASKS.each do |task|
|
48
|
+
@timers[:tasks][task.to_sym] = []
|
49
|
+
end
|
45
50
|
@in_progress = Hash.new(0)
|
46
51
|
end
|
47
52
|
|
@@ -150,7 +155,7 @@ module Sensu
|
|
150
155
|
if (signature.nil? || signature.empty?) && client[:signature]
|
151
156
|
@redis.set(signature_key, client[:signature])
|
152
157
|
end
|
153
|
-
if signature.nil? || signature.empty? ||
|
158
|
+
if signature.nil? || signature.empty? || client[:signature] == signature
|
154
159
|
@redis.multi
|
155
160
|
@redis.set(client_key, Sensu::JSON.dump(client))
|
156
161
|
@redis.sadd("clients", client[:name])
|
@@ -429,18 +434,11 @@ module Sensu
|
|
429
434
|
# @return [TrueClass, FalseClass]
|
430
435
|
def check_flapping?(stored_event, check)
|
431
436
|
if check.has_key?(:low_flap_threshold) && check.has_key?(:high_flap_threshold)
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
check[:total_state_change] > check[:low_flap_threshold]
|
436
|
-
else
|
437
|
-
check[:total_state_change] >= check[:high_flap_threshold]
|
438
|
-
end
|
437
|
+
was_flapping = stored_event && stored_event[:action] == EVENT_FLAPPING_ACTION
|
438
|
+
if was_flapping
|
439
|
+
check[:total_state_change] > check[:low_flap_threshold]
|
439
440
|
else
|
440
|
-
|
441
|
-
details[:client] = stored_event[:client] if stored_event
|
442
|
-
@logger.error("invalid check flap thresholds", details)
|
443
|
-
false
|
441
|
+
check[:total_state_change] >= check[:high_flap_threshold]
|
444
442
|
end
|
445
443
|
else
|
446
444
|
false
|
@@ -607,7 +605,10 @@ module Sensu
|
|
607
605
|
# `client_key` as the client name. Dynamically create client
|
608
606
|
# data can be updated using the API (POST /clients/:client). If
|
609
607
|
# a client does exist and it has a client signature, the check
|
610
|
-
# result must have a matching signature or it is discarded.
|
608
|
+
# result must have a matching signature or it is discarded. If
|
609
|
+
# the client does not exist, but a client signature exists, the
|
610
|
+
# check result must have a matching signature or it is
|
611
|
+
# discarded.
|
611
612
|
#
|
612
613
|
# @param result [Hash] data.
|
613
614
|
# @yield [client] callback/block to be called with client data,
|
@@ -633,10 +634,20 @@ module Sensu
|
|
633
634
|
yield(client)
|
634
635
|
end
|
635
636
|
else
|
636
|
-
client
|
637
|
-
|
638
|
-
|
639
|
-
|
637
|
+
@redis.get("client:#{client_key}:signature") do |signature|
|
638
|
+
if signature.nil? || signature.empty? || result[:signature] == signature
|
639
|
+
client = create_client(client_key)
|
640
|
+
client[:type] = "proxy" if result[:check][:source]
|
641
|
+
update_client_registry(client) do
|
642
|
+
yield(client)
|
643
|
+
end
|
644
|
+
else
|
645
|
+
@logger.warn("invalid check result signature", {
|
646
|
+
:result => result,
|
647
|
+
:signature => signature
|
648
|
+
})
|
649
|
+
yield(nil)
|
650
|
+
end
|
640
651
|
end
|
641
652
|
end
|
642
653
|
end
|
@@ -843,18 +854,16 @@ module Sensu
|
|
843
854
|
# creats an EventMachine timer for the request. This method will
|
844
855
|
# be called after every check cron request for subsequent
|
845
856
|
# requests. The timer is stored in the timer hash under
|
846
|
-
# `:
|
847
|
-
#
|
848
|
-
#
|
849
|
-
# the request is published, to stop the timer hash from growing
|
850
|
-
# infinitely.
|
857
|
+
# `:tasks`, so it can be cancelled etc. The check cron request
|
858
|
+
# timer object is removed from the timer hash after the request
|
859
|
+
# is published, to stop the timer hash from growing infinitely.
|
851
860
|
#
|
852
861
|
# @param check [Hash] definition.
|
853
862
|
def schedule_check_cron_request(check)
|
854
863
|
cron_time = determine_check_cron_time(check)
|
855
|
-
@timers[:
|
864
|
+
@timers[:tasks][:check_request_publisher] << EM::Timer.new(cron_time) do |timer|
|
856
865
|
create_check_request_proc(check).call
|
857
|
-
@timers[:
|
866
|
+
@timers[:tasks][:check_request_publisher].delete(timer)
|
858
867
|
schedule_check_cron_request(check)
|
859
868
|
end
|
860
869
|
end
|
@@ -874,17 +883,16 @@ module Sensu
|
|
874
883
|
# using an intial calculated request splay EventMachine timer
|
875
884
|
# and an EventMachine periodic timer for subsequent check
|
876
885
|
# requests. The timers are stored in the timers hash under
|
877
|
-
# `:
|
878
|
-
# Sensu server leader, so they can be cancelled etc.
|
886
|
+
# `:tasks`, so they can be cancelled etc.
|
879
887
|
#
|
880
888
|
# @param check [Hash] definition.
|
881
889
|
def schedule_check_interval_requests(check)
|
882
890
|
request_splay = testing? ? 0 : calculate_check_request_splay(check)
|
883
891
|
interval = testing? ? 0.5 : check[:interval]
|
884
|
-
@timers[:
|
892
|
+
@timers[:tasks][:check_request_publisher] << EM::Timer.new(request_splay) do
|
885
893
|
create_check_request = create_check_request_proc(check)
|
886
894
|
create_check_request.call
|
887
|
-
@timers[:
|
895
|
+
@timers[:tasks][:check_request_publisher] << EM::PeriodicTimer.new(interval, &create_check_request)
|
888
896
|
end
|
889
897
|
end
|
890
898
|
|
@@ -1041,10 +1049,10 @@ module Sensu
|
|
1041
1049
|
|
1042
1050
|
# Set up the client monitor, a periodic timer to run
|
1043
1051
|
# `determine_stale_clients()` every 30 seconds. The timer is
|
1044
|
-
# stored in the timers hash under `:
|
1052
|
+
# stored in the timers hash under `:tasks`.
|
1045
1053
|
def setup_client_monitor
|
1046
1054
|
@logger.debug("monitoring client keepalives")
|
1047
|
-
@timers[:
|
1055
|
+
@timers[:tasks][:client_monitor] << EM::PeriodicTimer.new(30) do
|
1048
1056
|
determine_stale_clients
|
1049
1057
|
end
|
1050
1058
|
end
|
@@ -1087,31 +1095,21 @@ module Sensu
|
|
1087
1095
|
|
1088
1096
|
# Set up the check result monitor, a periodic timer to run
|
1089
1097
|
# `determine_stale_check_results()` every 30 seconds. The timer
|
1090
|
-
# is stored in the timers hash under `:
|
1098
|
+
# is stored in the timers hash under `:tasks`.
|
1091
1099
|
def setup_check_result_monitor(interval = 30)
|
1092
1100
|
@logger.debug("monitoring check results")
|
1093
|
-
@timers[:
|
1101
|
+
@timers[:tasks][:check_result_monitor] << EM::PeriodicTimer.new(interval) do
|
1094
1102
|
determine_stale_check_results(interval)
|
1095
1103
|
end
|
1096
1104
|
end
|
1097
1105
|
|
1098
|
-
# Set up the leader duties, tasks only performed by a single
|
1099
|
-
# Sensu server at a time. The duties include publishing check
|
1100
|
-
# requests, monitoring for stale clients, and pruning check
|
1101
|
-
# result aggregations.
|
1102
|
-
def leader_duties
|
1103
|
-
setup_check_request_publisher
|
1104
|
-
setup_client_monitor
|
1105
|
-
setup_check_result_monitor
|
1106
|
-
end
|
1107
|
-
|
1108
1106
|
# Create a lock timestamp (integer), current time including
|
1109
|
-
# milliseconds. This method is used by Sensu server
|
1107
|
+
# milliseconds. This method is used by Sensu server task
|
1110
1108
|
# election.
|
1111
1109
|
#
|
1112
1110
|
# @return [Integer]
|
1113
1111
|
def create_lock_timestamp
|
1114
|
-
(Time.now.to_f *
|
1112
|
+
(Time.now.to_f * 10000000).to_i
|
1115
1113
|
end
|
1116
1114
|
|
1117
1115
|
# Create/return the unique Sensu server ID for the current
|
@@ -1122,122 +1120,168 @@ module Sensu
|
|
1122
1120
|
@server_id ||= random_uuid
|
1123
1121
|
end
|
1124
1122
|
|
1125
|
-
#
|
1126
|
-
#
|
1127
|
-
#
|
1128
|
-
#
|
1129
|
-
#
|
1130
|
-
#
|
1131
|
-
#
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1123
|
+
# Setup a Sensu server task. Unless the current process is
|
1124
|
+
# already responsible for the task, this method sets the tasks
|
1125
|
+
# server ID stored in Redis to the unique random server ID for
|
1126
|
+
# the process. If the tasks server ID is successfully updated,
|
1127
|
+
# the task is added to `@tasks` for tracking purposes and the
|
1128
|
+
# task setup method is called.
|
1129
|
+
#
|
1130
|
+
# @param task [String]
|
1131
|
+
# @yield callback/block called after setting up the task.
|
1132
|
+
def setup_task(task)
|
1133
|
+
unless @tasks.include?(task)
|
1134
|
+
@redis.set("task:#{task}:server", server_id) do
|
1135
|
+
@logger.info("i am now responsible for a server task", :task => task)
|
1136
|
+
@tasks << task
|
1137
|
+
self.send("setup_#{task}".to_sym)
|
1138
|
+
yield if block_given?
|
1138
1139
|
end
|
1139
1140
|
else
|
1140
|
-
@logger.debug("i am already
|
1141
|
+
@logger.debug("i am already responsible for a server task", :task => task)
|
1141
1142
|
end
|
1142
1143
|
end
|
1143
1144
|
|
1144
|
-
#
|
1145
|
-
#
|
1146
|
-
#
|
1147
|
-
#
|
1148
|
-
#
|
1149
|
-
#
|
1150
|
-
#
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1145
|
+
# Relinquish a Sensu server task. This method cancels and
|
1146
|
+
# clears the associated task timers, those with references
|
1147
|
+
# stored in the timers hash under `:tasks`, and removes the task
|
1148
|
+
# from `@tasks`. The task server ID and lock are not removed
|
1149
|
+
# from Redis, as they will be updated when another server takes
|
1150
|
+
# reponsibility for the task, this method does not need to
|
1151
|
+
# handle Redis connectivity issues.
|
1152
|
+
#
|
1153
|
+
# @param task [String]
|
1154
|
+
def relinquish_task(task)
|
1155
|
+
if @tasks.include?(task)
|
1156
|
+
@logger.warn("relinquishing server task", :task => task)
|
1157
|
+
@timers[:tasks][task.to_sym].each do |timer|
|
1155
1158
|
timer.cancel
|
1156
1159
|
end
|
1157
|
-
@timers[:
|
1158
|
-
@
|
1160
|
+
@timers[:tasks][task.to_sym].clear
|
1161
|
+
@tasks.delete(task)
|
1159
1162
|
else
|
1160
|
-
@logger.debug("not currently
|
1163
|
+
@logger.debug("not currently responsible for a server task", :task => task)
|
1161
1164
|
end
|
1162
1165
|
end
|
1163
1166
|
|
1164
|
-
#
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1167
|
+
# Relinquish all Sensu server tasks, if any.
|
1168
|
+
def relinquish_tasks
|
1169
|
+
unless @tasks.empty?
|
1170
|
+
@tasks.dup.each do |task|
|
1171
|
+
relinquish_task(task)
|
1172
|
+
end
|
1173
|
+
else
|
1174
|
+
@logger.debug("not currently responsible for a server task")
|
1175
|
+
end
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
# Updates a Sensu server task lock timestamp. The current task
|
1179
|
+
# server ID is retrieved from Redis and compared with the server
|
1180
|
+
# ID of the current process to determine if it is still
|
1181
|
+
# responsible for the task. If the current process is still
|
1182
|
+
# responsible, the task lock timestamp is updated. If the
|
1183
|
+
# current process is no longer responsible, `relinquish_task()`
|
1184
|
+
# is called for cleanup.
|
1185
|
+
#
|
1186
|
+
# @param task [String]
|
1187
|
+
def update_task_lock(task)
|
1188
|
+
@redis.get("task:#{task}:server") do |current_server_id|
|
1189
|
+
if current_server_id == server_id
|
1190
|
+
@redis.set("lock:task:#{task}", create_lock_timestamp) do
|
1191
|
+
@logger.debug("updated task lock timestamp", :task => task)
|
1177
1192
|
end
|
1178
1193
|
else
|
1179
|
-
@logger.warn("another sensu server
|
1180
|
-
|
1194
|
+
@logger.warn("another sensu server is responsible for the task", :task => task)
|
1195
|
+
relinquish_task(task)
|
1181
1196
|
end
|
1182
1197
|
end
|
1183
1198
|
end
|
1184
1199
|
|
1185
|
-
#
|
1186
|
-
#
|
1187
|
-
#
|
1188
|
-
#
|
1189
|
-
#
|
1190
|
-
#
|
1191
|
-
#
|
1192
|
-
#
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
+
# Set up a Sensu server task lock updater. This method uses a
|
1201
|
+
# periodic timer to update a task lock timestamp in Redis, every
|
1202
|
+
# 10 seconds. If the current process fails to keep the lock
|
1203
|
+
# timestamp updated for a task that it is responsible for,
|
1204
|
+
# another Sensu server will claim responsibility. This method is
|
1205
|
+
# called after task setup.
|
1206
|
+
#
|
1207
|
+
# @param task [String]
|
1208
|
+
def setup_task_lock_updater(task)
|
1209
|
+
@timers[:run] << EM::PeriodicTimer.new(10) do
|
1210
|
+
update_task_lock(task)
|
1211
|
+
end
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
# Request a Sensu server task election, a process to determine
|
1215
|
+
# if the current process is to be responsible for the task. A
|
1216
|
+
# Redis key/value is used as a central lock, using the "SETNX"
|
1217
|
+
# Redis command to set the key/value if it does not exist, using
|
1218
|
+
# a timestamp for the value. If the current process was able to
|
1219
|
+
# create the key/value, it is elected, and is then responsible
|
1220
|
+
# for the task. If the current process was not able to create
|
1221
|
+
# the key/value, but the current timestamp value is equal to or
|
1222
|
+
# over 30 seconds ago, the "GETSET" Redis command is used to set
|
1223
|
+
# a new timestamp and fetch the previous value to compare them,
|
1224
|
+
# to determine if it was set by the current process. If the
|
1225
|
+
# current process is able to set the timestamp value, it is
|
1226
|
+
# elected. If elected, the current process sets up the task and
|
1227
|
+
# the associated task lock updater.
|
1228
|
+
#
|
1229
|
+
# @param task [String]
|
1230
|
+
# @yield callback/block called either after being elected and
|
1231
|
+
# setting up the task, or after failing to be elected.
|
1232
|
+
def request_task_election(task, &callback)
|
1233
|
+
@redis.setnx("lock:task:#{task}", create_lock_timestamp) do |created|
|
1200
1234
|
if created
|
1201
|
-
|
1235
|
+
setup_task(task, &callback)
|
1236
|
+
setup_task_lock_updater(task)
|
1202
1237
|
else
|
1203
|
-
@redis.get("lock:
|
1238
|
+
@redis.get("lock:task:#{task}") do |current_lock_timestamp|
|
1204
1239
|
new_lock_timestamp = create_lock_timestamp
|
1205
|
-
if new_lock_timestamp - current_lock_timestamp.to_i >=
|
1206
|
-
@redis.getset("lock:
|
1240
|
+
if new_lock_timestamp - current_lock_timestamp.to_i >= 300000000
|
1241
|
+
@redis.getset("lock:task:#{task}", new_lock_timestamp) do |previous_lock_timestamp|
|
1207
1242
|
if previous_lock_timestamp == current_lock_timestamp
|
1208
|
-
|
1243
|
+
setup_task(task, &callback)
|
1244
|
+
setup_task_lock_updater(task)
|
1209
1245
|
end
|
1210
1246
|
end
|
1247
|
+
else
|
1248
|
+
yield if block_given?
|
1211
1249
|
end
|
1212
1250
|
end
|
1213
1251
|
end
|
1214
1252
|
end
|
1215
1253
|
end
|
1216
1254
|
|
1217
|
-
#
|
1218
|
-
#
|
1219
|
-
#
|
1220
|
-
#
|
1221
|
-
#
|
1222
|
-
#
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
if
|
1229
|
-
|
1255
|
+
# Request Sensu server task elections. The task list is ordered
|
1256
|
+
# by prioity. This method works through the task list serially,
|
1257
|
+
# increasing the election request delay as the current process
|
1258
|
+
# becomes responsible for one or more tasks, this is to improve
|
1259
|
+
# the initial distribution of tasks amongst Sensu servers.
|
1260
|
+
#
|
1261
|
+
# @param splay [Integer]
|
1262
|
+
def setup_task_elections(splay=10)
|
1263
|
+
tasks = TASKS.dup - @tasks
|
1264
|
+
next_task = Proc.new do
|
1265
|
+
task = tasks.shift
|
1266
|
+
if task
|
1267
|
+
delay = splay * @tasks.size
|
1268
|
+
@timers[:run] << EM::Timer.new(delay) do
|
1269
|
+
request_task_election(task, &next_task)
|
1270
|
+
end
|
1230
1271
|
else
|
1231
|
-
|
1272
|
+
@timers[:run] << EM::Timer.new(10) do
|
1273
|
+
setup_task_elections(splay)
|
1274
|
+
end
|
1232
1275
|
end
|
1233
1276
|
end
|
1277
|
+
next_task.call
|
1234
1278
|
end
|
1235
1279
|
|
1236
1280
|
# Update the Sensu server registry, stored in Redis. This method
|
1237
1281
|
# adds the local/current Sensu server info to the registry,
|
1238
|
-
# including its id, hostname, address,
|
1239
|
-
#
|
1240
|
-
#
|
1282
|
+
# including its id, hostname, address, its server tasks, and
|
1283
|
+
# some metrics. Sensu server registry entries expire in 30
|
1284
|
+
# seconds unless updated.
|
1241
1285
|
#
|
1242
1286
|
# @yield [success] passes success status to optional
|
1243
1287
|
# callback/block.
|
@@ -1250,13 +1294,19 @@ module Sensu
|
|
1250
1294
|
:id => server_id,
|
1251
1295
|
:hostname => system_hostname,
|
1252
1296
|
:address => system_address,
|
1253
|
-
:
|
1297
|
+
:tasks => @tasks,
|
1254
1298
|
:metrics => {
|
1255
1299
|
:cpu => {
|
1256
1300
|
:user => cpu_user,
|
1257
1301
|
:system => cpu_system
|
1258
1302
|
}
|
1259
1303
|
},
|
1304
|
+
:sensu => {
|
1305
|
+
:version => VERSION,
|
1306
|
+
:settings => {
|
1307
|
+
:hexdigest => @settings.hexdigest
|
1308
|
+
}
|
1309
|
+
},
|
1260
1310
|
:timestamp => Time.now.to_i
|
1261
1311
|
}
|
1262
1312
|
@redis.sadd("servers", server_id)
|
@@ -1304,13 +1354,13 @@ module Sensu
|
|
1304
1354
|
end
|
1305
1355
|
|
1306
1356
|
# Bootstrap the Sensu server process, setting up the keepalive
|
1307
|
-
# and check result consumers, and attemping to
|
1308
|
-
#
|
1309
|
-
#
|
1357
|
+
# and check result consumers, and attemping to carry out Sensu
|
1358
|
+
# server tasks. This method sets the process/daemon `@state` to
|
1359
|
+
# `:running`.
|
1310
1360
|
def bootstrap
|
1311
1361
|
setup_keepalives
|
1312
1362
|
setup_results
|
1313
|
-
|
1363
|
+
setup_task_elections
|
1314
1364
|
setup_server_registry_updater
|
1315
1365
|
@state = :running
|
1316
1366
|
end
|
@@ -1330,8 +1380,8 @@ module Sensu
|
|
1330
1380
|
# set to `:pausing`, to indicate that it's in progress. All run
|
1331
1381
|
# timers are cancelled, and the references are cleared. The
|
1332
1382
|
# Sensu server will unsubscribe from all transport
|
1333
|
-
# subscriptions,
|
1334
|
-
#
|
1383
|
+
# subscriptions, relinquish any Sensu server tasks, then set the
|
1384
|
+
# process/daemon `@state` to `:paused`.
|
1335
1385
|
def pause
|
1336
1386
|
unless @state == :pausing || @state == :paused
|
1337
1387
|
@state = :pausing
|
@@ -1340,7 +1390,7 @@ module Sensu
|
|
1340
1390
|
end
|
1341
1391
|
@timers[:run].clear
|
1342
1392
|
unsubscribe
|
1343
|
-
|
1393
|
+
relinquish_tasks
|
1344
1394
|
@state = :paused
|
1345
1395
|
end
|
1346
1396
|
end
|
data/lib/sensu/utilities.rb
CHANGED
@@ -259,9 +259,10 @@ module Sensu
|
|
259
259
|
#
|
260
260
|
# @param object [Hash]
|
261
261
|
# @param match_attributes [Object]
|
262
|
+
# @param support_eval [TrueClass, FalseClass]
|
262
263
|
# @param object_attributes [Object]
|
263
264
|
# @return [TrueClass, FalseClass]
|
264
|
-
def attributes_match?(object, match_attributes, object_attributes=nil)
|
265
|
+
def attributes_match?(object, match_attributes, support_eval=true, object_attributes=nil)
|
265
266
|
object_attributes ||= object
|
266
267
|
match_attributes.all? do |key, value_one|
|
267
268
|
value_two = object_attributes[key]
|
@@ -269,10 +270,10 @@ module Sensu
|
|
269
270
|
when value_one == value_two
|
270
271
|
true
|
271
272
|
when value_one.is_a?(Hash) && value_two.is_a?(Hash)
|
272
|
-
attributes_match?(object, value_one, value_two)
|
273
|
+
attributes_match?(object, value_one, support_eval, value_two)
|
273
274
|
when value_one.to_s == value_two.to_s
|
274
275
|
true
|
275
|
-
when value_one.is_a?(String) && value_one.start_with?(EVAL_PREFIX)
|
276
|
+
when value_one.is_a?(String) && value_one.start_with?(EVAL_PREFIX) && support_eval
|
276
277
|
eval_attribute_value(object, value_one, value_two)
|
277
278
|
else
|
278
279
|
false
|
data/sensu.gemspec
CHANGED
@@ -15,12 +15,12 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.add_dependency "eventmachine", "1.2.2"
|
16
16
|
s.add_dependency "sensu-json", "2.1.0"
|
17
17
|
s.add_dependency "sensu-logger", "1.2.1"
|
18
|
-
s.add_dependency "sensu-settings", "
|
18
|
+
s.add_dependency "sensu-settings", "10.0.0"
|
19
19
|
s.add_dependency "sensu-extension", "1.5.1"
|
20
|
-
s.add_dependency "sensu-extensions", "1.
|
20
|
+
s.add_dependency "sensu-extensions", "1.9.0"
|
21
21
|
s.add_dependency "sensu-transport", "7.0.2"
|
22
22
|
s.add_dependency "sensu-spawn", "2.2.1"
|
23
|
-
s.add_dependency "sensu-redis", "2.1.
|
23
|
+
s.add_dependency "sensu-redis", "2.1.1"
|
24
24
|
s.add_dependency "em-http-server", "0.1.8"
|
25
25
|
s.add_dependency "parse-cron", "0.1.4"
|
26
26
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.29.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Porter
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -59,14 +59,14 @@ dependencies:
|
|
59
59
|
requirements:
|
60
60
|
- - '='
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
62
|
+
version: 10.0.0
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - '='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: 10.0.0
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: sensu-extension
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,14 +87,14 @@ dependencies:
|
|
87
87
|
requirements:
|
88
88
|
- - '='
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 1.
|
90
|
+
version: 1.9.0
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - '='
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 1.
|
97
|
+
version: 1.9.0
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: sensu-transport
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,14 +129,14 @@ dependencies:
|
|
129
129
|
requirements:
|
130
130
|
- - '='
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: 2.1.
|
132
|
+
version: 2.1.1
|
133
133
|
type: :runtime
|
134
134
|
prerelease: false
|
135
135
|
version_requirements: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
137
|
- - '='
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version: 2.1.
|
139
|
+
version: 2.1.1
|
140
140
|
- !ruby/object:Gem::Dependency
|
141
141
|
name: em-http-server
|
142
142
|
requirement: !ruby/object:Gem::Requirement
|
@@ -253,8 +253,10 @@ files:
|
|
253
253
|
- lib/sensu/api/routes/request.rb
|
254
254
|
- lib/sensu/api/routes/resolve.rb
|
255
255
|
- lib/sensu/api/routes/results.rb
|
256
|
+
- lib/sensu/api/routes/settings.rb
|
256
257
|
- lib/sensu/api/routes/silenced.rb
|
257
258
|
- lib/sensu/api/routes/stashes.rb
|
259
|
+
- lib/sensu/api/utilities/filter_response_content.rb
|
258
260
|
- lib/sensu/api/utilities/publish_check_request.rb
|
259
261
|
- lib/sensu/api/utilities/publish_check_result.rb
|
260
262
|
- lib/sensu/api/utilities/resolve_event.rb
|