mirror of https://github.com/ansible/ansible.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
5.1 KiB
Python
202 lines
5.1 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from ansible._internal._errors import _error_factory
|
|
|
|
from ansible.errors import AnsibleError
|
|
from ansible._internal._datatag._tags import Origin
|
|
from ansible._internal._errors._utils import format_exception_message
|
|
from ansible.utils.display import _format_message
|
|
from ansible.module_utils._internal import _messages
|
|
|
|
|
|
def raise_exceptions(exceptions: list[BaseException]) -> None:
|
|
if len(exceptions) > 1:
|
|
try:
|
|
raise_exceptions(exceptions[1:])
|
|
except Exception as ex:
|
|
raise exceptions[0] from ex
|
|
|
|
raise exceptions[0]
|
|
|
|
|
|
_shared_cause = Exception('shared cause')
|
|
_origin_x = Origin(path='/x')
|
|
_origin_y = Origin(path='/y')
|
|
|
|
|
|
@pytest.mark.parametrize("exceptions, expected_message_chain, expected_formatted_message", (
|
|
([AnsibleError('a')], 'a', None),
|
|
([AnsibleError('a'), AnsibleError('b')], 'a: b', None),
|
|
([AnsibleError('a: b'), AnsibleError('b')], 'a: b', None),
|
|
([Exception('a')], 'a', None),
|
|
([Exception('a'), Exception('b')], 'a: b', None),
|
|
([Exception('a: b'), Exception('b')], 'a: b', None),
|
|
([AnsibleError('a'), Exception('b')], 'a: b', None),
|
|
([AnsibleError('a: b'), Exception('b')], 'a: b', None),
|
|
([Exception('a'), AnsibleError('b')], 'a: b', None),
|
|
([Exception('a: b'), AnsibleError('b')], 'a: b', None),
|
|
([AnsibleError('a'), AnsibleError('b'), Exception('c'), Exception('d')], 'a: b: c: d', None),
|
|
([AnsibleError('a: b: c: d'), AnsibleError('b'), Exception('c: d'), Exception('d')], 'a: b: c: d', None),
|
|
|
|
# collapsing help_text
|
|
|
|
(
|
|
[
|
|
AnsibleError('a', help_text='one'),
|
|
Exception('b'),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b one'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', help_text='one'),
|
|
AnsibleError('b', help_text='one'),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b one'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', help_text='one'),
|
|
Exception('b'),
|
|
AnsibleError('c', help_text='one'),
|
|
],
|
|
'a: b: c',
|
|
(
|
|
'a: b: c one'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', help_text='one'),
|
|
AnsibleError('b', help_text='two'),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n\n'
|
|
'a one\n\n'
|
|
'<<< caused by >>>\n\n'
|
|
'b two'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a'),
|
|
AnsibleError('b', help_text='one'),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n\n'
|
|
'a\n\n'
|
|
'<<< caused by >>>\n\n'
|
|
'b one'
|
|
),
|
|
),
|
|
|
|
# collapsing origin
|
|
|
|
(
|
|
[
|
|
AnsibleError('a', obj=_origin_x.tag('x'), orig_exc=Exception('ignored')),
|
|
Exception('b'),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n'
|
|
'Origin: /x'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', obj=_origin_x.tag('x'), orig_exc=_shared_cause),
|
|
_shared_cause,
|
|
],
|
|
'a: shared cause',
|
|
(
|
|
'a: shared cause\n'
|
|
'Origin: /x'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
# same as above, but exercises the old `orig_exc` path that displays a warning
|
|
AnsibleError('a', obj=_origin_x.tag('x'), orig_exc=Exception('b')),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n'
|
|
'Origin: /x'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', obj=_origin_x.tag('x')),
|
|
AnsibleError('b', obj=_origin_x.tag('x')),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n'
|
|
'Origin: /x'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', obj=_origin_x.tag('x')),
|
|
Exception('b'),
|
|
AnsibleError('c', obj=_origin_x.tag('x')),
|
|
],
|
|
'a: b: c',
|
|
(
|
|
'a: b: c\n'
|
|
'Origin: /x'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a', obj=_origin_x.tag('x')),
|
|
AnsibleError('b', obj=_origin_y.tag('x')),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n\n'
|
|
'a\n'
|
|
'Origin: /x\n\n'
|
|
'<<< caused by >>>\n\n'
|
|
'b\n'
|
|
'Origin: /y'
|
|
),
|
|
),
|
|
(
|
|
[
|
|
AnsibleError('a'),
|
|
AnsibleError('b', obj=_origin_y.tag('x')),
|
|
],
|
|
'a: b',
|
|
(
|
|
'a: b\n\n'
|
|
'a\n\n'
|
|
'<<< caused by >>>\n\n'
|
|
'b\n'
|
|
'Origin: /y'
|
|
),
|
|
),
|
|
), ids=str)
|
|
def test_error_messages(exceptions: list[BaseException], expected_message_chain: str, expected_formatted_message: str | None) -> None:
|
|
with pytest.raises(Exception) as error:
|
|
raise_exceptions(exceptions)
|
|
|
|
event = _error_factory.ControllerEventFactory.from_exception(error.value, False)
|
|
|
|
message_chain = format_exception_message(error.value)
|
|
formatted_message = _format_message(_messages.ErrorSummary(event=event), False)
|
|
|
|
assert message_chain == expected_message_chain
|
|
assert formatted_message.strip() == (expected_formatted_message or expected_message_chain)
|