Merge pull request #60 from drewkerrigan/http-json

Parse JSON on HTTPError, if JSON in response
This commit is contained in:
Markus Opolka 2020-07-03 09:02:14 +02:00 committed by GitHub
commit 41279cad2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 147 additions and 28 deletions

View File

@ -1,5 +1,5 @@
# pylint config
[MESSAGES CONTROL]
disable=line-too-long, redefined-outer-name, too-many-arguments, too-many-instance-attributes, fixme, invalid-name, superfluous-parens, missing-function-docstring, missing-module-docstring, multiple-imports, no-else-return, too-many-return-statements
disable=line-too-long, redefined-outer-name, too-many-arguments, too-many-instance-attributes, fixme, invalid-name, superfluous-parens, missing-function-docstring, missing-module-docstring, multiple-imports, no-else-return, too-many-return-statements, too-many-branches, too-many-statements
[MASTER]
ignore-patterns=^test.*

View File

@ -424,7 +424,7 @@ def parseArgs(args):
parser.add_argument('-s', '--ssl', action='store_true',
help='use TLS to connect to remote host')
parser.add_argument('-H', '--host', dest='host',
required=not ('-V' in sys.argv or '--version' in sys.argv),
required=not ('-V' in args or '--version' in args),
help='remote host to query')
parser.add_argument('-k', '--insecure', action='store_true',
help='do not check server SSL certificate')
@ -524,10 +524,12 @@ def debugPrint(debug_flag, message, pretty_flag=False):
print(message)
# Program entry point
if __name__ == "__main__":
def main(cliargs):
"""
Main entrypoint for CLI
"""
args = parseArgs(sys.argv[1:])
args = parseArgs(cliargs)
nagios = NagiosHelper()
context = None
@ -607,7 +609,11 @@ if __name__ == "__main__":
json_data = response.read()
except HTTPError as e:
nagios.append_unknown(" HTTPError[%s], url:%s" % (str(e.code), url))
# Try to recover from HTTP Error, if there is JSON in the response
if "json" in e.info().get_content_subtype():
json_data = e.read()
else:
nagios.append_unknown(" HTTPError[%s], url:%s" % (str(e.code), url))
except URLError as e:
nagios.append_critical(" URLError[%s], url:%s" % (str(e.reason), url))
@ -630,4 +636,9 @@ if __name__ == "__main__":
print(nagios.getMessage())
sys.exit(nagios.getCode())
if __name__ == "__main__":
# Program entry point
main(sys.argv[1:])
#EOF

9
makefile Normal file
View File

@ -0,0 +1,9 @@
.PHONY: lint test coverage
lint:
python3 -m pylint check_http_json.py
test:
python3 -m unittest discover
coverage:
python3 -m coverage run -m unittest discover
python3 -m coverage report -m --include check_http_json.py

2
test/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
coverage==5.0.3
pylint==2.4.4

44
test/test_cli.py Normal file
View File

@ -0,0 +1,44 @@
#!/usr/bin/env python3
import unittest
import unittest.mock as mock
import sys
import os
sys.path.append('..')
from check_http_json import debugPrint
class CLITest(unittest.TestCase):
"""
Tests for CLI
"""
def setUp(self):
"""
Defining the exitcodes
"""
self.exit_0 = 0 << 8
self.exit_1 = 1 << 8
self.exit_2 = 2 << 8
self.exit_3 = 3 << 8
def test_debugprint(self):
with mock.patch('builtins.print') as mock_print:
debugPrint(True, 'debug')
mock_print.assert_called_once_with('debug')
def test_debugprint_pprint(self):
with mock.patch('check_http_json.pprint') as mock_pprint:
debugPrint(True, 'debug', True)
mock_pprint.assert_called_once_with('debug')
def test_cli_without_params(self):
command = '/usr/bin/env python3 check_http_json.py > /dev/null 2>&1'
status = os.system(command)
self.assertEqual(status, self.exit_2)

View File

@ -8,37 +8,90 @@ import os
sys.path.append('..')
from check_http_json import debugPrint
from check_http_json import main
class MockResponse():
def __init__(self, status_code=200, content='{}'):
self.status_code = status_code
self.content = content
def read(self):
return self.content
class MainTest(unittest.TestCase):
"""
Tests for main
Tests for Main
"""
def setUp(self):
"""
Defining the exitcodes
"""
@mock.patch('builtins.print')
def test_main_version(self, mock_print):
args = ['--version']
self.exit_0 = 0 << 8
self.exit_1 = 1 << 8
self.exit_2 = 2 << 8
self.exit_3 = 3 << 8
with self.assertRaises(SystemExit) as test:
main(args)
def test_debugprint(self):
with mock.patch('builtins.print') as mock_print:
debugPrint(True, 'debug')
mock_print.assert_called_once_with('debug')
mock_print.assert_called_once()
self.assertEqual(test.exception.code, 0)
def test_debugprint_pprint(self):
with mock.patch('check_http_json.pprint') as mock_pprint:
debugPrint(True, 'debug', True)
mock_pprint.assert_called_once_with('debug')
@mock.patch('builtins.print')
@mock.patch('urllib.request.urlopen')
def test_main_with_ssl(self, mock_request, mock_print):
args = '-H localhost --ssl'.split(' ')
def test_cli_without_params(self):
mock_request.return_value = MockResponse()
command = '/usr/bin/env python3 check_http_json.py > /dev/null 2>&1'
status = os.system(command)
with self.assertRaises(SystemExit) as test:
main(args)
self.assertEqual(status, self.exit_2)
self.assertEqual(test.exception.code, 0)
@mock.patch('builtins.print')
@mock.patch('urllib.request.urlopen')
def test_main_with_parse_error(self, mock_request, mock_print):
args = '-H localhost'.split(' ')
mock_request.return_value = MockResponse(content='not JSON')
with self.assertRaises(SystemExit) as test:
main(args)
self.assertTrue('Parser error' in str(mock_print.call_args))
self.assertEqual(test.exception.code, 3)
@mock.patch('builtins.print')
def test_main_with_url_error(self, mock_print):
args = '-H localhost'.split(' ')
with self.assertRaises(SystemExit) as test:
main(args)
self.assertTrue('URLError' in str(mock_print.call_args))
self.assertEqual(test.exception.code, 3)
@mock.patch('builtins.print')
@mock.patch('urllib.request.urlopen')
def test_main_with_http_error_no_json(self, mock_request, mock_print):
args = '-H localhost'.split(' ')
mock_request.return_value = MockResponse(content='not JSON', status_code=503)
with self.assertRaises(SystemExit) as test:
main(args)
self.assertTrue('Parser error' in str(mock_print.call_args))
self.assertEqual(test.exception.code, 3)
@mock.patch('builtins.print')
@mock.patch('urllib.request.urlopen')
def test_main_with_http_error_valid_json(self, mock_request, mock_print):
args = '-H localhost'.split(' ')
mock_request.return_value = MockResponse(status_code=503)
with self.assertRaises(SystemExit) as test:
main(args)
self.assertEqual(test.exception.code, 0)