]> git.datanom.net - check_http.git/blob - check_actuator_health.py
Fix bug
[check_http.git] / check_actuator_health.py
1 #! /usr/bin/env python
2
3 ###############################################################################
4 # Nagios plugin check_actuator_health
5 #
6 # Notes
7 # - The RHEL boxes I work on are currently limited to Python 2.6.6, hence the
8 # use of (deprecated) optparse. If I can ever get them all updated to
9 # Python 2.7 (or better yet, 3.3), I'll switch to argparse
10 # - This template runs in 2.6-3.3. Any changes made will need to be appropriate
11 # to the Python distro you want to use
12 #
13 ###############################################################################
14
15 __author__ = 'mr.it@cbs.dk - Michael Rasmussen'
16 __version__= 0.1
17
18 try: # RHEL8 RHEL9
19 from optparse import OptionParser, OptionGroup #
20 import logging as log
21 import sys
22 import urllib3 as urllib # python3-urllib3-1.24.2-5.el8.noarch.rpm python3-urllib3-1.26.5-3.el9.noarch.rpm
23 import json
24 except:
25 sys.exit(3)
26
27 ## These will override any args passed to the script normally. Comment out after testing.
28 #testargs = '--help'
29 #testargs = '--version'
30 #testargs = '-vvv'
31 #testing = True
32
33 OK_RESPONSE = """
34 {
35 "status": "UP",
36 "components": {
37 "db": {
38 "status": "UP",
39 "details": {
40 "database": "PostgreSQL",
41 "validationQuery": "isValid()"
42 }
43 },
44 "diskSpace": {
45 "status": "UP",
46 "details": {
47 "total": 2013582688256,
48 "free": 1635574571008,
49 "threshold": 10485760,
50 "path": "/home/mir/git/soasi-course-catalog-course-target-adapter/.",
51 "exists": true
52 }
53 },
54 "ping": {
55 "status": "UP"
56 }
57 }
58 }"""
59 DOWN_RESPONSE = """
60 {
61 "status": "DOWN",
62 "components": {
63 "db": {
64 "status": "DOWN",
65 "components": {
66 "adapterDataSource": {
67 "status": "DOWN",
68 "details": {
69 "error": "org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection"
70 }
71 },
72 "es3DataSource": {
73 "status": "UP",
74 "details": {
75 "database": "Microsoft SQL Server",
76 "validationQuery": "isValid()"
77 }
78 },
79 "providersDataSource": {
80 "status": "DOWN",
81 "details": {
82 "error": "org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection"
83 }
84 }
85 }
86 },
87 "diskSpace": {
88 "status": "UP",
89 "details": {
90 "total": 1013309239296,
91 "free": 882010726400,
92 "threshold": 10485760,
93 "path": "C:\\Users\\hf.it\\Projects\\smart-integrations\\adapters\\target\\soasi-invigilation-report-target-adapter",
94 "exists": true
95 }
96 },
97 "ping": {
98 "status": "UP"
99 }
100 }
101 }
102 """
103 def main():
104 """ Main plugin logic goes here """
105
106 ## Parse command-line arguments
107 args, args2 = parse_args()
108
109 ## Uncomment to test logging levels against verbosity settings
110 # log.debug('debug message')
111 # log.info('info message')
112 # log.warning('warning message')
113 # log.error('error message')
114 # log.critical('critical message')
115 # log.fatal('fatal message')
116 options = vars(args)
117 keyword = options['keyword']
118 url = options['url']
119 agent = options['agent']
120 testing = options['testing']
121 if keyword is None or url is None:
122 message = "Keywork: {0} url: {1}".format(keyword, url)
123 status = 3
124 log.fatal(message)
125 else:
126 try:
127 if not testing:
128 req_headers = {
129 'User-Agent': agent
130 }
131 http = urllib.PoolManager()
132 response = http.request(
133 'GET', url, headers = req_headers
134 )
135 data = response.data.decode('utf-8').replace("\\"," ")
136 else:
137 data = DOWN_RESPONSE.replace("\\"," ")
138 data = json.loads(data)
139 if 'status' in data and data['status'] == keyword:
140 message = "UP"
141 status = 2
142 else:
143 status, message = gather_message(data)
144 except Exception as e:
145 log.fatal(e)
146 message = e
147 status = 3
148
149 gtfo(status, message)
150
151 def gather_message(json_data):
152 """ Assemble error messages """
153 status = 2
154 msg = None
155 try:
156 if 'components' in json_data:
157 components = json_data['components']
158 for component in components:
159 items = components[component]
160 if 'components' in items:
161 for item in items['components']:
162 if 'status' in items['components'][item] and items['components'][item]['status'].upper() == 'DOWN':
163 if msg is not None:
164 msg += "\n{0}: {1}".format(item, items['components'][item]['details']['error'])
165 else:
166 msg = "{0}: {1}".format(item, items['components'][item]['details']['error'])
167 else:
168 if 'status' in items and items['status'].upper() == 'DOWN':
169 if msg is not None:
170 if 'details' in items and 'error' in items['details']:
171 error = items['details']['error']
172 else:
173 error = "No error message"
174 if msg is not None:
175 msg += "\n{0}: {1}".format(component, error)
176 else:
177 msg = "{0}: {1}".format(component, error)
178 else:
179 return (3, msg)
180 except:
181 return (3, msg)
182 return (status, msg)
183
184
185 def parse_args():
186 """ Parse command-line arguments """
187
188 parser = OptionParser(usage='usage: %prog [-v|vv|vvv] [options]',
189 version='{0}: v.{1} by {2}'.format('%prog', __version__, __author__))
190
191 ## Verbosity (want this first, so it's right after --help and --version)
192 parser.add_option('-v', help='Set verbosity level',
193 action='count', default=0, dest='v')
194
195 ## CLI arguments specific to this script
196 group = OptionGroup(parser,'Plugin Options')
197 group.add_option('-a', '--agent', help="User agent for request. Default: Python-nagios",
198 default="Python-nagios", type='string')
199 group.add_option('-k', '--keyword', help="Keyword to search for in response", default=None)
200 group.add_option('-t', '--testing', help="Run in testing mode", default=False, action='store_true')
201 group.add_option('-u', '--url', help="URL to requested resource", default=None)
202
203 ## Common CLI arguments
204 #parser.add_option('-c', '--critical', help='Set the critical threshold. Default: %(default)s',
205 # default=97, type=float, dest='crit', metavar='##')
206 #parser.add_option('-w', '--warning', help='Set the warning threshold. Default: %(default)s',
207 # default=95, type=float, dest='warn', metavar='##')
208
209 parser.add_option_group(group)
210
211 ## Try to parse based on the testargs variable. If it doesn't exist, use args
212 try:
213 args, args2 = parser.parse_args(testargs.split())
214 except NameError:
215 args, args2 = parser.parse_args()
216
217 ## Set the logging level based on the -v arg
218 log.getLogger().setLevel([log.ERROR, log.WARN, log.INFO, log.DEBUG][args.v])
219
220 log.debug('Parsed arguments: {0}'.format(args))
221 log.debug('Other arguments: {0}'.format(args2))
222
223 return args, args2
224
225 def gtfo(exitcode, message=''):
226 """ Exit gracefully with exitcode and (optional) message """
227
228 log.debug('Exiting with status {0}. Message: {1}'.format(exitcode, message))
229
230 if message:
231 print(message)
232 exit(exitcode)
233
234 if __name__ == '__main__':
235 ## Initialize logging before hitting main, in case we need extra debuggability
236 log.basicConfig(level=log.DEBUG, format='%(asctime)s - %(funcName)s - %(levelname)s - %(message)s')
237 main()
This page took 0.078626 seconds and 6 git commands to generate.