-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathhandler-sensu.rb
executable file
·153 lines (142 loc) · 5.05 KB
/
handler-sensu.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env ruby
# frozen_string_literal: false
#
##################
# Sensu Remediator
##################
#
# This plugin reads configuration from a check definition
# and triggers appropriate remediation actions (defined as
# other checks) via the Sensu API, when the occurrences and
# severities reach certain values.
#
# The severities should be a list of integers.
#
# The occurrences should be an array of Integers, or strings,
# where the strings are dash seperated integers or plus
# suffixed integers.
#
# By default, the remediation checks will be triggered on the
# the client where the check is failing. An array of
# subscriptions may be specified via a 'trigger_on' property
# outside of the 'remediation' dictionary (in the 'check' dictionary).
#
# Example:
#
# {
# "checks": {
# "check_something": {
# "command": "ps aux | grep cron",
# "interval": 60,
# "subscribers": ["application_server"],
# "handler": ["debug", "irc", "remediator"],
# "remediation": {
# "light_remediation": {
# "occurrences": [1, 2],
# "severities": [1]
# },
# "medium_remediation": {
# "occurrences": ["3-10"],
# "severities": [1]
# },
# "heavy_remediation": {
# "occurrences": ["1+"],
# "severities": [2]
# }
# }
# },
# "light_remediation": {
# "command": "/bin/something",
# "subscribers": [],
# "handler": ["debug", "irc"],
# "publish": false,
# },
# "medium_remediation": {
# "command": "/bin/something_else",
# "subscribers": [],
# "handler": ["debug", "irc"],
# "publish": false,
# },
# "heavy_remediation": {
# "command": "sudo reboot",
# "subscribers": [],
# "handler": ["debug", "irc"],
# "publish": false,
# }
# }
# }
# ===
#
# Copyright 2012 Nick Stielau <[email protected]>
#
# Released under the same terms as Sensu (the MIT license); see LICENSE
# for details.
require 'sensu-handler'
require 'English'
class Remediator < Sensu::Handler
# Override filter_repeated from Sensu::Handler.
# Remediations are not alerts.
def filter_repeated; end
def handle
client = @event['client']['name']
check = @event['check']['name']
remediations = @event['check']['remediation']
occurrences = @event['occurrences']
trigger_on = @event['check']['trigger_on']
severity = @event['check']['status'].to_i
puts "REMEDIATION: Evaluating remediation: #{client} #{check} "\
"#{remediations.inspect} #=#{occurrences} sev=#{severity}"
remediation_checks = parse_remediations(remediations, occurrences, severity)
# at some point we should come back and remove the old default subscription of [client]
subscribers = trigger_on ? @event['check']['trigger_on'] : ['client:' + client, client]
remediation_checks.each do |remediation_check|
puts "REMEDIATION: Triggering remediation check '#{remediation_check}' "\
"for #{[client].inspect} #{subscribers}"
response = trigger_remediation(remediation_check, subscribers)
puts "REMEDIATION: Received API Response (#{response.code}): "\
"#{response.body}, exiting."
end
end
# Examine the defined remediations and return an array of
# checks that should be triggered given the current occurrence
# count and severity.
def parse_remediations(remediations, occurrences, severity)
remediations_to_trigger = []
remediations.each do |check, conditions|
# Check remediations matching the current severity
next unless (conditions['severities'] || []).include?(severity)
# Check for remediations matching the current occurrence count
trigger = false
(conditions['occurrences'] || []).each do |value|
trigger = if value.is_a?(Integer) && occurrences == value then true
elsif value.to_s =~ /^\d+$/ && occurrences == $LAST_MATCH_INFO.to_a.first.to_i then true
# #YELLOW
elsif value.to_s =~ /^(\d+)-(\d+)$/ && Range.new($LAST_MATCH_INFO.to_a[1].to_i, $LAST_MATCH_INFO.to_a[2].to_i).to_a.include?(occurrences) then true # rubocop:disable LineLength
elsif value.to_s.match(/^(\d+)\+$/) && Range.new($LAST_MATCH_INFO.to_a[1].to_i, 9999).include?(occurrences) then true
else false
end
break if trigger
end
remediations_to_trigger << check if trigger
end
remediations_to_trigger
end
# Issue a check via the API
def trigger_remediation(check, subscribers)
if subscribers.class != Array
p "subscribers: #{subscribers} must be an array"
exit 3
elsif subscribers.first.class == Array
subscribers.flatten
p "subscribers: #{subscribers} must be a flat array of strings, we auto flattened: #{subscribers}"
end
api_request(:POST, '/request') do |req|
req.body = JSON.dump(
'check' => check,
'subscribers' => subscribers,
'creator' => 'sensu-plugins-sensu',
'reason' => 'Auto remediation triggered'
)
end
end
end