sensu 0.24.1 → 0.25.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sensu/api/http_handler.rb +340 -0
- data/lib/sensu/api/process.rb +59 -947
- data/lib/sensu/api/routes.rb +72 -0
- data/lib/sensu/api/routes/aggregates.rb +191 -0
- data/lib/sensu/api/routes/checks.rb +25 -0
- data/lib/sensu/api/routes/clients.rb +152 -0
- data/lib/sensu/api/routes/events.rb +76 -0
- data/lib/sensu/api/routes/health.rb +34 -0
- data/lib/sensu/api/routes/info.rb +28 -0
- data/lib/sensu/api/routes/request.rb +33 -0
- data/lib/sensu/api/routes/resolve.rb +31 -0
- data/lib/sensu/api/routes/results.rb +116 -0
- data/lib/sensu/api/routes/stashes.rb +102 -0
- data/lib/sensu/api/utilities/publish_check_request.rb +57 -0
- data/lib/sensu/api/utilities/publish_check_result.rb +36 -0
- data/lib/sensu/api/utilities/resolve_event.rb +29 -0
- data/lib/sensu/api/utilities/transport_info.rb +37 -0
- data/lib/sensu/client/process.rb +28 -1
- data/lib/sensu/client/socket.rb +1 -1
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +18 -8
- data/lib/sensu/server/process.rb +13 -12
- data/sensu.gemspec +1 -4
- metadata +23 -35
@@ -0,0 +1,34 @@
|
|
1
|
+
require "sensu/api/utilities/transport_info"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Health
|
7
|
+
include Utilities::TransportInfo
|
8
|
+
|
9
|
+
HEALTH_URI = /^\/health$/
|
10
|
+
|
11
|
+
def get_health
|
12
|
+
if @redis.connected? && @transport.connected?
|
13
|
+
healthy = []
|
14
|
+
min_consumers = integer_parameter(@params[:consumers])
|
15
|
+
max_messages = integer_parameter(@params[:messages])
|
16
|
+
transport_info do |info|
|
17
|
+
if min_consumers
|
18
|
+
healthy << (info[:keepalives][:consumers] >= min_consumers)
|
19
|
+
healthy << (info[:results][:consumers] >= min_consumers)
|
20
|
+
end
|
21
|
+
if max_messages
|
22
|
+
healthy << (info[:keepalives][:messages] <= max_messages)
|
23
|
+
healthy << (info[:results][:messages] <= max_messages)
|
24
|
+
end
|
25
|
+
healthy.all? ? no_content! : precondition_failed!
|
26
|
+
end
|
27
|
+
else
|
28
|
+
precondition_failed!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "sensu/api/utilities/transport_info"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Info
|
7
|
+
include Utilities::TransportInfo
|
8
|
+
|
9
|
+
INFO_URI = /^\/info$/
|
10
|
+
|
11
|
+
def get_info
|
12
|
+
transport_info do |info|
|
13
|
+
@response_content = {
|
14
|
+
:sensu => {
|
15
|
+
:version => VERSION
|
16
|
+
},
|
17
|
+
:transport => info,
|
18
|
+
:redis => {
|
19
|
+
:connected => @redis.connected?
|
20
|
+
}
|
21
|
+
}
|
22
|
+
respond
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "sensu/api/utilities/publish_check_request"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Request
|
7
|
+
include Utilities::PublishCheckRequest
|
8
|
+
|
9
|
+
REQUEST_URI = /^\/request$/
|
10
|
+
|
11
|
+
def post_request
|
12
|
+
rules = {
|
13
|
+
:check => {:type => String, :nil_ok => false},
|
14
|
+
:subscribers => {:type => Array, :nil_ok => true}
|
15
|
+
}
|
16
|
+
read_data(rules) do |data|
|
17
|
+
if @settings[:checks][data[:check]]
|
18
|
+
check = @settings[:checks][data[:check]].dup
|
19
|
+
check[:name] = data[:check]
|
20
|
+
check[:subscribers] ||= Array.new
|
21
|
+
check[:subscribers] = data[:subscribers] if data[:subscribers]
|
22
|
+
publish_check_request(check)
|
23
|
+
@response_content = {:issued => Time.now.to_i}
|
24
|
+
accepted!
|
25
|
+
else
|
26
|
+
not_found!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "sensu/api/utilities/resolve_event"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Resolve
|
7
|
+
include Utilities::ResolveEvent
|
8
|
+
|
9
|
+
RESOLVE_URI = /^\/resolve$/
|
10
|
+
|
11
|
+
def post_resolve
|
12
|
+
rules = {
|
13
|
+
:client => {:type => String, :nil_ok => false},
|
14
|
+
:check => {:type => String, :nil_ok => false}
|
15
|
+
}
|
16
|
+
read_data(rules) do |data|
|
17
|
+
@redis.hgetall("events:#{data[:client]}") do |events|
|
18
|
+
if events.include?(data[:check])
|
19
|
+
resolve_event(events[data[:check]])
|
20
|
+
@response_content = {:issued => Time.now.to_i}
|
21
|
+
accepted!
|
22
|
+
else
|
23
|
+
not_found!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "sensu/api/utilities/publish_check_result"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Results
|
7
|
+
include Utilities::PublishCheckResult
|
8
|
+
|
9
|
+
RESULTS_URI = /^\/results$/
|
10
|
+
RESULTS_CLIENT_URI = /^\/results\/([\w\.-]+)$/
|
11
|
+
RESULT_URI = /^\/results\/([\w\.-]+)\/([\w\.-]+)$/
|
12
|
+
|
13
|
+
def post_results
|
14
|
+
rules = {
|
15
|
+
:name => {:type => String, :nil_ok => false, :regex => /\A[\w\.-]+\z/},
|
16
|
+
:output => {:type => String, :nil_ok => false},
|
17
|
+
:status => {:type => Integer, :nil_ok => true},
|
18
|
+
:source => {:type => String, :nil_ok => true, :regex => /\A[\w\.-]+\z/}
|
19
|
+
}
|
20
|
+
read_data(rules) do |data|
|
21
|
+
publish_check_result("sensu-api", data)
|
22
|
+
@response_content = {:issued => Time.now.to_i}
|
23
|
+
accepted!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_results
|
28
|
+
@response_content = []
|
29
|
+
@redis.smembers("clients") do |clients|
|
30
|
+
unless clients.empty?
|
31
|
+
clients.each_with_index do |client_name, client_index|
|
32
|
+
@redis.smembers("result:#{client_name}") do |checks|
|
33
|
+
if !checks.empty?
|
34
|
+
checks.each_with_index do |check_name, check_index|
|
35
|
+
result_key = "result:#{client_name}:#{check_name}"
|
36
|
+
@redis.get(result_key) do |result_json|
|
37
|
+
unless result_json.nil?
|
38
|
+
check = Sensu::JSON.load(result_json)
|
39
|
+
@response_content << {:client => client_name, :check => check}
|
40
|
+
end
|
41
|
+
if client_index == clients.length - 1 && check_index == checks.length - 1
|
42
|
+
respond
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
elsif client_index == clients.length - 1
|
47
|
+
respond
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
respond
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_results_client
|
58
|
+
client_name = RESULTS_CLIENT_URI.match(@http_request_uri)[1]
|
59
|
+
@response_content = []
|
60
|
+
@redis.smembers("result:#{client_name}") do |checks|
|
61
|
+
unless checks.empty?
|
62
|
+
checks.each_with_index do |check_name, check_index|
|
63
|
+
result_key = "result:#{client_name}:#{check_name}"
|
64
|
+
@redis.get(result_key) do |result_json|
|
65
|
+
unless result_json.nil?
|
66
|
+
check = Sensu::JSON.load(result_json)
|
67
|
+
@response_content << {:client => client_name, :check => check}
|
68
|
+
end
|
69
|
+
if check_index == checks.length - 1
|
70
|
+
respond
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
else
|
75
|
+
not_found!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_result
|
81
|
+
uri_match = RESULT_URI.match(@http_request_uri)
|
82
|
+
client_name = uri_match[1]
|
83
|
+
check_name = uri_match[2]
|
84
|
+
result_key = "result:#{client_name}:#{check_name}"
|
85
|
+
@redis.get(result_key) do |result_json|
|
86
|
+
unless result_json.nil?
|
87
|
+
check = Sensu::JSON.load(result_json)
|
88
|
+
@response_content = {:client => client_name, :check => check}
|
89
|
+
respond
|
90
|
+
else
|
91
|
+
not_found!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete_result
|
97
|
+
uri_match = RESULT_URI.match(@http_request_uri)
|
98
|
+
client_name = uri_match[1]
|
99
|
+
check_name = uri_match[2]
|
100
|
+
result_key = "result:#{client_name}:#{check_name}"
|
101
|
+
@redis.exists(result_key) do |result_exists|
|
102
|
+
if result_exists
|
103
|
+
@redis.srem("result:#{client_name}", check_name) do
|
104
|
+
@redis.del(result_key) do
|
105
|
+
no_content!
|
106
|
+
end
|
107
|
+
end
|
108
|
+
else
|
109
|
+
not_found!
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Routes
|
4
|
+
module Stashes
|
5
|
+
STASHES_URI = /^\/stashes$/
|
6
|
+
STASH_URI = /^\/stash(?:es)?\/(.*)$/
|
7
|
+
|
8
|
+
def post_stash
|
9
|
+
path = STASH_URI.match(@http_request_uri)[1]
|
10
|
+
read_data do |data|
|
11
|
+
@redis.set("stash:#{path}", Sensu::JSON.dump(data)) do
|
12
|
+
@redis.sadd("stashes", path) do
|
13
|
+
@response_content = {:path => path}
|
14
|
+
created!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_stash
|
21
|
+
path = STASH_URI.match(@http_request_uri)[1]
|
22
|
+
@redis.get("stash:#{path}") do |stash_json|
|
23
|
+
unless stash_json.nil?
|
24
|
+
@response_content = Sensu::JSON.load(stash_json)
|
25
|
+
respond
|
26
|
+
else
|
27
|
+
not_found!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_stash
|
33
|
+
path = STASH_URI.match(@http_request_uri)[1]
|
34
|
+
@redis.exists("stash:#{path}") do |stash_exists|
|
35
|
+
if stash_exists
|
36
|
+
@redis.srem("stashes", path) do
|
37
|
+
@redis.del("stash:#{path}") do
|
38
|
+
no_content!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
not_found!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_stashes
|
48
|
+
@response_content = []
|
49
|
+
@redis.smembers("stashes") do |stashes|
|
50
|
+
unless stashes.empty?
|
51
|
+
stashes = pagination(stashes)
|
52
|
+
stashes.each_with_index do |path, index|
|
53
|
+
@redis.get("stash:#{path}") do |stash_json|
|
54
|
+
@redis.ttl("stash:#{path}") do |ttl|
|
55
|
+
unless stash_json.nil?
|
56
|
+
item = {
|
57
|
+
:path => path,
|
58
|
+
:content => Sensu::JSON.load(stash_json),
|
59
|
+
:expire => ttl
|
60
|
+
}
|
61
|
+
@response_content << item
|
62
|
+
else
|
63
|
+
@redis.srem("stashes", path)
|
64
|
+
end
|
65
|
+
if index == stashes.length - 1
|
66
|
+
respond
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
else
|
72
|
+
respond
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def post_stashes
|
78
|
+
rules = {
|
79
|
+
:path => {:type => String, :nil_ok => false},
|
80
|
+
:content => {:type => Hash, :nil_ok => false},
|
81
|
+
:expire => {:type => Integer, :nil_ok => true}
|
82
|
+
}
|
83
|
+
read_data(rules) do |data|
|
84
|
+
stash_key = "stash:#{data[:path]}"
|
85
|
+
@redis.set(stash_key, Sensu::JSON.dump(data[:content])) do
|
86
|
+
@redis.sadd("stashes", data[:path]) do
|
87
|
+
@response_content = {:path => data[:path]}
|
88
|
+
if data[:expire]
|
89
|
+
@redis.expire(stash_key, data[:expire]) do
|
90
|
+
created!
|
91
|
+
end
|
92
|
+
else
|
93
|
+
created!
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Utilities
|
4
|
+
module PublishCheckRequest
|
5
|
+
# Determine the Sensu Transport publish options for a
|
6
|
+
# subscription. If a subscription begins with a Transport pipe
|
7
|
+
# type, either "direct:" or "roundrobin:", the subscription uses
|
8
|
+
# a direct Transport pipe. If a subscription does not specify a
|
9
|
+
# Transport pipe type, a fanout Transport pipe is used.
|
10
|
+
#
|
11
|
+
# @param subscription [String]
|
12
|
+
# @param message [String]
|
13
|
+
# @return [Array] containing the Transport publish options:
|
14
|
+
# the Transport pipe type, pipe, and the message to be
|
15
|
+
# published.
|
16
|
+
def transport_publish_options(subscription, message)
|
17
|
+
_, raw_type = subscription.split(":", 2).reverse
|
18
|
+
case raw_type
|
19
|
+
when "direct", "roundrobin"
|
20
|
+
[:direct, subscription, message]
|
21
|
+
else
|
22
|
+
[:fanout, subscription, message]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Publish a check request to the Transport. A check request is
|
27
|
+
# composed of a check `:name`, an `:issued` timestamp, a check
|
28
|
+
# `:command` if available, and a check `:extension if available.
|
29
|
+
# The check request is published to a Transport pipe, for each
|
30
|
+
# of the check `:subscribers` in its definition, eg. "webserver".
|
31
|
+
# JSON serialization is used when publishing the check request
|
32
|
+
# payload to the Transport pipes. Transport errors are logged.
|
33
|
+
#
|
34
|
+
# @param check [Hash] definition.
|
35
|
+
def publish_check_request(check)
|
36
|
+
payload = check.merge(:issued => Time.now.to_i)
|
37
|
+
@logger.info("publishing check request", {
|
38
|
+
:payload => payload,
|
39
|
+
:subscribers => check[:subscribers]
|
40
|
+
})
|
41
|
+
check[:subscribers].each do |subscription|
|
42
|
+
options = transport_publish_options(subscription.to_s, Sensu::JSON.dump(payload))
|
43
|
+
@transport.publish(*options) do |info|
|
44
|
+
if info[:error]
|
45
|
+
@logger.error("failed to publish check request", {
|
46
|
+
:subscription => subscription,
|
47
|
+
:payload => payload,
|
48
|
+
:error => info[:error].to_s
|
49
|
+
})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Utilities
|
4
|
+
module PublishCheckResult
|
5
|
+
# Publish a check result to the Transport for processing. A
|
6
|
+
# check result is composed of a client name and a check
|
7
|
+
# definition, containing check `:output` and `:status`. A client
|
8
|
+
# signature is added to the check result payload if one is
|
9
|
+
# registered for the client. JSON serialization is used when
|
10
|
+
# publishing the check result payload to the Transport pipe.
|
11
|
+
# Transport errors are logged.
|
12
|
+
#
|
13
|
+
# @param client_name [String]
|
14
|
+
# @param check [Hash]
|
15
|
+
def publish_check_result(client_name, check)
|
16
|
+
check[:issued] = Time.now.to_i
|
17
|
+
check[:executed] = Time.now.to_i
|
18
|
+
check[:status] ||= 0
|
19
|
+
payload = {
|
20
|
+
:client => client_name,
|
21
|
+
:check => check
|
22
|
+
}
|
23
|
+
@logger.info("publishing check result", :payload => payload)
|
24
|
+
@transport.publish(:direct, "results", Sensu::JSON.dump(payload)) do |info|
|
25
|
+
if info[:error]
|
26
|
+
@logger.error("failed to publish check result", {
|
27
|
+
:payload => payload,
|
28
|
+
:error => info[:error].to_s
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|