6
6
# Released under the same terms as Sensu (the MIT license); see LICENSE
7
7
# for details.
8
8
9
+ '''
10
+ This provides a base SensuHandler class that can be used for writing
11
+ python-based Sensu handlers.
12
+ '''
13
+
9
14
from __future__ import print_function
10
15
import os
11
16
import sys
17
+ import json
12
18
import requests
13
19
try :
14
20
from urlparse import urlparse
15
21
except ImportError :
16
22
from urllib .parse import urlparse
17
- from utils import *
23
+ from sensu_plugin . utils import get_settings
18
24
19
25
20
26
class SensuHandler (object ):
27
+ '''
28
+ Class to be used as a basis for handlers.
29
+ '''
21
30
def __init__ (self ):
22
31
# Parse the stdin into a global event object
23
32
stdin = sys .stdin .read ()
@@ -40,8 +49,8 @@ def read_event(self, check_result):
40
49
self .event ['occurrences' ] = self .event .get ('occurrences' , 1 )
41
50
self .event ['check' ] = self .event .get ('check' , {})
42
51
self .event ['client' ] = self .event .get ('client' , {})
43
- except Exception as e :
44
- print ('error reading event: ' + e . message )
52
+ except Exception as exception : # pylint: disable=broad-except
53
+ print ('error reading event: ' + exception )
45
54
sys .exit (1 )
46
55
47
56
def handle (self ):
@@ -63,7 +72,7 @@ def filter(self):
63
72
self .filter_silenced ()
64
73
self .filter_dependencies ()
65
74
66
- if self .deprecated_occurrence_filtering_enabled ():
75
+ if self .deprecated_occurrence_filtering ():
67
76
print ('warning: occurrence filtering in sensu-plugin is' +
68
77
'deprecated, see http://bit.ly/sensu-plugin' )
69
78
self .filter_repeated ()
@@ -78,7 +87,7 @@ def deprecated_filtering_enabled(self):
78
87
'''
79
88
return self .event ['check' ].get ('enable_deprecated_filtering' , False )
80
89
81
- def deprecated_occurrence_filtering_enabled (self ):
90
+ def deprecated_occurrence_filtering (self ):
82
91
'''
83
92
Evaluates whether the event should be processed by the
84
93
filter_repeated method. Defaults to true, i.e. filter_repeated
@@ -94,23 +103,23 @@ def bail(self, msg):
94
103
'''
95
104
Gracefully terminate with message
96
105
'''
97
- client_name = self .event [ 'client' ] .get ('name ' , 'error:no-client-name' )
106
+ client_name = self .event .get ('client ' , 'error:no-client-name' )
98
107
check_name = self .event ['client' ].get ('name' , 'error:no-check-name' )
99
108
print ('{}: {}/{}' .format (msg , client_name , check_name ))
100
109
sys .exit (0 )
101
110
102
111
def get_api_settings (self ):
103
112
'''
104
- Return a hash of API settings derived first from ENV['SENSU_API_URL ']
113
+ Return a hash of API settings derived first from ENV['sensu_api_url ']
105
114
if set, then Sensu config `api` scope if configured, and finally
106
115
falling back to to ipv4 localhost address on default API port.
107
116
108
117
return dict
109
118
'''
110
119
111
- SENSU_API_URL = os .environ .get ('SENSU_API_URL ' )
112
- if SENSU_API_URL :
113
- uri = urlparse (SENSU_API_URL )
120
+ sensu_api_url = os .environ .get ('sensu_api_url ' )
121
+ if sensu_api_url :
122
+ uri = urlparse (sensu_api_url )
114
123
self .api_settings = {
115
124
'host' : '{0}//{1}' .format (uri .scheme , uri .hostname ),
116
125
'port' : uri .port ,
@@ -125,7 +134,10 @@ def get_api_settings(self):
125
134
'port' , 4567 )
126
135
127
136
# API requests
128
- def api_request (method , path , blk ):
137
+ def api_request (self , method , path ):
138
+ '''
139
+ Query Sensu api for information.
140
+ '''
129
141
if not hasattr (self , 'api_settings' ):
130
142
ValueError ('api.json settings not found' )
131
143
@@ -135,7 +147,6 @@ def api_request(method, path, blk):
135
147
_request = requests .post
136
148
137
149
domain = self .api_settings ['host' ]
138
- # TODO: http/https
139
150
uri = 'http://{}:{}{}' .format (domain , self .api_settings ['port' ], path )
140
151
if self .api_settings ['user' ] and self .api_settings ['password' ]:
141
152
auth = (self .api_settings ['user' ], self .api_settings ['password' ])
@@ -145,19 +156,32 @@ def api_request(method, path, blk):
145
156
return req
146
157
147
158
def stash_exists (self , path ):
159
+ '''
160
+ Query Sensu API for stash data.
161
+ '''
148
162
return self .api_request ('get' , '/stash' + path ).status_code == 200
149
163
150
164
def event_exists (self , client , check ):
151
- return self .api_request ('get' ,
152
- '/events/{}/{}' .format (client , check )
153
- ).status_code == 200
165
+ '''
166
+ Query Sensu API for event.
167
+ '''
168
+ return self .api_request (
169
+ 'get' ,
170
+ 'events/{}/{}' .format (client , check )
171
+ ).status_code == 200
154
172
155
173
# Filters
156
174
def filter_disabled (self ):
175
+ '''
176
+ Determine whether a check is disabled and shouldn't handle.
177
+ '''
157
178
if self .event ['check' ]['alert' ] is False :
158
- bail ('alert disabled' )
179
+ self . bail ('alert disabled' )
159
180
160
181
def filter_silenced (self ):
182
+ '''
183
+ Determine whether a check is silenced and shouldn't handle.
184
+ '''
161
185
stashes = [
162
186
('client' , '/silence/{}' .format (self .event ['client' ]['name' ])),
163
187
('check' , '/silence/{}/{}' .format (
@@ -166,17 +190,18 @@ def filter_silenced(self):
166
190
('check' , '/silence/all/{}' .format (self .event ['check' ]['name' ]))
167
191
]
168
192
for scope , path in stashes :
169
- if stash_exists (path ):
170
- bail (scope + ' alerts silenced' )
171
- # TODO: Timeout for querying Sensu API?
172
- # More appropriate in the api_request method?
193
+ if self .stash_exists (path ):
194
+ self .bail (scope + ' alerts silenced' )
173
195
174
196
def filter_dependencies (self ):
197
+ '''
198
+ Determine whether a check has dependencies.
199
+ '''
175
200
dependencies = self .event ['check' ].get ('dependencies' , None )
176
201
if dependencies is None or not isinstance (dependencies , list ):
177
202
return
178
203
for dependency in self .event ['check' ]['dependencies' ]:
179
- if len ( str (dependency )) == 0 :
204
+ if not str (dependency ):
180
205
continue
181
206
dependency_split = tuple (dependency .split ('/' ))
182
207
# If there's a dependency on a check from another client, then use
@@ -187,9 +212,12 @@ def filter_dependencies(self):
187
212
client = self .event ['client' ]['name' ]
188
213
check = dependency_split [0 ]
189
214
if self .event_exists (client , check ):
190
- bail ('check dependency event exists' )
215
+ self . bail ('check dependency event exists' )
191
216
192
217
def filter_repeated (self ):
218
+ '''
219
+ Determine whether a check is repeating.
220
+ '''
193
221
defaults = {
194
222
'occurrences' : 1 ,
195
223
'interval' : 30 ,
@@ -198,8 +226,7 @@ def filter_repeated(self):
198
226
199
227
# Override defaults with anything defined in the settings
200
228
if isinstance (self .settings ['sensu_plugin' ], dict ):
201
- defaults .update (settings ['sensu_plugin' ])
202
- end
229
+ defaults .update (self .settings ['sensu_plugin' ])
203
230
204
231
occurrences = int (self .event ['check' ].get (
205
232
'occurrences' , defaults ['occurrences' ]))
@@ -209,7 +236,7 @@ def filter_repeated(self):
209
236
'refresh' , defaults ['refresh' ]))
210
237
211
238
if self .event ['occurrences' ] < occurrences :
212
- bail ('not enough occurrences' )
239
+ self . bail ('not enough occurrences' )
213
240
214
241
if (self .event ['occurrences' ] > occurrences and
215
242
self .event ['action' ] == 'create' ):
@@ -220,4 +247,4 @@ def filter_repeated(self):
220
247
(self .event ['occurrences' ] - occurrences ) % number == 0 ):
221
248
return
222
249
223
- bail ('only handling every ' + str (number ) + ' occurrences' )
250
+ self . bail ('only handling every ' + str (number ) + ' occurrences' )
0 commit comments