From afc9fe2d17205dad3edab0712558896dfe0b663b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 30 Oct 2022 19:57:59 +0100 Subject: [PATCH] Include symbolic HTTP status codes in error and log messages when available. --- changelogs/fragments/524-acme-http-errors.yml | 2 ++ plugins/module_utils/acme/acme.py | 5 +++-- plugins/module_utils/acme/errors.py | 17 ++++++++++---- .../plugins/module_utils/acme/test_errors.py | 22 +++++++++---------- 4 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 changelogs/fragments/524-acme-http-errors.yml diff --git a/changelogs/fragments/524-acme-http-errors.yml b/changelogs/fragments/524-acme-http-errors.yml new file mode 100644 index 000000000..cd6bbc4bd --- /dev/null +++ b/changelogs/fragments/524-acme-http-errors.yml @@ -0,0 +1,2 @@ +minor_changes: + - "acme_* modules - include symbolic HTTP status codes in error and log messages when available (https://github.com/ansible-collections/community.crypto/pull/524)." diff --git a/plugins/module_utils/acme/acme.py b/plugins/module_utils/acme/acme.py index e9f67a3f1..b0f64454b 100644 --- a/plugins/module_utils/acme/acme.py +++ b/plugins/module_utils/acme/acme.py @@ -38,6 +38,7 @@ NetworkException, ModuleFailException, KeyParsingError, + format_http_status, ) from ansible_collections.community.crypto.plugins.module_utils.acme.utils import ( @@ -69,7 +70,7 @@ def _decode_retry(module, response, info, retry_count): retry_after = min(max(1, int(info.get('retry-after'))), 60) except (TypeError, ValueError) as dummy: retry_after = 10 - module.log('Retrieved a %d HTTP status on %s, retrying in %s seconds' % (info['status'], info['url'], retry_after)) + module.log('Retrieved a %s HTTP status on %s, retrying in %s seconds' % (format_http_status(info['status']), info['url'], retry_after)) time.sleep(retry_after) return True @@ -138,7 +139,7 @@ def get_nonce(self, resource=None): retry_count += 1 continue if info['status'] not in (200, 204): - raise NetworkException("Failed to get replay-nonce, got status {0}".format(info['status'])) + raise NetworkException("Failed to get replay-nonce, got status {0}".format(format_http_status(info['status']))) return info['replay-nonce'] diff --git a/plugins/module_utils/acme/errors.py b/plugins/module_utils/acme/errors.py index 892d26c6b..208a1ae4f 100644 --- a/plugins/module_utils/acme/errors.py +++ b/plugins/module_utils/acme/errors.py @@ -10,6 +10,14 @@ from ansible.module_utils.common.text.converters import to_text from ansible.module_utils.six import binary_type, PY3 +from ansible.module_utils.six.moves.http_client import responses as http_responses + + +def format_http_status(status_code): + expl = http_responses.get(status_code) + if not expl: + return str(status_code) + return '%d %s' % (status_code, expl) def format_error_problem(problem, subproblem_prefix=''): @@ -87,9 +95,10 @@ def __init__(self, module, msg=None, info=None, response=None, content=None, con extras['http_status'] = code if code is not None and code >= 400 and content_json is not None and 'type' in content_json: if 'status' in content_json and content_json['status'] != code: - code = 'status {problem_code} (HTTP status: {http_code})'.format(http_code=code, problem_code=content_json['status']) + code = 'status {problem_code} (HTTP status: {http_code})'.format( + http_code=format_http_status(code), problem_code=content_json['status']) else: - code = 'status {problem_code}'.format(problem_code=code) + code = 'status {problem_code}'.format(problem_code=format_http_status(code)) subproblems = content_json.pop('subproblems', None) add_msg = ' {problem}.'.format(problem=format_error_problem(content_json)) extras['problem'] = content_json @@ -103,12 +112,12 @@ def __init__(self, module, msg=None, info=None, response=None, content=None, con problem=format_error_problem(problem, subproblem_prefix='{0}.'.format(index)), ) else: - code = 'HTTP status {code}'.format(code=code) + code = 'HTTP status {code}'.format(code=format_http_status(code)) if content_json is not None: add_msg = ' The JSON error result: {content}'.format(content=content_json) elif content is not None: add_msg = ' The raw error result: {content}'.format(content=to_text(content)) - msg = '{msg} for {url} with {code}'.format(msg=msg, url=url, code=code) + msg = '{msg} for {url} with {code}'.format(msg=msg, url=url, code=format_http_status(code)) elif content_json is not None: add_msg = ' The JSON result: {content}'.format(content=content_json) elif content is not None: diff --git a/tests/unit/plugins/module_utils/acme/test_errors.py b/tests/unit/plugins/module_utils/acme/test_errors.py index 7285b7c32..c84015d33 100644 --- a/tests/unit/plugins/module_utils/acme/test_errors.py +++ b/tests/unit/plugins/module_utils/acme/test_errors.py @@ -166,7 +166,7 @@ def f(content): }, }, None, - 'ACME request failed for https://ca.example.com/foo with HTTP status 201.', + 'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created.', { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -181,7 +181,7 @@ def f(content): 'response': create_regular_response('xxx'), }, None, - 'ACME request failed for https://ca.example.com/foo with HTTP status 201. The raw error result: xxx', + 'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx', { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -196,7 +196,7 @@ def f(content): 'response': create_regular_response('xxx'), }, create_decode_error('yyy'), - 'ACME request failed for https://ca.example.com/foo with HTTP status 201. The raw error result: xxx', + 'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx', { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -211,7 +211,7 @@ def f(content): 'response': create_regular_response('xxx'), }, lambda content: dict(foo='bar'), - "ACME request failed for https://ca.example.com/foo with HTTP status 201. The JSON error result: {'foo': 'bar'}", + "ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'foo': 'bar'}", { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -226,7 +226,7 @@ def f(content): 'response': create_error_response(), }, None, - 'ACME request failed for https://ca.example.com/foo with HTTP status 201.', + 'ACME request failed for https://ca.example.com/foo with HTTP status 201 Created.', { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -242,7 +242,7 @@ def f(content): 'response': create_error_response(), }, lambda content: dict(foo='bar'), - "ACME request failed for https://ca.example.com/foo with HTTP status 201. The JSON error result: {'foo': 'bar'}", + "ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'foo': 'bar'}", { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -257,7 +257,7 @@ def f(content): 'content': 'xxx', }, None, - "ACME request failed for https://ca.example.com/foo with HTTP status 201. The raw error result: xxx", + "ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The raw error result: xxx", { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -277,7 +277,7 @@ def f(content): } }, None, - "ACME request failed for https://ca.example.com/foo with HTTP status 400. The JSON error result: {'foo': 'bar'}", + "ACME request failed for https://ca.example.com/foo with HTTP status 400 Bad Request. The JSON error result: {'foo': 'bar'}", { 'http_url': 'https://ca.example.com/foo', 'http_status': 400, @@ -295,7 +295,7 @@ def f(content): }, }, None, - "ACME request failed for https://ca.example.com/foo with HTTP status 201. The JSON error result: {'type': 'foo'}", + "ACME request failed for https://ca.example.com/foo with HTTP status 201 Created. The JSON error result: {'type': 'foo'}", { 'http_url': 'https://ca.example.com/foo', 'http_status': 201, @@ -312,7 +312,7 @@ def f(content): }, }, None, - "ACME request failed for https://ca.example.com/foo with status 400. Error foo.", + "ACME request failed for https://ca.example.com/foo with status 400 Bad Request. Error foo.", { 'http_url': 'https://ca.example.com/foo', 'http_status': 400, @@ -341,7 +341,7 @@ def f(content): }, }, None, - "ACME request failed for https://ca.example.com/foo with status 400. Error \"Foo Error\" (foo). Subproblems:\n" + "ACME request failed for https://ca.example.com/foo with status 400 Bad Request. Error \"Foo Error\" (foo). Subproblems:\n" "(0) Error bar: \"This is a bar error\".", { 'http_url': 'https://ca.example.com/foo',