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,72 @@
|
|
1
|
+
require "sensu/api/routes/info"
|
2
|
+
require "sensu/api/routes/health"
|
3
|
+
require "sensu/api/routes/clients"
|
4
|
+
require "sensu/api/routes/checks"
|
5
|
+
require "sensu/api/routes/request"
|
6
|
+
require "sensu/api/routes/events"
|
7
|
+
require "sensu/api/routes/resolve"
|
8
|
+
require "sensu/api/routes/aggregates"
|
9
|
+
require "sensu/api/routes/stashes"
|
10
|
+
require "sensu/api/routes/results"
|
11
|
+
|
12
|
+
module Sensu
|
13
|
+
module API
|
14
|
+
module Routes
|
15
|
+
include Info
|
16
|
+
include Health
|
17
|
+
include Clients
|
18
|
+
include Checks
|
19
|
+
include Request
|
20
|
+
include Events
|
21
|
+
include Resolve
|
22
|
+
include Aggregates
|
23
|
+
include Stashes
|
24
|
+
include Results
|
25
|
+
|
26
|
+
GET_METHOD = "GET".freeze
|
27
|
+
POST_METHOD = "POST".freeze
|
28
|
+
DELETE_METHOD = "DELETE".freeze
|
29
|
+
OPTIONS_METHOD = "OPTIONS".freeze
|
30
|
+
|
31
|
+
ROUTES = {
|
32
|
+
GET_METHOD => [
|
33
|
+
[INFO_URI, :get_info],
|
34
|
+
[HEALTH_URI, :get_health],
|
35
|
+
[CLIENTS_URI, :get_clients],
|
36
|
+
[CLIENT_URI, :get_client],
|
37
|
+
[CLIENT_HISTORY_URI, :get_client_history],
|
38
|
+
[CHECKS_URI, :get_checks],
|
39
|
+
[CHECK_URI, :get_check],
|
40
|
+
[EVENTS_URI, :get_events],
|
41
|
+
[EVENTS_CLIENT_URI, :get_events_client],
|
42
|
+
[EVENT_URI, :get_event],
|
43
|
+
[AGGREGATES_URI, :get_aggregates],
|
44
|
+
[AGGREGATE_URI, :get_aggregate],
|
45
|
+
[AGGREGATE_CLIENTS_URI, :get_aggregate_clients],
|
46
|
+
[AGGREGATE_CHECKS_URI, :get_aggregate_checks],
|
47
|
+
[AGGREGATE_RESULTS_SEVERITY_URI, :get_aggregate_results_severity],
|
48
|
+
[STASHES_URI, :get_stashes],
|
49
|
+
[STASH_URI, :get_stash],
|
50
|
+
[RESULTS_URI, :get_results],
|
51
|
+
[RESULTS_CLIENT_URI, :get_results_client],
|
52
|
+
[RESULT_URI, :get_result]
|
53
|
+
],
|
54
|
+
POST_METHOD => [
|
55
|
+
[CLIENTS_URI, :post_clients],
|
56
|
+
[REQUEST_URI, :post_request],
|
57
|
+
[RESOLVE_URI, :post_resolve],
|
58
|
+
[STASHES_URI, :post_stashes],
|
59
|
+
[STASH_URI, :post_stash],
|
60
|
+
[RESULTS_URI, :post_results]
|
61
|
+
],
|
62
|
+
DELETE_METHOD => [
|
63
|
+
[CLIENT_URI, :delete_client],
|
64
|
+
[EVENT_URI, :delete_event],
|
65
|
+
[AGGREGATE_URI, :delete_aggregate],
|
66
|
+
[STASH_URI, :delete_stash],
|
67
|
+
[RESULT_URI, :delete_result]
|
68
|
+
]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Routes
|
4
|
+
module Aggregates
|
5
|
+
AGGREGATES_URI = /^\/aggregates$/
|
6
|
+
AGGREGATE_URI = /^\/aggregates\/([\w\.-]+)$/
|
7
|
+
AGGREGATE_CLIENTS_URI = /^\/aggregates\/([\w\.-]+)\/clients$/
|
8
|
+
AGGREGATE_CHECKS_URI = /^\/aggregates\/([\w\.-]+)\/checks$/
|
9
|
+
AGGREGATE_RESULTS_SEVERITY_URI = /^\/aggregates\/([\w\.-]+)\/results\/([\w\.-]+)$/
|
10
|
+
|
11
|
+
def get_aggregates
|
12
|
+
@redis.smembers("aggregates") do |aggregates|
|
13
|
+
aggregates.map! do |aggregate|
|
14
|
+
{:name => aggregate}
|
15
|
+
end
|
16
|
+
@response_content = aggregates
|
17
|
+
respond
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_aggregate
|
22
|
+
aggregate = AGGREGATE_URI.match(@http_request_uri)[1]
|
23
|
+
@redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
24
|
+
unless aggregate_members.empty?
|
25
|
+
@response_content = {
|
26
|
+
:clients => 0,
|
27
|
+
:checks => 0,
|
28
|
+
:results => {
|
29
|
+
:ok => 0,
|
30
|
+
:warning => 0,
|
31
|
+
:critical => 0,
|
32
|
+
:unknown => 0,
|
33
|
+
:total => 0,
|
34
|
+
:stale => 0
|
35
|
+
}
|
36
|
+
}
|
37
|
+
clients = []
|
38
|
+
checks = []
|
39
|
+
results = []
|
40
|
+
aggregate_members.each_with_index do |member, index|
|
41
|
+
client_name, check_name = member.split(":")
|
42
|
+
clients << client_name
|
43
|
+
checks << check_name
|
44
|
+
result_key = "result:#{client_name}:#{check_name}"
|
45
|
+
@redis.get(result_key) do |result_json|
|
46
|
+
unless result_json.nil?
|
47
|
+
results << Sensu::JSON.load(result_json)
|
48
|
+
else
|
49
|
+
@redis.srem("aggregates:#{aggregate}", member)
|
50
|
+
end
|
51
|
+
if index == aggregate_members.length - 1
|
52
|
+
@response_content[:clients] = clients.uniq.length
|
53
|
+
@response_content[:checks] = checks.uniq.length
|
54
|
+
max_age = integer_parameter(@params[:max_age])
|
55
|
+
if max_age
|
56
|
+
result_count = results.length
|
57
|
+
timestamp = Time.now.to_i - max_age
|
58
|
+
results.reject! do |result|
|
59
|
+
result[:executed] < timestamp
|
60
|
+
end
|
61
|
+
@response_content[:results][:stale] = result_count - results.length
|
62
|
+
end
|
63
|
+
@response_content[:results][:total] = results.length
|
64
|
+
results.each do |result|
|
65
|
+
severity = (SEVERITIES[result[:status]] || "unknown")
|
66
|
+
@response_content[:results][severity.to_sym] += 1
|
67
|
+
end
|
68
|
+
respond
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
not_found!
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete_aggregate
|
79
|
+
aggregate = AGGREGATE_URI.match(@http_request_uri)[1]
|
80
|
+
@redis.smembers("aggregates") do |aggregates|
|
81
|
+
if aggregates.include?(aggregate)
|
82
|
+
@redis.srem("aggregates", aggregate) do
|
83
|
+
@redis.del("aggregates:#{aggregate}") do
|
84
|
+
no_content!
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
not_found!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_aggregate_clients
|
94
|
+
aggregate = AGGREGATE_CLIENTS_URI.match(@http_request_uri)[1]
|
95
|
+
@response_content = []
|
96
|
+
@redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
97
|
+
unless aggregate_members.empty?
|
98
|
+
clients = {}
|
99
|
+
aggregate_members.each do |member|
|
100
|
+
client_name, check_name = member.split(":")
|
101
|
+
clients[client_name] ||= []
|
102
|
+
clients[client_name] << check_name
|
103
|
+
end
|
104
|
+
clients.each do |client_name, checks|
|
105
|
+
@response_content << {
|
106
|
+
:name => client_name,
|
107
|
+
:checks => checks
|
108
|
+
}
|
109
|
+
end
|
110
|
+
respond
|
111
|
+
else
|
112
|
+
not_found!
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def get_aggregate_checks
|
118
|
+
aggregate = AGGREGATE_CHECKS_URI.match(@http_request_uri)[1]
|
119
|
+
@response_content = []
|
120
|
+
@redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
121
|
+
unless aggregate_members.empty?
|
122
|
+
checks = {}
|
123
|
+
aggregate_members.each do |member|
|
124
|
+
client_name, check_name = member.split(":")
|
125
|
+
checks[check_name] ||= []
|
126
|
+
checks[check_name] << client_name
|
127
|
+
end
|
128
|
+
checks.each do |check_name, clients|
|
129
|
+
@response_content << {
|
130
|
+
:name => check_name,
|
131
|
+
:clients => clients
|
132
|
+
}
|
133
|
+
end
|
134
|
+
respond
|
135
|
+
else
|
136
|
+
not_found!
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_aggregate_results_severity
|
142
|
+
uri_match = AGGREGATE_RESULTS_SEVERITY_URI.match(@http_request_uri)
|
143
|
+
aggregate = uri_match[1]
|
144
|
+
severity = uri_match[2]
|
145
|
+
@response_content = []
|
146
|
+
if SEVERITIES.include?(severity)
|
147
|
+
@redis.smembers("aggregates:#{aggregate}") do |aggregate_members|
|
148
|
+
unless aggregate_members.empty?
|
149
|
+
summaries = Hash.new
|
150
|
+
max_age = integer_parameter(@params[:max_age])
|
151
|
+
current_timestamp = Time.now.to_i
|
152
|
+
aggregate_members.each_with_index do |member, index|
|
153
|
+
client_name, check_name = member.split(":")
|
154
|
+
result_key = "result:#{client_name}:#{check_name}"
|
155
|
+
@redis.get(result_key) do |result_json|
|
156
|
+
unless result_json.nil?
|
157
|
+
result = Sensu::JSON.load(result_json)
|
158
|
+
if SEVERITIES[result[:status]] == severity &&
|
159
|
+
(max_age.nil? || result[:executed] >= (current_timestamp - max_age))
|
160
|
+
summaries[check_name] ||= {}
|
161
|
+
summaries[check_name][result[:output]] ||= {:total => 0, :clients => []}
|
162
|
+
summaries[check_name][result[:output]][:total] += 1
|
163
|
+
summaries[check_name][result[:output]][:clients] << client_name
|
164
|
+
end
|
165
|
+
end
|
166
|
+
if index == aggregate_members.length - 1
|
167
|
+
summaries.each do |check_name, outputs|
|
168
|
+
summary = outputs.map do |output, output_summary|
|
169
|
+
{:output => output}.merge(output_summary)
|
170
|
+
end
|
171
|
+
@response_content << {
|
172
|
+
:check => check_name,
|
173
|
+
:summary => summary
|
174
|
+
}
|
175
|
+
end
|
176
|
+
respond
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
else
|
181
|
+
not_found!
|
182
|
+
end
|
183
|
+
end
|
184
|
+
else
|
185
|
+
bad_request!
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Routes
|
4
|
+
module Checks
|
5
|
+
CHECKS_URI = /^\/checks$/
|
6
|
+
CHECK_URI = /^\/checks\/([\w\.-]+)$/
|
7
|
+
|
8
|
+
def get_checks
|
9
|
+
@response_content = @settings.checks
|
10
|
+
respond
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_check
|
14
|
+
check_name = CHECK_URI.match(@http_request_uri)[1]
|
15
|
+
if @settings[:checks][check_name]
|
16
|
+
@response_content = @settings[:checks][check_name].merge(:name => check_name)
|
17
|
+
respond
|
18
|
+
else
|
19
|
+
not_found!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require "sensu/api/utilities/resolve_event"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Clients
|
7
|
+
include Utilities::ResolveEvent
|
8
|
+
|
9
|
+
CLIENTS_URI = /^\/clients$/
|
10
|
+
CLIENT_URI = /^\/clients\/([\w\.-]+)$/
|
11
|
+
CLIENT_HISTORY_URI = /^\/clients\/([\w\.-]+)\/history$/
|
12
|
+
|
13
|
+
def post_clients
|
14
|
+
read_data do |client|
|
15
|
+
client[:keepalives] = client.fetch(:keepalives, false)
|
16
|
+
client[:version] = VERSION
|
17
|
+
client[:timestamp] = Time.now.to_i
|
18
|
+
validator = Validators::Client.new
|
19
|
+
if validator.valid?(client)
|
20
|
+
@redis.set("client:#{client[:name]}", Sensu::JSON.dump(client)) do
|
21
|
+
@redis.sadd("clients", client[:name]) do
|
22
|
+
@response_content = {:name => client[:name]}
|
23
|
+
created!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
else
|
27
|
+
bad_request!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_clients
|
33
|
+
@response_content = []
|
34
|
+
@redis.smembers("clients") do |clients|
|
35
|
+
clients = pagination(clients)
|
36
|
+
unless clients.empty?
|
37
|
+
clients.each_with_index do |client_name, index|
|
38
|
+
@redis.get("client:#{client_name}") do |client_json|
|
39
|
+
unless client_json.nil?
|
40
|
+
@response_content << Sensu::JSON.load(client_json)
|
41
|
+
else
|
42
|
+
@logger.error("client data missing from registry", :client_name => client_name)
|
43
|
+
@redis.srem("clients", client_name)
|
44
|
+
end
|
45
|
+
if index == clients.length - 1
|
46
|
+
respond
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
respond
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_client
|
57
|
+
client_name = CLIENT_URI.match(@http_request_uri)[1]
|
58
|
+
@redis.get("client:#{client_name}") do |client_json|
|
59
|
+
unless client_json.nil?
|
60
|
+
@response_content = Sensu::JSON.load(client_json)
|
61
|
+
respond
|
62
|
+
else
|
63
|
+
not_found!
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_client_history
|
69
|
+
client_name = CLIENT_HISTORY_URI.match(@http_request_uri)[1]
|
70
|
+
@response_content = []
|
71
|
+
@redis.smembers("result:#{client_name}") do |checks|
|
72
|
+
unless checks.empty?
|
73
|
+
checks.each_with_index do |check_name, index|
|
74
|
+
result_key = "#{client_name}:#{check_name}"
|
75
|
+
history_key = "history:#{result_key}"
|
76
|
+
@redis.lrange(history_key, -21, -1) do |history|
|
77
|
+
history.map! do |status|
|
78
|
+
status.to_i
|
79
|
+
end
|
80
|
+
@redis.get("result:#{result_key}") do |result_json|
|
81
|
+
unless result_json.nil?
|
82
|
+
result = Sensu::JSON.load(result_json)
|
83
|
+
last_execution = result[:executed]
|
84
|
+
unless history.empty? || last_execution.nil?
|
85
|
+
item = {
|
86
|
+
:check => check_name,
|
87
|
+
:history => history,
|
88
|
+
:last_execution => last_execution.to_i,
|
89
|
+
:last_status => history.last,
|
90
|
+
:last_result => result
|
91
|
+
}
|
92
|
+
@response_content << item
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if index == checks.length - 1
|
96
|
+
respond
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
else
|
102
|
+
respond
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def delete_client
|
108
|
+
client_name = CLIENT_URI.match(@http_request_uri)[1]
|
109
|
+
@redis.get("client:#{client_name}") do |client_json|
|
110
|
+
unless client_json.nil?
|
111
|
+
@redis.hgetall("events:#{client_name}") do |events|
|
112
|
+
events.each do |check_name, event_json|
|
113
|
+
resolve_event(event_json)
|
114
|
+
end
|
115
|
+
delete_client = Proc.new do |attempts|
|
116
|
+
attempts += 1
|
117
|
+
@redis.hgetall("events:#{client_name}") do |events|
|
118
|
+
if events.empty? || attempts == 5
|
119
|
+
@logger.info("deleting client from registry", :client_name => client_name)
|
120
|
+
@redis.srem("clients", client_name) do
|
121
|
+
@redis.del("client:#{client_name}")
|
122
|
+
@redis.del("client:#{client_name}:signature")
|
123
|
+
@redis.del("events:#{client_name}")
|
124
|
+
@redis.smembers("result:#{client_name}") do |checks|
|
125
|
+
checks.each do |check_name|
|
126
|
+
result_key = "#{client_name}:#{check_name}"
|
127
|
+
@redis.del("result:#{result_key}")
|
128
|
+
@redis.del("history:#{result_key}")
|
129
|
+
end
|
130
|
+
@redis.del("result:#{client_name}")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
else
|
134
|
+
EM::Timer.new(1) do
|
135
|
+
delete_client.call(attempts)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
delete_client.call(0)
|
141
|
+
@response_content = {:issued => Time.now.to_i}
|
142
|
+
accepted!
|
143
|
+
end
|
144
|
+
else
|
145
|
+
not_found!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "sensu/api/utilities/resolve_event"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Routes
|
6
|
+
module Events
|
7
|
+
include Utilities::ResolveEvent
|
8
|
+
|
9
|
+
EVENTS_URI = /^\/events$/
|
10
|
+
EVENTS_CLIENT_URI = /^\/events\/([\w\.-]+)$/
|
11
|
+
EVENT_URI = /^\/events\/([\w\.-]+)\/([\w\.-]+)$/
|
12
|
+
|
13
|
+
def get_events
|
14
|
+
@response_content = []
|
15
|
+
@redis.smembers("clients") do |clients|
|
16
|
+
unless clients.empty?
|
17
|
+
clients.each_with_index do |client_name, index|
|
18
|
+
@redis.hgetall("events:#{client_name}") do |events|
|
19
|
+
events.each do |check_name, event_json|
|
20
|
+
@response_content << Sensu::JSON.load(event_json)
|
21
|
+
end
|
22
|
+
if index == clients.length - 1
|
23
|
+
respond
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
else
|
28
|
+
respond
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_events_client
|
34
|
+
client_name = EVENTS_CLIENT_URI.match(@http_request_uri)[1]
|
35
|
+
@response_content = []
|
36
|
+
@redis.hgetall("events:#{client_name}") do |events|
|
37
|
+
events.each do |check_name, event_json|
|
38
|
+
@response_content << Sensu::JSON.load(event_json)
|
39
|
+
end
|
40
|
+
respond
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_event
|
45
|
+
uri_match = EVENT_URI.match(@http_request_uri)
|
46
|
+
client_name = uri_match[1]
|
47
|
+
check_name = uri_match[2]
|
48
|
+
@redis.hgetall("events:#{client_name}") do |events|
|
49
|
+
event_json = events[check_name]
|
50
|
+
unless event_json.nil?
|
51
|
+
@response_content = Sensu::JSON.load(event_json)
|
52
|
+
respond
|
53
|
+
else
|
54
|
+
not_found!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_event
|
60
|
+
uri_match = EVENT_URI.match(@http_request_uri)
|
61
|
+
client_name = uri_match[1]
|
62
|
+
check_name = uri_match[2]
|
63
|
+
@redis.hgetall("events:#{client_name}") do |events|
|
64
|
+
if events.include?(check_name)
|
65
|
+
resolve_event(events[check_name])
|
66
|
+
@response_content = {:issued => Time.now.to_i}
|
67
|
+
accepted!
|
68
|
+
else
|
69
|
+
not_found!
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|