From 0f913e817f8c420845c71de54af81d23fbda4a65 Mon Sep 17 00:00:00 2001 From: David Vallee Delisle Date: Wed, 27 Nov 2019 19:18:16 -0500 Subject: [PATCH] Adding support to output json instead of python dict It's easier to parse json output than python dict. --- .coveragerc | 2 ++ haproxy/line.py | 1 + haproxy/main.py | 27 ++++++++++++++++++++++----- haproxy/tests/test_argparse.py | 21 +++++++++++++++++++++ haproxy/tests/test_log_file.py | 1 + 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/.coveragerc b/.coveragerc index 1446a94..f5e837c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -6,3 +6,5 @@ omit = exclude_lines = def console_script() except ImportError + except json.decoder.JSONDecodeError + if isinstance diff --git a/haproxy/line.py b/haproxy/line.py index 4763d69..ea8200b 100644 --- a/haproxy/line.py +++ b/haproxy/line.py @@ -253,3 +253,4 @@ def handle_bad_http_request(self): if self.raw_http_request != '': print('Could not process HTTP request {0}'.format(self.raw_http_request),) + diff --git a/haproxy/main.py b/haproxy/main.py index db9be5e..59b2508 100644 --- a/haproxy/main.py +++ b/haproxy/main.py @@ -5,6 +5,8 @@ from haproxy.logfile import Log import argparse +import datetime +import json import os import re @@ -76,6 +78,8 @@ def create_parser(): '--list-filters', action='store_true', help='Lists all filters available.' ) + parser.add_argument('--json', action='store_true', help='Output results in json.') + return parser @@ -89,6 +93,7 @@ def parse_arguments(args): 'log': None, 'list_commands': None, 'list_filters': None, + 'json': None, } if args.list_commands: @@ -122,6 +127,9 @@ def parse_arguments(args): _validate_arg_logfile(args.log) data['log'] = args.log + if args.json is not None: + data['json'] = args.json + return data @@ -185,6 +193,11 @@ def _validate_arg_logfile(filename): raise ValueError('filename {0} does not exist'.format(filepath)) +def json_dumps_converter(o): + if isinstance(o, datetime.datetime): + return o.__str__() + + def print_commands(): """Prints all commands available from Log with their description. @@ -219,7 +232,7 @@ def show_help(data): # make sure that if no arguments are passed the help is shown show = True for key in data: - if data[key] is not None and key != 'log': + if data[key] is not None and key not in ('log', 'json'): show = False break @@ -266,13 +279,17 @@ def main(args): # run all commands for command in args['commands']: - string = 'command: {0}'.format(command) - print(string) - print('=' * len(string)) + if args['json'] is False: + string = 'command: {0}'.format(command) + print(string) + print('=' * len(string)) cmd = getattr(log_file, 'cmd_{0}'.format(command)) result = cmd() - print(result) + if args['json'] is True: + print(json.dumps(result, default=json_dumps_converter)) + else: + print(result) return log_file # return the log_file object so that tests can inspect it diff --git a/haproxy/tests/test_argparse.py b/haproxy/tests/test_argparse.py index aafe73f..38befa9 100644 --- a/haproxy/tests/test_argparse.py +++ b/haproxy/tests/test_argparse.py @@ -7,6 +7,7 @@ from haproxy.main import VALID_FILTERS from tempfile import NamedTemporaryFile +import json import os import sys import unittest @@ -47,6 +48,13 @@ def tearDown(self): if filename.endswith('.pickle'): os.remove('{0}/{1}'.format(path, filename)) + def validate_json(self, jsons): + try: + json.loads(jsons) + except json.decoder.JSONDecodeError: + return False + return True + def test_arg_parser_start_invalid(self): """Check that if a 'start' argument is not valid an exception is raised. @@ -224,6 +232,19 @@ def test_arg_parser_list_filters_output(self): for filter_name in VALID_FILTERS: self.assertIn(filter_name[7:], output_text) + def test_arg_parser_json(self): + """Test that list filters argument outputs what's expected.""" + arguments = ['-l', 'haproxy/tests/files/small.log', '--json', '-c', 'counter'] + data = parse_arguments(self.parser.parse_args(arguments)) + test_output = NamedTemporaryFile(mode='w', delete=False) + + with RedirectStdout(stdout=test_output): + main(data) + + with open(test_output.name, 'r') as output_file: + output_text = output_file.read() + self.assertTrue(self.validate_json(output_text)) + def test_arg_parser_filters(self): """Check that the filter logic on haproxy.main.main works as expected. """ diff --git a/haproxy/tests/test_log_file.py b/haproxy/tests/test_log_file.py index 539ec56..6fcaa9d 100644 --- a/haproxy/tests/test_log_file.py +++ b/haproxy/tests/test_log_file.py @@ -30,6 +30,7 @@ def test_from_main(self): 'filters': None, 'list_commands': False, 'list_filters': False, + 'json': False, } logfile = main(data)