Skip to content

Commit

Permalink
Merge pull request #378 from /issues/377
Browse files Browse the repository at this point in the history
fixes #377 - 6.0.1 release
  • Loading branch information
jantman authored Jan 27, 2019
2 parents 364d88f + 43eb7b2 commit d8eccf1
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

6.0.1 (2019-01-27)
------------------

* `Issue #375 <https://github.com/jantman/awslimitchecker/issues/375>`_ - Fix uncaught ``ClientError`` exception when checking SES Send Quota in certain regions. Thanks to `bergkampsliew <https://github.com/bergkampsliew>`_ for `PR #376 <https://github.com/jantman/awslimitchecker/pull/376>`_.

6.0.0 (2019-01-01)
------------------

Expand Down
21 changes: 19 additions & 2 deletions awslimitchecker/services/ses.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from .base import _AwsService
from ..limit import AwsLimit
from botocore.exceptions import EndpointConnectionError
from botocore.exceptions import ClientError

logger = logging.getLogger(__name__)

Expand All @@ -65,8 +66,16 @@ def find_usage(self):
self.connect()
resp = self.conn.get_send_quota()
except EndpointConnectionError as ex:
logger.warn('Skipping SES: %s', str(ex))
logger.warning('Skipping SES: %s', str(ex))
return
except ClientError as ex:
if (
ex.response['Error']['Code'] == 'AccessDenied' and
ex.response['Error']['Message'] == 'Unknown'
):
logger.warning('Skipping SES: %s', ex)
return
raise
self.limits['Daily sending quota']._add_current_usage(
resp['SentLast24Hours']
)
Expand Down Expand Up @@ -104,8 +113,16 @@ def _update_limits_from_api(self):
self.connect()
resp = self.conn.get_send_quota()
except EndpointConnectionError as ex:
logger.warn('Skipping SES: %s', str(ex))
logger.warning('Skipping SES: %s', str(ex))
return
except ClientError as ex:
if (
ex.response['Error']['Code'] == 'AccessDenied' and
ex.response['Error']['Message'] == 'Unknown'
):
logger.warning('Skipping SES: %s', ex)
return
raise
self.limits['Daily sending quota']._set_api_limit(resp['Max24HourSend'])

def required_iam_permissions(self):
Expand Down
142 changes: 139 additions & 3 deletions awslimitchecker/tests/services/test_ses.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
"""

import sys
import pytest
from awslimitchecker.services.ses import _SesService
from botocore.exceptions import EndpointConnectionError
from botocore.exceptions import ClientError, EndpointConnectionError

# https://code.google.com/p/mock/issues/detail?id=249
# py>=3.4 should use unittest.mock not the mock package on pypi
Expand Down Expand Up @@ -125,14 +126,86 @@ def se_get():
assert cls._have_usage is False
assert mock_logger.mock_calls == [
call.debug('Checking usage for service %s', 'SES'),
call.warn(
call.warning(
'Skipping SES: %s',
'Could not connect to the endpoint URL: "myurl"'
)
]
assert mock_conn.mock_calls == [call.get_send_quota()]
assert len(cls.limits['Daily sending quota'].get_current_usage()) == 0

def test_find_usage_invalid_region_client_error(self):
resp = {
'ResponseMetadata': {
'HTTPStatusCode': 400,
'RequestId': '7d74c6f0-c789-11e5-82fe-a96cdaa6d564'
},
'Error': {
'Message': 'Unknown',
'Code': 'AccessDenied',
'Type': 'Sender'
}
}
ce = ClientError(resp, 'GetSendQuota')

def se_get():
raise ce

mock_conn = Mock()
mock_conn.get_send_quota.side_effect = se_get

with patch('%s.connect' % pb) as mock_connect:
with patch('%s.logger' % pbm) as mock_logger:
cls = _SesService(21, 43)
cls.conn = mock_conn
assert cls._have_usage is False
cls.find_usage()
assert mock_connect.mock_calls == [call()]
assert cls._have_usage is False
assert mock_logger.mock_calls == [
call.debug('Checking usage for service %s', 'SES'),
call.warning(
'Skipping SES: %s', ce
)
]
assert mock_conn.mock_calls == [call.get_send_quota()]
assert len(cls.limits['Daily sending quota'].get_current_usage()) == 0

def test_find_usage_other_client_error(self):
resp = {
'ResponseMetadata': {
'HTTPStatusCode': 400,
'RequestId': '7d74c6f0-c789-11e5-82fe-a96cdaa6d564'
},
'Error': {
'Message': 'Not Unknown',
'Code': 'AccessDenied',
'Type': 'Sender'
}
}
ce = ClientError(resp, 'operation')

def se_get():
raise ce

mock_conn = Mock()
mock_conn.get_send_quota.side_effect = se_get

with patch('%s.connect' % pb) as mock_connect:
with patch('%s.logger' % pbm) as mock_logger:
cls = _SesService(21, 43)
cls.conn = mock_conn
assert cls._have_usage is False
with pytest.raises(ClientError):
cls.find_usage()
assert mock_connect.mock_calls == [call()]
assert cls._have_usage is False
assert mock_logger.mock_calls == [
call.debug('Checking usage for service %s', 'SES')
]
assert mock_conn.mock_calls == [call.get_send_quota()]
assert len(cls.limits['Daily sending quota'].get_current_usage()) == 0

def test_update_limits_from_api(self):
mock_conn = Mock()
mock_conn.get_send_quota.return_value = {
Expand Down Expand Up @@ -164,13 +237,76 @@ def se_get():
assert mock_connect.mock_calls == [call()]
assert mock_conn.mock_calls == [call.get_send_quota()]
assert mock_logger.mock_calls == [
call.warn(
call.warning(
'Skipping SES: %s',
'Could not connect to the endpoint URL: "myurl"'
)
]
assert cls.limits['Daily sending quota'].api_limit is None

def test_update_limits_from_api_invalid_region_client_error(self):
resp = {
'ResponseMetadata': {
'HTTPStatusCode': 400,
'RequestId': '7d74c6f0-c789-11e5-82fe-a96cdaa6d564'
},
'Error': {
'Message': 'Unknown',
'Code': 'AccessDenied',
'Type': 'Sender'
}
}
ce = ClientError(resp, 'GetSendQuota')

def se_get():
raise ce

mock_conn = Mock()
mock_conn.get_send_quota.side_effect = se_get

with patch('%s.connect' % pb) as mock_connect:
with patch('%s.logger' % pbm) as mock_logger:
cls = _SesService(21, 43)
cls.conn = mock_conn
cls._update_limits_from_api()
assert mock_connect.mock_calls == [call()]
assert mock_conn.mock_calls == [call.get_send_quota()]
assert mock_logger.mock_calls == [
call.warning('Skipping SES: %s', ce)
]
assert cls.limits['Daily sending quota'].api_limit is None

def test_update_limits_from_api_other_client_error(self):
resp = {
'ResponseMetadata': {
'HTTPStatusCode': 400,
'RequestId': '7d74c6f0-c789-11e5-82fe-a96cdaa6d564'
},
'Error': {
'Message': 'Not Unknown',
'Code': 'AccessDenied',
'Type': 'Sender'
}
}
ce = ClientError(resp, 'GetSendQuota')

def se_get():
raise ce

mock_conn = Mock()
mock_conn.get_send_quota.side_effect = se_get

with patch('%s.connect' % pb) as mock_connect:
with patch('%s.logger' % pbm) as mock_logger:
cls = _SesService(21, 43)
cls.conn = mock_conn
with pytest.raises(ClientError):
cls._update_limits_from_api()
assert mock_connect.mock_calls == [call()]
assert mock_conn.mock_calls == [call.get_send_quota()]
assert mock_logger.mock_calls == []
assert cls.limits['Daily sending quota'].api_limit is None

def test_required_iam_permissions(self):
cls = _SesService(21, 43)
assert cls.required_iam_permissions() == [
Expand Down
2 changes: 1 addition & 1 deletion awslimitchecker/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
except ImportError:
logger.error("Unable to import versionfinder", exc_info=True)

_VERSION_TUP = (6, 0, 0)
_VERSION_TUP = (6, 0, 1)
_VERSION = '.'.join([str(x) for x in _VERSION_TUP])
_PROJECT_URL = 'https://github.com/jantman/awslimitchecker'

Expand Down
2 changes: 1 addition & 1 deletion docs/source/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Trusted Advisor

awslimitchecker supports retrieving your current service limits via the
`Trusted Advisor <https://aws.amazon.com/premiumsupport/trustedadvisor/>`_
`"Service Limits" performance check <https://aws.amazon.com/premiumsupport/trustedadvisor/best-practices/#performance>`_
`"Service Limits" performance check <https://aws.amazon.com/premiumsupport/trustedadvisor/best-practices/#Performance>`_
, for limits which Trusted Advisor tracks (currently a subset of what awslimitchecker
knows about). The results of this check may not be available via the API for all
accounts; as of December 2016, the Trusted Advisor documentation states that while
Expand Down

0 comments on commit d8eccf1

Please sign in to comment.