Adding support for querying AWS Config for supported configurations.
At this time, only adding support for S3.
This commit is contained in:
parent
4497f18c1a
commit
c4b310d7a5
10 changed files with 675 additions and 2 deletions
|
|
@ -230,3 +230,27 @@ class TooManyTags(JsonRESTError):
|
|||
super(TooManyTags, self).__init__(
|
||||
'ValidationException', "1 validation error detected: Value '{}' at '{}' failed to satisfy "
|
||||
"constraint: Member must have length less than or equal to 50.".format(tags, param))
|
||||
|
||||
|
||||
class InvalidResourceParameters(JsonRESTError):
|
||||
code = 400
|
||||
|
||||
def __init__(self):
|
||||
super(InvalidResourceParameters, self).__init__('ValidationException', 'Both Resource ID and Resource Name '
|
||||
'cannot be specified in the request')
|
||||
|
||||
|
||||
class InvalidLimit(JsonRESTError):
|
||||
code = 400
|
||||
|
||||
def __init__(self, value):
|
||||
super(InvalidLimit, self).__init__('ValidationException', 'Value \'{value}\' at \'limit\' failed to satisify constraint: Member'
|
||||
' must have value less than or equal to 100'.format(value=value))
|
||||
|
||||
|
||||
class TooManyResourceIds(JsonRESTError):
|
||||
code = 400
|
||||
|
||||
def __init__(self):
|
||||
super(TooManyResourceIds, self).__init__('ValidationException', "The specified list had more than 20 resource ID's. "
|
||||
"It must have '20' or less items")
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@ from moto.config.exceptions import InvalidResourceTypeException, InvalidDelivery
|
|||
InvalidSNSTopicARNException, MaxNumberOfDeliveryChannelsExceededException, NoAvailableDeliveryChannelException, \
|
||||
NoSuchDeliveryChannelException, LastDeliveryChannelDeleteFailedException, TagKeyTooBig, \
|
||||
TooManyTags, TagValueTooBig, TooManyAccountSources, InvalidParameterValueException, InvalidNextTokenException, \
|
||||
NoSuchConfigurationAggregatorException, InvalidTagCharacters, DuplicateTags
|
||||
NoSuchConfigurationAggregatorException, InvalidTagCharacters, DuplicateTags, InvalidLimit, InvalidResourceParameters, TooManyResourceIds
|
||||
|
||||
from moto.core import BaseBackend, BaseModel
|
||||
from moto.s3.config import s3_config_query
|
||||
|
||||
DEFAULT_ACCOUNT_ID = 123456789012
|
||||
DEFAULT_ACCOUNT_ID = '123456789012'
|
||||
POP_STRINGS = [
|
||||
'capitalizeStart',
|
||||
'CapitalizeStart',
|
||||
|
|
@ -32,6 +33,11 @@ POP_STRINGS = [
|
|||
]
|
||||
DEFAULT_PAGE_SIZE = 100
|
||||
|
||||
# Map the Config resource type to a backend:
|
||||
RESOURCE_MAP = {
|
||||
'AWS::S3::Bucket': s3_config_query
|
||||
}
|
||||
|
||||
|
||||
def datetime2int(date):
|
||||
return int(time.mktime(date.timetuple()))
|
||||
|
|
@ -680,6 +686,110 @@ class ConfigBackend(BaseBackend):
|
|||
|
||||
del self.delivery_channels[channel_name]
|
||||
|
||||
def list_discovered_resources(self, resource_type, backend_region, resource_ids, resource_name, limit, next_token):
|
||||
"""This will query against the mocked AWS Config listing function that must exist for the resource backend.
|
||||
|
||||
:param resource_type:
|
||||
:param backend_region:
|
||||
:param ids:
|
||||
:param name:
|
||||
:param limit:
|
||||
:param next_token:
|
||||
:return:
|
||||
"""
|
||||
identifiers = []
|
||||
new_token = None
|
||||
|
||||
limit = limit or DEFAULT_PAGE_SIZE
|
||||
if limit > DEFAULT_PAGE_SIZE:
|
||||
raise InvalidLimit(limit)
|
||||
|
||||
if resource_ids and resource_name:
|
||||
raise InvalidResourceParameters()
|
||||
|
||||
# Only 20 maximum Resource IDs:
|
||||
if resource_ids and len(resource_ids) > 20:
|
||||
raise TooManyResourceIds()
|
||||
|
||||
# If the resource type exists and the backend region is implemented in moto, then
|
||||
# call upon the resource type's Config Query class to retrieve the list of resources that match the criteria:
|
||||
if RESOURCE_MAP.get(resource_type, {}):
|
||||
# Is this a global resource type? -- if so, re-write the region to 'global':
|
||||
if RESOURCE_MAP[resource_type].backends.get('global'):
|
||||
backend_region = 'global'
|
||||
|
||||
# For non-aggregated queries, the we only care about the backend_region. Need to verify that moto has implemented
|
||||
# the region for the given backend:
|
||||
if RESOURCE_MAP[resource_type].backends.get(backend_region):
|
||||
# Fetch the resources for the backend's region:
|
||||
identifiers, new_token = \
|
||||
RESOURCE_MAP[resource_type].list_config_service_resources(resource_ids, resource_name, limit, next_token)
|
||||
|
||||
result = {'resourceIdentifiers': [
|
||||
{
|
||||
'resourceType': identifier['type'],
|
||||
'resourceId': identifier['id'],
|
||||
'resourceName': identifier['name']
|
||||
}
|
||||
for identifier in identifiers]
|
||||
}
|
||||
|
||||
if new_token:
|
||||
result['nextToken'] = new_token
|
||||
|
||||
return result
|
||||
|
||||
def list_aggregate_discovered_resources(self, aggregator_name, resource_type, filters, limit, next_token):
|
||||
"""This will query against the mocked AWS Config listing function that must exist for the resource backend.
|
||||
As far a moto goes -- the only real difference between this function and the `list_discovered_resources` function is that
|
||||
this will require a Config Aggregator be set up a priori and can search based on resource regions.
|
||||
|
||||
:param aggregator_name:
|
||||
:param resource_type:
|
||||
:param filters:
|
||||
:param limit:
|
||||
:param next_token:
|
||||
:return:
|
||||
"""
|
||||
if not self.config_aggregators.get(aggregator_name):
|
||||
raise NoSuchConfigurationAggregatorException()
|
||||
|
||||
identifiers = []
|
||||
new_token = None
|
||||
filters = filters or {}
|
||||
|
||||
limit = limit or DEFAULT_PAGE_SIZE
|
||||
if limit > DEFAULT_PAGE_SIZE:
|
||||
raise InvalidLimit(limit)
|
||||
|
||||
# If the resource type exists and the backend region is implemented in moto, then
|
||||
# call upon the resource type's Config Query class to retrieve the list of resources that match the criteria:
|
||||
if RESOURCE_MAP.get(resource_type, {}):
|
||||
# We only care about a filter's Region, Resource Name, and Resource ID:
|
||||
resource_region = filters.get('Region')
|
||||
resource_id = [filters['ResourceId']] if filters.get('ResourceId') else None
|
||||
resource_name = filters.get('ResourceName')
|
||||
|
||||
identifiers, new_token = \
|
||||
RESOURCE_MAP[resource_type].list_config_service_resources(resource_id, resource_name, limit, next_token,
|
||||
resource_region=resource_region)
|
||||
|
||||
result = {'ResourceIdentifiers': [
|
||||
{
|
||||
'SourceAccountId': DEFAULT_ACCOUNT_ID,
|
||||
'SourceRegion': identifier['region'],
|
||||
'ResourceType': identifier['type'],
|
||||
'ResourceId': identifier['id'],
|
||||
'ResourceName': identifier['name']
|
||||
}
|
||||
for identifier in identifiers]
|
||||
}
|
||||
|
||||
if new_token:
|
||||
result['NextToken'] = new_token
|
||||
|
||||
return result
|
||||
|
||||
|
||||
config_backends = {}
|
||||
boto3_session = Session()
|
||||
|
|
|
|||
|
|
@ -84,3 +84,34 @@ class ConfigResponse(BaseResponse):
|
|||
def stop_configuration_recorder(self):
|
||||
self.config_backend.stop_configuration_recorder(self._get_param('ConfigurationRecorderName'))
|
||||
return ""
|
||||
|
||||
def list_discovered_resources(self):
|
||||
schema = self.config_backend.list_discovered_resources(self._get_param('resourceType'),
|
||||
self.region,
|
||||
self._get_param('resourceIds'),
|
||||
self._get_param('resourceName'),
|
||||
self._get_param('limit'),
|
||||
self._get_param('nextToken'))
|
||||
return json.dumps(schema)
|
||||
|
||||
def list_aggregate_discovered_resources(self):
|
||||
schema = self.config_backend.list_aggregate_discovered_resources(self._get_param('ConfigurationAggregatorName'),
|
||||
self._get_param('ResourceType'),
|
||||
self._get_param('Filters'),
|
||||
self._get_param('Limit'),
|
||||
self._get_param('NextToken'))
|
||||
return json.dumps(schema)
|
||||
|
||||
"""
|
||||
def batch_get_resource_config(self):
|
||||
# TODO implement me!
|
||||
return ""
|
||||
|
||||
def batch_get_aggregate_resource_config(self):
|
||||
# TODO implement me!
|
||||
return ""
|
||||
|
||||
def get_resource_config_history(self):
|
||||
# TODO implement me!
|
||||
return ""
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue