portertech-sensu 1.10.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 +7 -0
- data/CHANGELOG.md +961 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +65 -0
- data/exe/sensu-api +10 -0
- data/exe/sensu-client +10 -0
- data/exe/sensu-install +195 -0
- data/exe/sensu-server +10 -0
- data/lib/sensu/api/http_handler.rb +434 -0
- data/lib/sensu/api/process.rb +79 -0
- data/lib/sensu/api/routes/aggregates.rb +196 -0
- data/lib/sensu/api/routes/checks.rb +44 -0
- data/lib/sensu/api/routes/clients.rb +171 -0
- data/lib/sensu/api/routes/events.rb +86 -0
- data/lib/sensu/api/routes/health.rb +45 -0
- data/lib/sensu/api/routes/info.rb +37 -0
- data/lib/sensu/api/routes/request.rb +44 -0
- data/lib/sensu/api/routes/resolve.rb +32 -0
- data/lib/sensu/api/routes/results.rb +153 -0
- data/lib/sensu/api/routes/settings.rb +23 -0
- data/lib/sensu/api/routes/silenced.rb +182 -0
- data/lib/sensu/api/routes/stashes.rb +107 -0
- data/lib/sensu/api/routes.rb +88 -0
- data/lib/sensu/api/utilities/filter_response_content.rb +44 -0
- data/lib/sensu/api/utilities/publish_check_request.rb +107 -0
- data/lib/sensu/api/utilities/publish_check_result.rb +39 -0
- data/lib/sensu/api/utilities/resolve_event.rb +29 -0
- data/lib/sensu/api/utilities/servers_info.rb +43 -0
- data/lib/sensu/api/utilities/transport_info.rb +43 -0
- data/lib/sensu/api/validators/check.rb +55 -0
- data/lib/sensu/api/validators/client.rb +35 -0
- data/lib/sensu/api/validators/invalid.rb +8 -0
- data/lib/sensu/cli.rb +69 -0
- data/lib/sensu/client/http_socket.rb +217 -0
- data/lib/sensu/client/process.rb +655 -0
- data/lib/sensu/client/socket.rb +207 -0
- data/lib/sensu/client/utils.rb +53 -0
- data/lib/sensu/client/validators/check.rb +53 -0
- data/lib/sensu/constants.rb +17 -0
- data/lib/sensu/daemon.rb +396 -0
- data/lib/sensu/sandbox.rb +19 -0
- data/lib/sensu/server/filter.rb +227 -0
- data/lib/sensu/server/handle.rb +201 -0
- data/lib/sensu/server/mutate.rb +92 -0
- data/lib/sensu/server/process.rb +1646 -0
- data/lib/sensu/server/socket.rb +54 -0
- data/lib/sensu/server/tessen.rb +170 -0
- data/lib/sensu/utilities.rb +398 -0
- data/lib/sensu.rb +3 -0
- data/sensu.gemspec +36 -0
- metadata +322 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Routes
|
4
|
+
module Silenced
|
5
|
+
SILENCED_URI = /^\/silenced$/
|
6
|
+
SILENCED_ID_URI = /^\/silenced\/ids\/([\w\.\-\*\:]+)$/
|
7
|
+
SILENCED_SUBSCRIPTION_URI = /^\/silenced\/subscriptions\/([\w\.\-:]+)$/
|
8
|
+
SILENCED_CHECK_URI = /^\/silenced\/checks\/([\w\.\-]+)$/
|
9
|
+
SILENCED_CLEAR_URI = /^\/silenced\/clear$/
|
10
|
+
|
11
|
+
# Fetch silenced registry entries for the provided silenced
|
12
|
+
# entry keys.
|
13
|
+
#
|
14
|
+
# @param silenced_keys [Array]
|
15
|
+
# @yield callback [entries] callback/block called after the
|
16
|
+
# silenced registry entries have been fetched.
|
17
|
+
def fetch_silenced(silenced_keys=[])
|
18
|
+
entries = []
|
19
|
+
unless silenced_keys.empty?
|
20
|
+
@redis.mget(*silenced_keys) do |silenced|
|
21
|
+
silenced_keys.each_with_index do |silenced_key, silenced_index|
|
22
|
+
if silenced[silenced_index]
|
23
|
+
silenced_info = Sensu::JSON.load(silenced[silenced_index])
|
24
|
+
@redis.ttl(silenced_key) do |ttl|
|
25
|
+
silenced_info[:expire] = ttl
|
26
|
+
entries << silenced_info
|
27
|
+
if silenced_index == silenced_keys.length - 1
|
28
|
+
yield(entries)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
else
|
32
|
+
@redis.srem("silenced", silenced_key)
|
33
|
+
if silenced_index == silenced_keys.length - 1
|
34
|
+
@redis.ping do
|
35
|
+
yield(entries)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
yield(entries)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# POST /silenced
|
47
|
+
def post_silenced
|
48
|
+
rules = {
|
49
|
+
:subscription => {:type => String, :nil_ok => true, :regex => /\A[\w\.\-\:]+\z/},
|
50
|
+
:check => {:type => String, :nil_ok => true, :regex => /\A[\w\.-]+\z/},
|
51
|
+
:begin => {:type => Integer, :nil_ok => true},
|
52
|
+
:expire => {:type => Integer, :nil_ok => true},
|
53
|
+
:reason => {:type => String, :nil_ok => true},
|
54
|
+
:creator => {:type => String, :nil_ok => true},
|
55
|
+
:expire_on_resolve => {:type => [TrueClass, FalseClass], :nil_ok => true}
|
56
|
+
}
|
57
|
+
read_data(rules) do |data|
|
58
|
+
if data[:subscription] || data[:check]
|
59
|
+
subscription = data.fetch(:subscription, "*")
|
60
|
+
check = data.fetch(:check, "*")
|
61
|
+
silenced_id = "#{subscription}:#{check}"
|
62
|
+
timestamp = Time.now.to_i
|
63
|
+
silenced_info = {
|
64
|
+
:id => silenced_id,
|
65
|
+
:subscription => data[:subscription],
|
66
|
+
:check => data[:check],
|
67
|
+
:reason => data[:reason],
|
68
|
+
:creator => data[:creator],
|
69
|
+
:begin => data[:begin],
|
70
|
+
:expire_on_resolve => data.fetch(:expire_on_resolve, false),
|
71
|
+
:timestamp => timestamp
|
72
|
+
}
|
73
|
+
silenced_key = "silence:#{silenced_id}"
|
74
|
+
@redis.set(silenced_key, Sensu::JSON.dump(silenced_info)) do
|
75
|
+
@redis.sadd("silenced", silenced_key) do
|
76
|
+
if data[:expire]
|
77
|
+
expire = data[:expire]
|
78
|
+
if data[:begin]
|
79
|
+
diff = data[:begin] - timestamp
|
80
|
+
expire += diff if diff > 0
|
81
|
+
end
|
82
|
+
@redis.expire(silenced_key, expire) do
|
83
|
+
created!
|
84
|
+
end
|
85
|
+
else
|
86
|
+
created!
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
else
|
91
|
+
bad_request!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# GET /silenced
|
97
|
+
def get_silenced
|
98
|
+
@redis.smembers("silenced") do |silenced_keys|
|
99
|
+
silenced_keys = pagination(silenced_keys)
|
100
|
+
fetch_silenced(silenced_keys) do |silenced|
|
101
|
+
@response_content = silenced
|
102
|
+
respond
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# GET /silenced/subscriptions/:subscription
|
108
|
+
def get_silenced_subscription
|
109
|
+
subscription = parse_uri(SILENCED_SUBSCRIPTION_URI).first
|
110
|
+
@redis.smembers("silenced") do |silenced_keys|
|
111
|
+
silenced_keys.select! do |key|
|
112
|
+
key =~ /^silence:#{subscription}:/
|
113
|
+
end
|
114
|
+
silenced_keys = pagination(silenced_keys)
|
115
|
+
fetch_silenced(silenced_keys) do |silenced|
|
116
|
+
@response_content = silenced
|
117
|
+
respond
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# GET /silenced/ids/:id
|
123
|
+
def get_silenced_id
|
124
|
+
id = parse_uri(SILENCED_ID_URI).first
|
125
|
+
@redis.smembers("silenced") do |silenced_keys|
|
126
|
+
silenced_keys.select! do |key|
|
127
|
+
key =~ /#{id.gsub('*', '\*')}$/
|
128
|
+
end
|
129
|
+
silenced_keys = pagination(silenced_keys)
|
130
|
+
fetch_silenced(silenced_keys) do |silenced|
|
131
|
+
if silenced.empty?
|
132
|
+
not_found!
|
133
|
+
else
|
134
|
+
@response_content = silenced.last
|
135
|
+
respond
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# GET /silenced/checks/:check
|
142
|
+
def get_silenced_check
|
143
|
+
check_name = parse_uri(SILENCED_CHECK_URI).first
|
144
|
+
@redis.smembers("silenced") do |silenced_keys|
|
145
|
+
silenced_keys.select! do |key|
|
146
|
+
key =~ /.*:#{check_name}$/
|
147
|
+
end
|
148
|
+
silenced_keys = pagination(silenced_keys)
|
149
|
+
fetch_silenced(silenced_keys) do |silenced|
|
150
|
+
@response_content = silenced
|
151
|
+
respond
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# POST /silenced/clear
|
157
|
+
def post_silenced_clear
|
158
|
+
rules = {
|
159
|
+
:id => {:type => String, :nil_ok => true},
|
160
|
+
:subscription => {:type => String, :nil_ok => true},
|
161
|
+
:check => {:type => String, :nil_ok => true, :regex => /\A[\w\.-]+\z/}
|
162
|
+
}
|
163
|
+
read_data(rules) do |data|
|
164
|
+
if !data[:id].nil? || (data[:subscription] || data[:check])
|
165
|
+
subscription = data.fetch(:subscription, "*")
|
166
|
+
check = data.fetch(:check, "*")
|
167
|
+
silenced_id = data[:id] || "#{subscription}:#{check}"
|
168
|
+
silenced_key = "silence:#{silenced_id}"
|
169
|
+
@redis.srem("silenced", silenced_key) do
|
170
|
+
@redis.del(silenced_key) do |deleted|
|
171
|
+
deleted ? no_content! : not_found!
|
172
|
+
end
|
173
|
+
end
|
174
|
+
else
|
175
|
+
bad_request!
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Routes
|
4
|
+
module Stashes
|
5
|
+
STASHES_URI = /^\/stashes$/
|
6
|
+
STASH_URI = /^\/stash(?:es)?\/(.*)$/
|
7
|
+
|
8
|
+
# POST /stash/:path or /stashes/:path
|
9
|
+
def post_stash
|
10
|
+
path = parse_uri(STASH_URI).first
|
11
|
+
read_data do |data|
|
12
|
+
@redis.set("stash:#{path}", Sensu::JSON.dump(data)) do
|
13
|
+
@redis.sadd("stashes", path) do
|
14
|
+
@response_content = {:path => path}
|
15
|
+
created!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# GET /stash/:path or /stashes/:path
|
22
|
+
def get_stash
|
23
|
+
path = parse_uri(STASH_URI).first
|
24
|
+
@redis.get("stash:#{path}") do |stash_json|
|
25
|
+
unless stash_json.nil?
|
26
|
+
@response_content = Sensu::JSON.load(stash_json)
|
27
|
+
respond
|
28
|
+
else
|
29
|
+
not_found!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# DELETE /stash/:path or /stashes/:path
|
35
|
+
def delete_stash
|
36
|
+
path = parse_uri(STASH_URI).first
|
37
|
+
@redis.exists("stash:#{path}") do |stash_exists|
|
38
|
+
if stash_exists
|
39
|
+
@redis.srem("stashes", path) do
|
40
|
+
@redis.del("stash:#{path}") do
|
41
|
+
no_content!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
else
|
45
|
+
not_found!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# GET /stashes
|
51
|
+
def get_stashes
|
52
|
+
@response_content = []
|
53
|
+
@redis.smembers("stashes") do |stashes|
|
54
|
+
unless stashes.empty?
|
55
|
+
stashes = pagination(stashes)
|
56
|
+
stashes.each_with_index do |path, index|
|
57
|
+
@redis.get("stash:#{path}") do |stash_json|
|
58
|
+
@redis.ttl("stash:#{path}") do |ttl|
|
59
|
+
unless stash_json.nil?
|
60
|
+
item = {
|
61
|
+
:path => path,
|
62
|
+
:content => Sensu::JSON.load(stash_json),
|
63
|
+
:expire => ttl
|
64
|
+
}
|
65
|
+
@response_content << item
|
66
|
+
else
|
67
|
+
@redis.srem("stashes", path)
|
68
|
+
end
|
69
|
+
if index == stashes.length - 1
|
70
|
+
respond
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
else
|
76
|
+
respond
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# POST /stashes
|
82
|
+
def post_stashes
|
83
|
+
rules = {
|
84
|
+
:path => {:type => String, :nil_ok => false},
|
85
|
+
:content => {:type => Hash, :nil_ok => false},
|
86
|
+
:expire => {:type => Integer, :nil_ok => true}
|
87
|
+
}
|
88
|
+
read_data(rules) do |data|
|
89
|
+
stash_key = "stash:#{data[:path]}"
|
90
|
+
@redis.set(stash_key, Sensu::JSON.dump(data[:content])) do
|
91
|
+
@redis.sadd("stashes", data[:path]) do
|
92
|
+
@response_content = {:path => data[:path]}
|
93
|
+
if data[:expire]
|
94
|
+
@redis.expire(stash_key, data[:expire]) do
|
95
|
+
created!
|
96
|
+
end
|
97
|
+
else
|
98
|
+
created!
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "sensu/api/routes/settings"
|
2
|
+
require "sensu/api/routes/info"
|
3
|
+
require "sensu/api/routes/health"
|
4
|
+
require "sensu/api/routes/clients"
|
5
|
+
require "sensu/api/routes/checks"
|
6
|
+
require "sensu/api/routes/request"
|
7
|
+
require "sensu/api/routes/events"
|
8
|
+
require "sensu/api/routes/resolve"
|
9
|
+
require "sensu/api/routes/aggregates"
|
10
|
+
require "sensu/api/routes/stashes"
|
11
|
+
require "sensu/api/routes/results"
|
12
|
+
require "sensu/api/routes/silenced"
|
13
|
+
|
14
|
+
module Sensu
|
15
|
+
module API
|
16
|
+
module Routes
|
17
|
+
include Settings
|
18
|
+
include Info
|
19
|
+
include Health
|
20
|
+
include Clients
|
21
|
+
include Checks
|
22
|
+
include Request
|
23
|
+
include Events
|
24
|
+
include Resolve
|
25
|
+
include Aggregates
|
26
|
+
include Stashes
|
27
|
+
include Results
|
28
|
+
include Silenced
|
29
|
+
|
30
|
+
GET_METHOD = "GET".freeze
|
31
|
+
HEAD_METHOD = "HEAD".freeze
|
32
|
+
POST_METHOD = "POST".freeze
|
33
|
+
DELETE_METHOD = "DELETE".freeze
|
34
|
+
OPTIONS_METHOD = "OPTIONS".freeze
|
35
|
+
|
36
|
+
GET_ROUTES = [
|
37
|
+
[SETTINGS_URI, :get_settings],
|
38
|
+
[INFO_URI, :get_info],
|
39
|
+
[HEALTH_URI, :get_health],
|
40
|
+
[CLIENTS_URI, :get_clients],
|
41
|
+
[CLIENT_URI, :get_client],
|
42
|
+
[CLIENT_HISTORY_URI, :get_client_history],
|
43
|
+
[CHECKS_URI, :get_checks],
|
44
|
+
[CHECK_URI, :get_check],
|
45
|
+
[EVENTS_URI, :get_events],
|
46
|
+
[EVENTS_CLIENT_URI, :get_events_client],
|
47
|
+
[EVENT_URI, :get_event],
|
48
|
+
[AGGREGATES_URI, :get_aggregates],
|
49
|
+
[AGGREGATE_URI, :get_aggregate],
|
50
|
+
[AGGREGATE_CLIENTS_URI, :get_aggregate_clients],
|
51
|
+
[AGGREGATE_CHECKS_URI, :get_aggregate_checks],
|
52
|
+
[AGGREGATE_RESULTS_SEVERITY_URI, :get_aggregate_results_severity],
|
53
|
+
[STASHES_URI, :get_stashes],
|
54
|
+
[STASH_URI, :get_stash],
|
55
|
+
[RESULTS_URI, :get_results],
|
56
|
+
[RESULTS_CLIENT_URI, :get_results_client],
|
57
|
+
[RESULT_URI, :get_result],
|
58
|
+
[SILENCED_URI, :get_silenced],
|
59
|
+
[SILENCED_ID_URI, :get_silenced_id],
|
60
|
+
[SILENCED_SUBSCRIPTION_URI, :get_silenced_subscription],
|
61
|
+
[SILENCED_CHECK_URI, :get_silenced_check]
|
62
|
+
]
|
63
|
+
|
64
|
+
ROUTES = {
|
65
|
+
GET_METHOD => GET_ROUTES,
|
66
|
+
HEAD_METHOD => GET_ROUTES,
|
67
|
+
POST_METHOD => [
|
68
|
+
[CLIENTS_URI, :post_clients],
|
69
|
+
[REQUEST_URI, :post_request],
|
70
|
+
[RESOLVE_URI, :post_resolve],
|
71
|
+
[STASHES_URI, :post_stashes],
|
72
|
+
[STASH_URI, :post_stash],
|
73
|
+
[RESULTS_URI, :post_results],
|
74
|
+
[SILENCED_URI, :post_silenced],
|
75
|
+
[SILENCED_CLEAR_URI, :post_silenced_clear]
|
76
|
+
],
|
77
|
+
DELETE_METHOD => [
|
78
|
+
[CLIENT_URI, :delete_client],
|
79
|
+
[CHECK_URI, :delete_check],
|
80
|
+
[EVENT_URI, :delete_event],
|
81
|
+
[AGGREGATE_URI, :delete_aggregate],
|
82
|
+
[STASH_URI, :delete_stash],
|
83
|
+
[RESULT_URI, :delete_result]
|
84
|
+
]
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
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
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "sensu/utilities"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Utilities
|
6
|
+
module PublishCheckRequest
|
7
|
+
include Sensu::Utilities
|
8
|
+
|
9
|
+
# Determine the Sensu Transport publish options for a
|
10
|
+
# subscription. If a subscription begins with a Transport pipe
|
11
|
+
# type, either "direct:" or "roundrobin:", the subscription uses
|
12
|
+
# a direct Transport pipe. If a subscription does not specify a
|
13
|
+
# Transport pipe type, a fanout Transport pipe is used.
|
14
|
+
#
|
15
|
+
# @param subscription [String]
|
16
|
+
# @param message [String]
|
17
|
+
# @return [Array] containing the Transport publish options:
|
18
|
+
# the Transport pipe type, pipe, and the message to be
|
19
|
+
# published.
|
20
|
+
def transport_publish_options(subscription, message)
|
21
|
+
_, raw_type = subscription.split(":", 2).reverse
|
22
|
+
case raw_type
|
23
|
+
when "direct", "roundrobin"
|
24
|
+
[:direct, subscription, message]
|
25
|
+
else
|
26
|
+
[:fanout, subscription, message]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Publish a check request to the Transport. A check request is
|
31
|
+
# composed of a check `:name`, an `:issued` timestamp, a check
|
32
|
+
# `:command` if available, and a check `:extension if available.
|
33
|
+
# The check request is published to a Transport pipe, for each
|
34
|
+
# of the check `:subscribers` in its definition, eg. "webserver".
|
35
|
+
# JSON serialization is used when publishing the check request
|
36
|
+
# payload to the Transport pipes. Transport errors are logged.
|
37
|
+
#
|
38
|
+
# @param check [Hash] definition.
|
39
|
+
def publish_check_request(check)
|
40
|
+
payload = check.reject do |key, value|
|
41
|
+
[:subscribers, :interval].include?(key)
|
42
|
+
end
|
43
|
+
payload[:issued] = Time.now.to_i
|
44
|
+
@logger.info("publishing check request", {
|
45
|
+
:payload => payload,
|
46
|
+
:subscribers => check[:subscribers]
|
47
|
+
})
|
48
|
+
check[:subscribers].each do |subscription|
|
49
|
+
options = transport_publish_options(subscription.to_s, Sensu::JSON.dump(payload))
|
50
|
+
@transport.publish(*options) do |info|
|
51
|
+
if info[:error]
|
52
|
+
@logger.error("failed to publish check request", {
|
53
|
+
:subscription => subscription,
|
54
|
+
:payload => payload,
|
55
|
+
:error => info[:error].to_s
|
56
|
+
})
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
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(deep_dup(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
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,39 @@
|
|
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
|
+
@redis.get("client:#{client_name}:signature") do |signature|
|
24
|
+
payload[:signature] = signature unless signature.nil?
|
25
|
+
@logger.info("publishing check result", :payload => payload)
|
26
|
+
@transport.publish(:direct, "results", Sensu::JSON.dump(payload)) do |info|
|
27
|
+
if info[:error]
|
28
|
+
@logger.error("failed to publish check result", {
|
29
|
+
:payload => payload,
|
30
|
+
:error => info[:error].to_s
|
31
|
+
})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "sensu/api/utilities/publish_check_result"
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
module API
|
5
|
+
module Utilities
|
6
|
+
module ResolveEvent
|
7
|
+
include PublishCheckResult
|
8
|
+
|
9
|
+
# Resolve an event. This method publishes a check result with
|
10
|
+
# a check status of `0` (OK) to resolve the event. The
|
11
|
+
# published check result uses `force_resolve` to ensure the
|
12
|
+
# event is resolved and removed from the registry, even if the
|
13
|
+
# current event has an event action of `flapping` etc.
|
14
|
+
#
|
15
|
+
# @param event_json [String] JSON formatted event data.
|
16
|
+
def resolve_event(event_json)
|
17
|
+
event = Sensu::JSON.load(event_json)
|
18
|
+
check = event[:check].merge(
|
19
|
+
:output => "Resolving on request of the API",
|
20
|
+
:status => 0,
|
21
|
+
:force_resolve => true
|
22
|
+
)
|
23
|
+
check.delete(:history)
|
24
|
+
publish_check_result(event[:client][:name], check)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Utilities
|
4
|
+
module ServersInfo
|
5
|
+
# Retreive the Sensu servers info.
|
6
|
+
#
|
7
|
+
# @yield [Hash] passes servers info to the callback/block.
|
8
|
+
def servers_info
|
9
|
+
info = []
|
10
|
+
if @redis.connected?
|
11
|
+
@redis.smembers("servers") do |servers|
|
12
|
+
unless servers.empty?
|
13
|
+
servers.each_with_index do |server_id, index|
|
14
|
+
@redis.get("server:#{server_id}") do |server_json|
|
15
|
+
unless server_json.nil?
|
16
|
+
server = Sensu::JSON.load(server_json)
|
17
|
+
if server[:timestamp] >= (Time.now.to_i - 30)
|
18
|
+
info << server
|
19
|
+
else
|
20
|
+
@redis.del("server:#{server_id}") do
|
21
|
+
@redis.srem("servers", server_id)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
else
|
25
|
+
@redis.srem("servers", server_id)
|
26
|
+
end
|
27
|
+
if index == servers.length - 1
|
28
|
+
yield(info)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else
|
33
|
+
yield(info)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
yield(info)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Utilities
|
4
|
+
module TransportInfo
|
5
|
+
# Retreive the Sensu Transport info, if the API is connected
|
6
|
+
# to it, keepalive messages and consumers, and results
|
7
|
+
# messages and consumers.
|
8
|
+
#
|
9
|
+
# @yield [Hash] passes Transport info to the callback/block.
|
10
|
+
def transport_info
|
11
|
+
info = {
|
12
|
+
:name => @settings[:transport][:name],
|
13
|
+
:keepalives => {
|
14
|
+
:messages => nil,
|
15
|
+
:consumers => nil
|
16
|
+
},
|
17
|
+
:results => {
|
18
|
+
:messages => nil,
|
19
|
+
:consumers => nil
|
20
|
+
},
|
21
|
+
:connected => false
|
22
|
+
}
|
23
|
+
if @transport.connected?
|
24
|
+
@transport.stats("keepalives") do |stats|
|
25
|
+
info[:keepalives] = stats
|
26
|
+
if @transport.connected?
|
27
|
+
@transport.stats("results") do |stats|
|
28
|
+
info[:results] = stats
|
29
|
+
info[:connected] = @transport.connected?
|
30
|
+
yield(info)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
yield(info)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
yield(info)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|