Skip to content

Commit

Permalink
Move exceptions (#1246)
Browse files Browse the repository at this point in the history
Move exceptions into their own python module

SUMMARY
Move base/core exceptions into their own python module
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
module_utils
ADDITIONAL INFORMATION

Reviewed-by: Alina Buzachis <None>
  • Loading branch information
tremble authored Nov 4, 2022
1 parent df44023 commit 8ff6340
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 4 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/20221104-exceptions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- module_utils - move exceptions into dedicated python module (https://github.com/ansible-collections/amazon.aws/pull/1246).
7 changes: 3 additions & 4 deletions plugins/module_utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
from .botocore import get_boto3_client_method_parameters # pylint: disable=unused-import
from .botocore import normalize_boto3_result # pylint: disable=unused-import

# Used to live here, moved into ansible_collections.amazon.aws.plugins.module_utils.exceptions
from .exceptions import AnsibleAWSError # pylint: disable=unused-import

# Used to live here, moved into ansible_collections.amazon.aws.plugins.module_utils.modules
from .modules import AnsibleAWSModule # pylint: disable=unused-import

Expand All @@ -71,7 +74,3 @@

# We will also export HAS_BOTO3 so end user modules can use it.
__all__ = ('AnsibleAWSModule', 'HAS_BOTO3', 'is_boto3_error_code', 'is_boto3_error_message')


class AnsibleAWSError(Exception):
pass
38 changes: 38 additions & 0 deletions plugins/module_utils/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# (c) 2022 Red Hat Inc.
#
# This file is part of Ansible
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.module_utils._text import to_native


class AnsibleAWSError(Exception):

def __str__(self):
if self.exception and self.message:
return "{0}: {1}".format(self.message, to_native(self.exception))

return super().__str__()

def __init__(self, message=None, exception=None, **kwargs):
if not message and not exception:
super().__init__()
elif not message:
super().__init__(exception)
else:
super().__init__(message)

self.exception = exception
self.message = message

# In places where passing more information to module.fail_json would be helpful
# store the extra info. Other plugin types have to raise the correct exception
# such as AnsibleLookupError, so can't easily consume this.
self.kwargs = kwargs or {}


class AnsibleBotocoreError(AnsibleAWSError):
pass
101 changes: 101 additions & 0 deletions tests/unit/module_utils/exceptions/test_exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# (c) 2022 Red Hat Inc.
#
# This file is part of Ansible
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import pytest
from unittest.mock import sentinel

import ansible_collections.amazon.aws.plugins.module_utils.exceptions as aws_exceptions


@pytest.fixture
def utils_exceptions():
return aws_exceptions


def test_with_kwargs(utils_exceptions):
nested_exception = Exception(sentinel.EXCEPTION)
with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(kw1=sentinel.KW1, kw2=sentinel.KW2)
assert str(e.value) == ''
assert e.value.exception is None
assert e.value.message is None
assert e.value.kwargs == dict(kw1=sentinel.KW1, kw2=sentinel.KW2)

with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(message=sentinel.MESSAGE, exception=nested_exception, kw1=sentinel.KW1, kw2=sentinel.KW2)
assert str(e.value) == 'sentinel.MESSAGE: sentinel.EXCEPTION'
assert e.value.exception is nested_exception
assert e.value.message is sentinel.MESSAGE
assert e.value.kwargs == dict(kw1=sentinel.KW1, kw2=sentinel.KW2)


def test_with_both(utils_exceptions):
nested_exception = Exception(sentinel.EXCEPTION)

with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(message=sentinel.MESSAGE, exception=nested_exception)
assert str(e.value) == 'sentinel.MESSAGE: sentinel.EXCEPTION'
assert e.value.exception is nested_exception
assert e.value.message is sentinel.MESSAGE
assert e.value.kwargs == {}

with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(sentinel.MESSAGE, exception=nested_exception)
assert str(e.value) == 'sentinel.MESSAGE: sentinel.EXCEPTION'
assert e.value.exception is nested_exception
assert e.value.message is sentinel.MESSAGE
assert e.value.kwargs == {}


def test_with_exception(utils_exceptions):
nested_exception = Exception(sentinel.EXCEPTION)

with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(exception=nested_exception)
assert str(e.value) == 'sentinel.EXCEPTION'
assert e.value.exception is nested_exception
assert e.value.message is None
assert e.value.kwargs == {}


def test_with_message(utils_exceptions):
with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(message=sentinel.MESSAGE)
assert str(e.value) == 'sentinel.MESSAGE'
assert e.value.exception is None
assert e.value.message is sentinel.MESSAGE
assert e.value.kwargs == {}

with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError(sentinel.MESSAGE)
assert str(e.value) == 'sentinel.MESSAGE'
assert e.value.exception is None
assert e.value.message is sentinel.MESSAGE
assert e.value.kwargs == {}


def test_empty(utils_exceptions):
with pytest.raises(utils_exceptions.AnsibleAWSError) as e:
raise utils_exceptions.AnsibleAWSError()
assert str(e.value) == ''
assert e.value.exception is None
assert e.value.message is None
assert e.value.kwargs == {}


def test_inheritence(utils_exceptions):
aws_exception = utils_exceptions.AnsibleAWSError()

assert isinstance(aws_exception, Exception)
assert isinstance(aws_exception, utils_exceptions.AnsibleAWSError)

botocore_exception = utils_exceptions.AnsibleBotocoreError()

assert isinstance(botocore_exception, Exception)
assert isinstance(botocore_exception, utils_exceptions.AnsibleAWSError)
assert isinstance(botocore_exception, utils_exceptions.AnsibleBotocoreError)

0 comments on commit 8ff6340

Please sign in to comment.