Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

acme module utils: include symbolic HTTP status codes in error and log messages when available #524

Merged
merged 1 commit into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/524-acme-http-errors.yml
Original file line number Diff line number Diff line change
@@ -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)."
5 changes: 3 additions & 2 deletions plugins/module_utils/acme/acme.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
NetworkException,
ModuleFailException,
KeyParsingError,
format_http_status,
)

from ansible_collections.community.crypto.plugins.module_utils.acme.utils import (
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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']


Expand Down
17 changes: 13 additions & 4 deletions plugins/module_utils/acme/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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=''):
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down
22 changes: 11 additions & 11 deletions tests/unit/plugins/module_utils/acme/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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',
Expand Down