From d9ee817dfcef7ba325af147f80ac2e45451eb154 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 18 Mar 2024 08:34:39 +0100 Subject: [PATCH 1/4] Update dev-requirements --- .gitignore | 1 + requirements-dev.txt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6d55d97..d2d38e6 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ var/ .installed.cfg *.egg .venv/ +venv/ # PyInstaller # Usually these files are written by a python script from a template diff --git a/requirements-dev.txt b/requirements-dev.txt index e84cd4e..ef4b7b4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,2 @@ -coverage==6.4.4 -pylint==2.15.2 +coverage==6.5.0 +pylint==2.17.7 From e96bba0eb8f38a2328adff1827182f29cdd41356 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 18 Mar 2024 09:32:31 +0100 Subject: [PATCH 2/4] Refactor for a leaner main function - Also added tests for TLS options --- check_http_json.py | 134 +++++++++++++++++++++++-------------------- test/test_main.py | 34 +++++++++++ test/tls/ca-root.pem | 21 +++++++ test/tls/cert.pem | 19 ++++++ test/tls/key.pem | 27 +++++++++ 5 files changed, 172 insertions(+), 63 deletions(-) create mode 100644 test/tls/ca-root.pem create mode 100644 test/tls/cert.pem create mode 100644 test/tls/key.pem diff --git a/check_http_json.py b/check_http_json.py index 3eb7c50..1313f5e 100755 --- a/check_http_json.py +++ b/check_http_json.py @@ -528,6 +528,75 @@ def debugPrint(debug_flag, message, pretty_flag=False): print(message) +def prepare_context(args): + """ + Prepare TLS Context + """ + nagios = NagiosHelper() + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.options |= ssl.OP_NO_SSLv2 + context.options |= ssl.OP_NO_SSLv3 + + if args.insecure: + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + else: + context.verify_mode = ssl.CERT_OPTIONAL + context.load_default_certs() + if args.cacert: + try: + context.load_verify_locations(args.cacert) + except ssl.SSLError: + nagios.append_unknown('Error loading SSL CA cert "%s"!' % args.cacert) + if args.cert: + try: + context.load_cert_chain(args.cert, keyfile=args.key) + except ssl.SSLError: + if args.key: + nagios.append_unknown('Error loading SSL cert. Make sure key "%s" belongs to cert "%s"!' % (args.key, args.cert)) + else: + nagios.append_unknown('Error loading SSL cert. Make sure "%s" contains the key as well!' % (args.cert)) + + if nagios.getCode() != OK_CODE: + print(nagios.getMessage()) + sys.exit(nagios.getCode()) + + return context + + +def make_request(args, url, context): + """ + Performs the actual request to the given URL + """ + req = urllib.request.Request(url, method=args.method) + req.add_header("User-Agent", "check_http_json") + if args.auth: + authbytes = str(args.auth).encode() + base64str = base64.encodebytes(authbytes).decode().replace('\n', '') + req.add_header('Authorization', 'Basic %s' % base64str) + if args.headers: + headers = json.loads(args.headers) + debugPrint(args.debug, "Headers:\n %s" % headers) + for header in headers: + req.add_header(header, headers[header]) + if args.timeout and args.data: + databytes = str(args.data).encode() + response = urllib.request.urlopen(req, timeout=args.timeout, + data=databytes, context=context) + elif args.timeout: + response = urllib.request.urlopen(req, timeout=args.timeout, + context=context) + elif args.data: + databytes = str(args.data).encode() + response = urllib.request.urlopen(req, data=databytes, context=context) + else: + # pylint: disable=consider-using-with + response = urllib.request.urlopen(req, context=context) + + return response.read() + + def main(cliargs): """ Main entrypoint for CLI @@ -543,42 +612,7 @@ def main(cliargs): if args.ssl: url = "https://%s" % args.host - - context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - context.options |= ssl.OP_NO_SSLv2 - context.options |= ssl.OP_NO_SSLv3 - - if args.insecure: - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - else: - context.verify_mode = ssl.CERT_OPTIONAL - context.load_default_certs() - if args.cacert: - try: - context.load_verify_locations(args.cacert) - except ssl.SSLError: - nagios.append_unknown( - 'Error loading SSL CA cert "%s"!' - % args.cacert) - - if args.cert: - try: - context.load_cert_chain(args.cert, keyfile=args.key) - except ssl.SSLError: - if args.key: - nagios.append_unknown( - 'Error loading SSL cert. Make sure key "%s" belongs to cert "%s"!' - % (args.key, args.cert)) - else: - nagios.append_unknown( - 'Error loading SSL cert. Make sure "%s" contains the key as well!' - % (args.cert)) - - if nagios.getCode() != OK_CODE: - print(nagios.getMessage()) - sys.exit(nagios.getCode()) - + context = prepare_context(args) else: url = "http://%s" % args.host if args.port: @@ -590,33 +624,7 @@ def main(cliargs): json_data = '' try: - req = urllib.request.Request(url, method=args.method) - req.add_header("User-Agent", "check_http_json") - if args.auth: - authbytes = str(args.auth).encode() - base64str = base64.encodebytes(authbytes).decode().replace('\n', '') - req.add_header('Authorization', 'Basic %s' % base64str) - if args.headers: - headers = json.loads(args.headers) - debugPrint(args.debug, "Headers:\n %s" % headers) - for header in headers: - req.add_header(header, headers[header]) - if args.timeout and args.data: - databytes = str(args.data).encode() - response = urllib.request.urlopen(req, timeout=args.timeout, - data=databytes, context=context) - elif args.timeout: - response = urllib.request.urlopen(req, timeout=args.timeout, - context=context) - elif args.data: - databytes = str(args.data).encode() - response = urllib.request.urlopen(req, data=databytes, context=context) - else: - # pylint: disable=consider-using-with - response = urllib.request.urlopen(req, context=context) - - json_data = response.read() - + json_data = make_request(args, url, context) except HTTPError as e: # Try to recover from HTTP Error, if there is JSON in the response if "json" in e.info().get_content_subtype(): diff --git a/test/test_main.py b/test/test_main.py index a531af7..0949f2f 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -95,3 +95,37 @@ def test_main_with_http_error_valid_json(self, mock_request, mock_print): main(args) self.assertEqual(test.exception.code, 0) + + @mock.patch('builtins.print') + def test_main_with_tls(self, mock_print): + args = ['-H', 'localhost', + '--ssl', + '--cacert', + 'test/tls/ca-root.pem', + '--cert', + 'test/tls/cert.pem', + '--key', + 'test/tls/key.pem'] + + with self.assertRaises(SystemExit) as test: + main(args) + + self.assertTrue('https://localhost' in str(mock_print.call_args)) + self.assertEqual(test.exception.code, 3) + + @mock.patch('builtins.print') + def test_main_with_tls_wrong_ca(self, mock_print): + args = ['-H', 'localhost', + '--ssl', + '--cacert', + 'test/tls/key.pem', + '--cert', + 'test/tls/cert.pem', + '--key', + 'test/tls/key.pem'] + + with self.assertRaises(SystemExit) as test: + main(args) + + self.assertTrue('Error loading SSL CA' in str(mock_print.call_args)) + self.assertEqual(test.exception.code, 3) diff --git a/test/tls/ca-root.pem b/test/tls/ca-root.pem new file mode 100644 index 0000000..c09e8ec --- /dev/null +++ b/test/tls/ca-root.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIUB6EZDl3ajJgJsoLzyC9DrOQQpKowDQYJKoZIhvcNAQEN +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yNDAzMTgwODE5MDhaGA8yMDUx +MDgwMzA4MTkwOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALVxioj+6zw6Snr+B1JOivC8Of6YptVYym5ICiHX +wjpbSVVe+Py/P2LDb/uQ1QkAENlpvChFqSaRBZU5keXYS/DaFb2Evb2/zf5qIdWU +2ju8B5V13gXSeaNNetyEn1Ivvk0lOCQo2RwEZXuStpLS4Q32rkRBvkoL+RXDc1NX +c3RwcU1p9ybgBqAC7FYdV82sgHGugIrbzkjfFREJXp1AnqvKAdk39b1CnPxfmPZC +nzPPetfr3iivH8yVO5rodU/LDtQNph22JR94YvPB89QO+bZ9bw2GHtPdAKFew9HF +UxM1fmy381Mq2iS3KUq5vsC1jMe8slUAIFYEDzoPvOz+MpcCAwEAAaNTMFEwHQYD +VR0OBBYEFOmCb+JnMzX29hwgtXSzrN+m6mTDMB8GA1UdIwQYMBaAFOmCb+JnMzX2 +9hwgtXSzrN+m6mTDMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQENBQADggEB +AAkTD8K4UO4uO4i6p2BCofbhVm9LYA0ulmLO8Uro0U491TeEDOQpgMFAK+b2gZIU +zvDHoCMn3UPVxHKl7XzDgLZVkYYEc2s9vArxk5vSnFmh3XvlDu2SO5gSLB2sf68A +2+Jz2x6z9tjWWdZCGJWU/iwMbG2Y3JMHyv1NMF8cyOclJaSDNBAwF5c5sdlGTLKb +WHGXzVqHSAFlGcHtQrcEKclHiuzw2G3LZzwghGk0XzxwvyKrnAEy408RY0mfNLtz +32KHqYtrip0RYlGWKP7/7q6i0D8muEFW/I4emFI0z0I/1CcYZZS8tQkWaPf/wCN0 +llTD1kKJACsIMaqkkyy+EZM= +-----END CERTIFICATE----- diff --git a/test/tls/cert.pem b/test/tls/cert.pem new file mode 100644 index 0000000..3ae00a0 --- /dev/null +++ b/test/tls/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDzCCAfcCFBOrBcHIH2x9xcUyUeDid0cvBxWtMA0GCSqGSIb3DQEBDQUAMEUx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjQwMzE4MDgxOTM1WhgPMjA1MTA4MDMw +ODE5MzVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD +VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEeMA0GCSqGSIb3DQEBAQUA +A4IBCwAwggEGAoH+ALuzyIhEATF5YyAOsXKfr2mttF2HyJvEscGcoA7YetT57bjJ +5lg944kc3QH/wTEdrGda3cwh3OXdUuyR7Wrm9jPw38hMArx/fWPkiISOShrUSHGd +Qyy2bT+zxBaUo+pomyrlqlgwGlbxuwTAlTSFcI+i7yXrckl2HRj40EW4FNsYpPzv +maxRXs0kg0J2JLTYF+fHlqlYbSX/hRU9wz2DYfkRSS0+OYJNSmqK0jayUsdZYurG +gbPwOCgQ0QxLLh7P8z4sOanRowqUzqTI77cyUugEJRyoi+LJr4r0EwMTBX3STgPh +S9B78+LNvwOrLrZFUhr144RfO9QPLnz0uWcCAwEAATANBgkqhkiG9w0BAQ0FAAOC +AQEAeIR21PfLzgpL7WDBE2KgwI78nVc1wY9nwoAxSBzHjS0Olve3r9MaVzAKn5ZS +xHtv8oroXjhTcczCIzxii6Imp6u0iIr3QVBIceofxrH3aWmICURcC9l+dIiY6sk9 +Ct8P8gm/Erv2iF/7bnsARwDnw0f41fC9eXtHZ7WLRQrc7tLHpjL0Z7bT77ysQJVK +C1SWtBnq3afmwH3R1wVHENn0JVFQpBp+vqWU5KIlvjcz49yPU+aNODk1rJsHMlgS +x2iddwF31GNOxNfXtw8fdw4UDUl2wYoZ45w2e2pXt4pbN43m0Wys1eQZdk3tyR6G +AZOLP05073mLtbVlFRmcTdXIGg== +-----END CERTIFICATE----- diff --git a/test/tls/key.pem b/test/tls/key.pem new file mode 100644 index 0000000..b2b18bb --- /dev/null +++ b/test/tls/key.pem @@ -0,0 +1,27 @@ +-----BEGIN PRIVATE KEY----- +MIIEqAIBADANBgkqhkiG9w0BAQEFAASCBJIwggSOAgEAAoH+ALuzyIhEATF5YyAO +sXKfr2mttF2HyJvEscGcoA7YetT57bjJ5lg944kc3QH/wTEdrGda3cwh3OXdUuyR +7Wrm9jPw38hMArx/fWPkiISOShrUSHGdQyy2bT+zxBaUo+pomyrlqlgwGlbxuwTA +lTSFcI+i7yXrckl2HRj40EW4FNsYpPzvmaxRXs0kg0J2JLTYF+fHlqlYbSX/hRU9 +wz2DYfkRSS0+OYJNSmqK0jayUsdZYurGgbPwOCgQ0QxLLh7P8z4sOanRowqUzqTI +77cyUugEJRyoi+LJr4r0EwMTBX3STgPhS9B78+LNvwOrLrZFUhr144RfO9QPLnz0 +uWcCAwEAAQKB/UQAYzMy5/fDkWzoxdLQFV3E56ZG7h+4x+lr0/Ts6rtD/KLIyqHH +ciqXgV4bCSPBK1eabOZqkjvYzhUU3R2wpRu2NWy8VPVzfrr07ZyQbDqCE+jNX6vQ +P44nk2/W0/e1hBmrcOZYLwK2utmC58tKWLhBAEENpq8EkpAcfF/1y9aRHKYwNnH7 +vouoQibN5NTs5m8s0VyjRTDwRZja98eWnn5NfU3orqYO8fSlF6CyzDtoyhMco6zR +0skBgMzRYCRTuJpV+KekC7XFYyiJ6XZN5DKLbbqP6Y7YR8wjyFEruoGCS0mZH2H0 +9/rhTsJram1B2zohXHPsHJGGGv12/7kCfw5C7yda+8Yv0NmRp1F+EJYb75SCAWIP +kzN/xvjP2bMKa6oSzU0DOga3Wc4ijJHDaND8rqdPqQe3zXFr1nPdBrybLSJ6k5CN +4Dd6ENJWVWino0L460kpLtlBG6TsgmB8bkwhjWVE6Vgt4Vila+a3TGRXeniaRzdw +icNOtMrjYlUCfw0pWEvO2uFq0DbNZbmzC2j5ClFcU96CAl4AqKG2PiGnuSy9TKVZ +c5OiXFmyoig7v4LJzaKLSqVIN4hVBU80/MlhvG+dpeimvLaQKNtlZQethIs5hXlB +R1XfaPhq6BQiYmQ3tufyS/0Es2OY+Cs3LU1uDB8qVzonlmnIi69OwMsCfwRPISfJ +C+4UIIy8v8uVxbk1c6xxo61Xe2jCIQKo+uRoL6PRzoqIgQ3qdI4eTk70tkT/NF6F +aVNVrBOrO78Cd7ihQn/6fX/d/nOExHRpdaELlf70a1NNyEQIsiug8rvonQMP2ENT +ERZ9tmssgG/Tzpc6/1xVcVNFA7spmuL61YkCfwnu2zGTc0PO7kd96rkktIbL9YqD +6NQ0QH8bdildtjSGNc3bLB5ajUytq48Sryk4NogJr8Vt5K8q+qZMrE4kCmgd+C4w +x4b3V9Ncp0k1k/MgdLjyd5aUurbHfpyFapPPg3xpRAR3q/vP8WdIintrECiw1jsr +JFvChtVdQnbTM9MCfw41RcjNwCaIG+uXc8bD6Yf+NyXD8zP6ZDywmBlkMWlGSzx4 +xM8J+wQiQsNWthDBbF7inJc+lbtJiEe4YOPkbjCYVZRHribL65HKJlEUv6M9bvQo +3P1DS5tDrwo6z9UPs4tD1SgF9fDu/xA7fwPF1RTvuW07MhFJWlDo4FSWS9c= +-----END PRIVATE KEY----- From 4fbb0c828a5eaf3d0ef1daa812bddf2975c56ee2 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 18 Mar 2024 10:18:04 +0100 Subject: [PATCH 3/4] Add flag to override URL unreachable state - I refactored the Nagios helper a bit to integrate this functionality a bit simpler. Before we had distinct methods on the helper that added warn,crit,unko message, now there's a general method that takes an int as parameter. This way we avoid if-else structures for the new functionality. --- check_http_json.py | 44 ++++++++++++++++++++---------------- test/test_check_http_json.py | 6 ++--- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/check_http_json.py b/check_http_json.py index 1313f5e..63142f8 100755 --- a/check_http_json.py +++ b/check_http_json.py @@ -69,20 +69,19 @@ def getCode(self): code = UNKNOWN_CODE return code - def append_warning(self, warning_message): - self.warning_message += warning_message - - def append_critical(self, critical_message): - self.critical_message += critical_message - - def append_unknown(self, unknown_message): - self.unknown_message += unknown_message + def append_message(self, code, msg): + if code > 2 or code < 0: + self.unknown_message += msg + if code == 1: + self.warning_message += msg + if code == 2: + self.critical_message += msg def append_metrics(self, metrics): (performance_data, warning_message, critical_message) = metrics self.performance_data += performance_data - self.append_warning(warning_message) - self.append_critical(critical_message) + self.append_message(WARNING_CODE, warning_message) + self.append_message(CRITICAL_CODE, critical_message) class JsonHelper: @@ -444,6 +443,8 @@ def parseArgs(args): parser.add_argument('-p', '--path', dest='path', help='Path') parser.add_argument('-t', '--timeout', type=int, help='Connection timeout (seconds)') + parser.add_argument('--unreachable-state', type=int, default=3, + help='Exit with specified code if URL unreachable. Examples: 1 for Warning, 2 for Critical, 3 for Unknown (default: 3)') parser.add_argument('-B', '--basic-auth', dest='auth', help='Basic auth string "username:password"') parser.add_argument('-D', '--data', dest='data', @@ -548,15 +549,15 @@ def prepare_context(args): try: context.load_verify_locations(args.cacert) except ssl.SSLError: - nagios.append_unknown('Error loading SSL CA cert "%s"!' % args.cacert) + nagios.append_message(UNKNOWN_CODE, 'Error loading SSL CA cert "%s"!' % args.cacert) if args.cert: try: context.load_cert_chain(args.cert, keyfile=args.key) except ssl.SSLError: if args.key: - nagios.append_unknown('Error loading SSL cert. Make sure key "%s" belongs to cert "%s"!' % (args.key, args.cert)) + nagios.append_message(UNKNOWN_CODE, 'Error loading SSL cert. Make sure key "%s" belongs to cert "%s"!' % (args.key, args.cert)) else: - nagios.append_unknown('Error loading SSL cert. Make sure "%s" contains the key as well!' % (args.cert)) + nagios.append_message(UNKNOWN_CODE, 'Error loading SSL cert. Make sure "%s" contains the key as well!' % (args.cert)) if nagios.getCode() != OK_CODE: print(nagios.getMessage()) @@ -630,24 +631,29 @@ def main(cliargs): if "json" in e.info().get_content_subtype(): json_data = e.read() else: - nagios.append_unknown(" HTTPError[%s], url:%s" % (str(e.code), url)) + nagios.append_message(UNKNOWN_CODE, " Could not find JSON in HTTP body. HTTPError[%s], url:%s" % (str(e.code), url)) except URLError as e: - nagios.append_critical(" URLError[%s], url:%s" % (str(e.reason), url)) + # Some users might prefer another exit code if the URL wasn't reached + exit_code = args.unreachable_state + nagios.append_message(exit_code, " URLError[%s], url:%s" % (str(e.reason), url)) + # Since we don't got any data, we can simply exit + print(nagios.getMessage()) + sys.exit(nagios.getCode()) try: data = json.loads(json_data) except ValueError as e: - nagios.append_unknown(" Parser error: %s" % str(e)) + nagios.append_message(UNKNOWN_CODE, " JSON Parser error: %s" % str(e)) else: debugPrint(args.debug, 'json:') debugPrint(args.debug, data, True) # Apply rules to returned JSON data processor = JsonRuleProcessor(data, args) - nagios.append_warning(processor.checkWarning()) - nagios.append_critical(processor.checkCritical()) + nagios.append_message(WARNING_CODE, processor.checkWarning()) + nagios.append_message(CRITICAL_CODE, processor.checkCritical()) nagios.append_metrics(processor.checkMetrics()) - nagios.append_unknown(processor.checkUnknown()) + nagios.append_message(UNKNOWN_CODE, processor.checkUnknown()) # Print Nagios specific string and exit appropriately print(nagios.getMessage()) diff --git a/test/test_check_http_json.py b/test/test_check_http_json.py index 73904c7..3f2f8eb 100644 --- a/test/test_check_http_json.py +++ b/test/test_check_http_json.py @@ -84,10 +84,10 @@ def check_data(self, args, jsondata, code): data = json.loads(jsondata) nagios = NagiosHelper() processor = JsonRuleProcessor(data, args) - nagios.append_warning(processor.checkWarning()) - nagios.append_critical(processor.checkCritical()) + nagios.append_message(WARNING_CODE, processor.checkWarning()) + nagios.append_message(CRITICAL_CODE, processor.checkCritical()) nagios.append_metrics(processor.checkMetrics()) - nagios.append_unknown(processor.checkUnknown()) + nagios.append_message(UNKNOWN_CODE, processor.checkUnknown()) self.assertEqual(code, nagios.getCode()) def test_metrics(self): From 0aceabfe9196d2d4d630d984bbe57b981c8c1082 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 18 Mar 2024 10:52:51 +0100 Subject: [PATCH 4/4] Add verbose flag and function that can be used to enhance output more precisely - Before we only had a boolean debug flag, good for debugging errors. The verbose flag can be used more precisely (`-v -vvv`) to specify when something should be printed. This is useful for adding more output whilst avoiding full debug output that contains secrets. --- check_http_json.py | 31 +++++++++++++++++++------------ test/test_cli.py | 12 ++++++++---- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/check_http_json.py b/check_http_json.py index 63142f8..838cf75 100755 --- a/check_http_json.py +++ b/check_http_json.py @@ -6,7 +6,6 @@ import argparse import sys import ssl -from pprint import pprint from urllib.error import HTTPError from urllib.error import URLError @@ -422,6 +421,9 @@ def parseArgs(args): parser.add_argument('-d', '--debug', action='store_true', help='debug mode') + parser.add_argument('-v', '--verbose', action='count', default=0, + help='Verbose mode. Multiple -v options increase the verbosity') + parser.add_argument('-s', '--ssl', action='store_true', help='use TLS to connect to remote host') parser.add_argument('-H', '--host', dest='host', @@ -517,17 +519,24 @@ def parseArgs(args): return parser.parse_args(args) -def debugPrint(debug_flag, message, pretty_flag=False): +def debugPrint(debug_flag, message): """ - Print debug messages if -d (debug_flat ) is set. + Print debug messages if -d is set. """ + if not debug_flag: + return - if debug_flag: - if pretty_flag: - pprint(message) - else: - print(message) + print(message) +def verbosePrint(verbose_flag, when, message): + """ + Print verbose messages if -v is set. + Since -v can be used multiple times, the when parameter sets the required amount before printing + """ + if not verbose_flag: + return + if verbose_flag >= when: + print(message) def prepare_context(args): """ @@ -621,7 +630,7 @@ def main(cliargs): if args.path: url += "/%s" % args.path - debugPrint(args.debug, "url:%s" % url) + debugPrint(args.debug, "url: %s" % url) json_data = '' try: @@ -644,10 +653,8 @@ def main(cliargs): data = json.loads(json_data) except ValueError as e: nagios.append_message(UNKNOWN_CODE, " JSON Parser error: %s" % str(e)) - else: - debugPrint(args.debug, 'json:') - debugPrint(args.debug, data, True) + verbosePrint(args.verbose, 1, json.dumps(data, indent=2)) # Apply rules to returned JSON data processor = JsonRuleProcessor(data, args) nagios.append_message(WARNING_CODE, processor.checkWarning()) diff --git a/test/test_cli.py b/test/test_cli.py index 8766ef5..f22992d 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -9,6 +9,7 @@ sys.path.append('..') from check_http_json import debugPrint +from check_http_json import verbosePrint class CLITest(unittest.TestCase): @@ -31,10 +32,13 @@ def test_debugprint(self): 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_verbose(self): + with mock.patch('builtins.print') as mock_print: + verbosePrint(0, 3, 'verbose') + mock_print.assert_not_called() + + verbosePrint(3, 3, 'verbose') + mock_print.assert_called_once_with('verbose') def test_cli_without_params(self):