Internals¶
Overall Program Flow¶
AwsLimitChecker
provides the full and only public interface to this
project; it’s used by the awslimitchecker
command line script (entry point to runner
)
and should be the only portion directly used by external code.
Each AWS Service is represented by a subclass of the _AwsService
abstract base
class; these Service Classes are responsible for knowing which limits exist for the service they represent, what the
default values for these limits are, querying current limits from the service’s API (if supported),
and how to check the current usage via the AWS API (via boto
). When the
Service Classes are instantiated, they build a dict of all of their limits, correlating a string key (the “limit name”)
with an AwsLimit
object. The Service Class constructors must not make any network
connections; connections are created lazily as needed and stored as a class attribute. This allows us to inspect the
services, limits and default limit values without ever connecting to AWS (this is also used to generate the
Supported Limits documentation automatically).
All calls to the AWS APIs should be made through boto_query_wrapper()
. This function
encapsulates both retrying queries with an exponential backoff when queries are throttled due to your account hitting
the request rate limit
(via invoke_with_throttling_retries()
) and automatically paginating query responses
that aren’t automatically handled by boto.
When AwsLimitChecker
is instantiated, it imports services
which in turn creates instances of all awslimitchecker.services.*
classes and adds them to a dict mapping the
string Service Name to the Service Class instance. These instances are used for all interaction with the services.
So, once an instance of AwsLimitChecker
is created, we should have instant access
to the services and limits without any connection to AWS. This is utilized by the --list-services
and
--list-defaults
options for the command line client.
Trusted Advisor¶
When AwsLimitChecker
is initialized, it also initializes an instance of
TrustedAdvisor
. In get_limits()
,
find_usage()
and check_thresholds()
, when called with
use_ta == True
(the default), update_limits()
is called on the TrustedAdvisor
instance.
update_limits()
polls Trusted Advisor data is from the Support API via
_poll()
; this will retrieve the limits for all “flaggedResources” items in the
Service Limits
Trusted Advisor check result for the current AWS account. It then calls
_update_services()
, passing in the Trusted Advisor check results and the
dict of _AwsService
objects it was called with (from AwsLimitChecker
).
_update_services()
iterates over the Services in the Trusted Advisor check result
and attempts to find a matching _AwsService
(by string service name) in the dict passed
in from AwsLimitChecker
. If a match is found, it iterates over all limits for that service
in the TA result and attempts to call the Service
‘s _set_ta_limit()
method.
If a matching Service is not found, or if _set_ta_limit
raises a ValueError (matching Limit not found
for that Service), an error is logged.
Using this methodology, no additional code is needed to support new/additional Trusted Advisor limit checks;
so long as the Service and Limit name strings match between the Trusted Advisor API response and their
corresponding _AwsService
and AwsLimit
instances, the TA limits will be automatically
added to the corresponding AwsLimit
.
Service API Limit Information¶
Some services provide API calls to retrieve at least some of the current limits, such as the DescribeAccountAttributes
API calls for RDS
and EC2. Services that
support such calls should make them in a _update_limits_from_api()
method, which will be automatically called from
get_limits()
. The _update_limits_from_api()
method should make the API call, and then
update all relevant limits via the AwsLimit
class’s _set_api_limit()
method.
Limit Value Precedence¶
The value used for a limit is the first match in the following list:
- Limit Override (set at runtime)
- API Limit
- Trusted Advisor
- Hard-coded default