Merge pull request #1150 from gvlproject/refactor_filtering
Refactored handling of unknown filter names
This commit is contained in:
commit
35feb9feb7
@ -375,3 +375,20 @@ class RulesPerSecurityGroupLimitExceededError(EC2ClientError):
|
|||||||
"RulesPerSecurityGroupLimitExceeded",
|
"RulesPerSecurityGroupLimitExceeded",
|
||||||
'The maximum number of rules per security group '
|
'The maximum number of rules per security group '
|
||||||
'has been reached.')
|
'has been reached.')
|
||||||
|
|
||||||
|
|
||||||
|
class MotoNotImplementedError(NotImplementedError):
|
||||||
|
|
||||||
|
def __init__(self, blurb):
|
||||||
|
super(MotoNotImplementedError, self).__init__(
|
||||||
|
"{0} has not been implemented in Moto yet."
|
||||||
|
" Feel free to open an issue at"
|
||||||
|
" https://github.com/spulec/moto/issues".format(blurb))
|
||||||
|
|
||||||
|
|
||||||
|
class FilterNotImplementedError(MotoNotImplementedError):
|
||||||
|
|
||||||
|
def __init__(self, filter_name, method_name):
|
||||||
|
super(FilterNotImplementedError, self).__init__(
|
||||||
|
"The filter '{0}' for {1}".format(
|
||||||
|
filter_name, method_name))
|
||||||
|
@ -62,6 +62,8 @@ from .exceptions import (
|
|||||||
InvalidVpnConnectionIdError,
|
InvalidVpnConnectionIdError,
|
||||||
InvalidCustomerGatewayIdError,
|
InvalidCustomerGatewayIdError,
|
||||||
RulesPerSecurityGroupLimitExceededError,
|
RulesPerSecurityGroupLimitExceededError,
|
||||||
|
MotoNotImplementedError,
|
||||||
|
FilterNotImplementedError
|
||||||
)
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
EC2_RESOURCE_TO_PREFIX,
|
EC2_RESOURCE_TO_PREFIX,
|
||||||
@ -144,7 +146,7 @@ class TaggedEC2Resource(BaseModel):
|
|||||||
for key, value in tag_map.items():
|
for key, value in tag_map.items():
|
||||||
self.ec2_backend.create_tags([self.id], {key: value})
|
self.ec2_backend.create_tags([self.id], {key: value})
|
||||||
|
|
||||||
def get_filter_value(self, filter_name):
|
def get_filter_value(self, filter_name, method_name=None):
|
||||||
tags = self.get_tags()
|
tags = self.get_tags()
|
||||||
|
|
||||||
if filter_name.startswith('tag:'):
|
if filter_name.startswith('tag:'):
|
||||||
@ -154,12 +156,12 @@ class TaggedEC2Resource(BaseModel):
|
|||||||
return tag['value']
|
return tag['value']
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
elif filter_name == 'tag-key':
|
||||||
if filter_name == 'tag-key':
|
|
||||||
return [tag['key'] for tag in tags]
|
return [tag['key'] for tag in tags]
|
||||||
|
elif filter_name == 'tag-value':
|
||||||
if filter_name == 'tag-value':
|
|
||||||
return [tag['value'] for tag in tags]
|
return [tag['value'] for tag in tags]
|
||||||
|
else:
|
||||||
|
raise FilterNotImplementedError(filter_name, method_name)
|
||||||
|
|
||||||
|
|
||||||
class NetworkInterface(TaggedEC2Resource):
|
class NetworkInterface(TaggedEC2Resource):
|
||||||
@ -261,17 +263,9 @@ class NetworkInterface(TaggedEC2Resource):
|
|||||||
return [group.id for group in self._group_set]
|
return [group.id for group in self._group_set]
|
||||||
elif filter_name == 'availability-zone':
|
elif filter_name == 'availability-zone':
|
||||||
return self.subnet.availability_zone
|
return self.subnet.availability_zone
|
||||||
|
else:
|
||||||
filter_value = super(
|
return super(NetworkInterface, self).get_filter_value(
|
||||||
NetworkInterface, self).get_filter_value(filter_name)
|
filter_name, 'DescribeNetworkInterfaces')
|
||||||
|
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeNetworkInterfaces".format(
|
|
||||||
filter_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class NetworkInterfaceBackend(object):
|
class NetworkInterfaceBackend(object):
|
||||||
@ -802,6 +796,8 @@ class KeyPair(object):
|
|||||||
return self.name
|
return self.name
|
||||||
elif filter_name == 'fingerprint':
|
elif filter_name == 'fingerprint':
|
||||||
return self.fingerprint
|
return self.fingerprint
|
||||||
|
else:
|
||||||
|
raise FilterNotImplementedError(filter_name, 'DescribeKeyPairs')
|
||||||
|
|
||||||
|
|
||||||
class KeyPairBackend(object):
|
class KeyPairBackend(object):
|
||||||
@ -1039,14 +1035,9 @@ class Ami(TaggedEC2Resource):
|
|||||||
return self.state
|
return self.state
|
||||||
elif filter_name == 'name':
|
elif filter_name == 'name':
|
||||||
return self.name
|
return self.name
|
||||||
|
else:
|
||||||
filter_value = super(Ami, self).get_filter_value(filter_name)
|
return super(Ami, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeImages')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeImages".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class AmiBackend(object):
|
class AmiBackend(object):
|
||||||
@ -1703,43 +1694,31 @@ class Volume(TaggedEC2Resource):
|
|||||||
return 'available'
|
return 'available'
|
||||||
|
|
||||||
def get_filter_value(self, filter_name):
|
def get_filter_value(self, filter_name):
|
||||||
|
|
||||||
if filter_name.startswith('attachment') and not self.attachment:
|
if filter_name.startswith('attachment') and not self.attachment:
|
||||||
return None
|
return None
|
||||||
if filter_name == 'attachment.attach-time':
|
elif filter_name == 'attachment.attach-time':
|
||||||
return self.attachment.attach_time
|
return self.attachment.attach_time
|
||||||
if filter_name == 'attachment.device':
|
elif filter_name == 'attachment.device':
|
||||||
return self.attachment.device
|
return self.attachment.device
|
||||||
if filter_name == 'attachment.instance-id':
|
elif filter_name == 'attachment.instance-id':
|
||||||
return self.attachment.instance.id
|
return self.attachment.instance.id
|
||||||
if filter_name == 'attachment.status':
|
elif filter_name == 'attachment.status':
|
||||||
return self.attachment.status
|
return self.attachment.status
|
||||||
|
elif filter_name == 'create-time':
|
||||||
if filter_name == 'create-time':
|
|
||||||
return self.create_time
|
return self.create_time
|
||||||
|
elif filter_name == 'size':
|
||||||
if filter_name == 'size':
|
|
||||||
return self.size
|
return self.size
|
||||||
|
elif filter_name == 'snapshot-id':
|
||||||
if filter_name == 'snapshot-id':
|
|
||||||
return self.snapshot_id
|
return self.snapshot_id
|
||||||
|
elif filter_name == 'status':
|
||||||
if filter_name == 'status':
|
|
||||||
return self.status
|
return self.status
|
||||||
|
elif filter_name == 'volume-id':
|
||||||
if filter_name == 'volume-id':
|
|
||||||
return self.id
|
return self.id
|
||||||
|
elif filter_name == 'encrypted':
|
||||||
if filter_name == 'encrypted':
|
|
||||||
return str(self.encrypted).lower()
|
return str(self.encrypted).lower()
|
||||||
|
else:
|
||||||
filter_value = super(Volume, self).get_filter_value(filter_name)
|
return super(Volume, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeVolumes')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeVolumes".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class Snapshot(TaggedEC2Resource):
|
class Snapshot(TaggedEC2Resource):
|
||||||
@ -1754,35 +1733,23 @@ class Snapshot(TaggedEC2Resource):
|
|||||||
self.encrypted = encrypted
|
self.encrypted = encrypted
|
||||||
|
|
||||||
def get_filter_value(self, filter_name):
|
def get_filter_value(self, filter_name):
|
||||||
|
|
||||||
if filter_name == 'description':
|
if filter_name == 'description':
|
||||||
return self.description
|
return self.description
|
||||||
|
elif filter_name == 'snapshot-id':
|
||||||
if filter_name == 'snapshot-id':
|
|
||||||
return self.id
|
return self.id
|
||||||
|
elif filter_name == 'start-time':
|
||||||
if filter_name == 'start-time':
|
|
||||||
return self.start_time
|
return self.start_time
|
||||||
|
elif filter_name == 'volume-id':
|
||||||
if filter_name == 'volume-id':
|
|
||||||
return self.volume.id
|
return self.volume.id
|
||||||
|
elif filter_name == 'volume-size':
|
||||||
if filter_name == 'volume-size':
|
|
||||||
return self.volume.size
|
return self.volume.size
|
||||||
|
elif filter_name == 'encrypted':
|
||||||
if filter_name == 'encrypted':
|
|
||||||
return str(self.encrypted).lower()
|
return str(self.encrypted).lower()
|
||||||
|
elif filter_name == 'status':
|
||||||
if filter_name == 'status':
|
|
||||||
return self.status
|
return self.status
|
||||||
|
else:
|
||||||
filter_value = super(Snapshot, self).get_filter_value(filter_name)
|
return super(Snapshot, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeSnapshots')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeSnapshots".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class EBSBackend(object):
|
class EBSBackend(object):
|
||||||
@ -1944,16 +1911,10 @@ class VPC(TaggedEC2Resource):
|
|||||||
elif filter_name in ('dhcp-options-id', 'dhcpOptionsId'):
|
elif filter_name in ('dhcp-options-id', 'dhcpOptionsId'):
|
||||||
if not self.dhcp_options:
|
if not self.dhcp_options:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self.dhcp_options.id
|
return self.dhcp_options.id
|
||||||
|
else:
|
||||||
filter_value = super(VPC, self).get_filter_value(filter_name)
|
return super(VPC, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeVpcs')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeVPCs".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class VPCBackend(object):
|
class VPCBackend(object):
|
||||||
@ -2187,14 +2148,9 @@ class Subnet(TaggedEC2Resource):
|
|||||||
return self.availability_zone
|
return self.availability_zone
|
||||||
elif filter_name in ('defaultForAz', 'default-for-az'):
|
elif filter_name in ('defaultForAz', 'default-for-az'):
|
||||||
return self.default_for_az
|
return self.default_for_az
|
||||||
|
else:
|
||||||
filter_value = super(Subnet, self).get_filter_value(filter_name)
|
return super(Subnet, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeSubnets')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeSubnets".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
def get_cfn_attribute(self, attribute_name):
|
def get_cfn_attribute(self, attribute_name):
|
||||||
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
||||||
@ -2332,14 +2288,9 @@ class RouteTable(TaggedEC2Resource):
|
|||||||
return self.associations.keys()
|
return self.associations.keys()
|
||||||
elif filter_name == "association.subnet-id":
|
elif filter_name == "association.subnet-id":
|
||||||
return self.associations.values()
|
return self.associations.values()
|
||||||
|
else:
|
||||||
filter_value = super(RouteTable, self).get_filter_value(filter_name)
|
return super(RouteTable, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeRouteTables')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeRouteTables".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class RouteTableBackend(object):
|
class RouteTableBackend(object):
|
||||||
@ -2686,16 +2637,11 @@ class SpotInstanceRequest(BotoSpotRequest, TaggedEC2Resource):
|
|||||||
def get_filter_value(self, filter_name):
|
def get_filter_value(self, filter_name):
|
||||||
if filter_name == 'state':
|
if filter_name == 'state':
|
||||||
return self.state
|
return self.state
|
||||||
if filter_name == 'spot-instance-request-id':
|
elif filter_name == 'spot-instance-request-id':
|
||||||
return self.id
|
return self.id
|
||||||
filter_value = super(SpotInstanceRequest,
|
else:
|
||||||
self).get_filter_value(filter_name)
|
return super(SpotInstanceRequest, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeSpotInstanceRequests')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeSpotInstanceRequests".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
def launch_instance(self):
|
def launch_instance(self):
|
||||||
reservation = self.ec2_backend.add_instances(
|
reservation = self.ec2_backend.add_instances(
|
||||||
@ -2966,15 +2912,13 @@ class ElasticAddress(object):
|
|||||||
return self.instance.id
|
return self.instance.id
|
||||||
elif filter_name == 'network-interface-id' and self.eni:
|
elif filter_name == 'network-interface-id' and self.eni:
|
||||||
return self.eni.id
|
return self.eni.id
|
||||||
elif filter_name == 'network-interface-owner-id':
|
|
||||||
msg = "The filter '{0}' for DescribeAddresses has not been" \
|
|
||||||
" implemented in Moto yet. Feel free to open an issue at" \
|
|
||||||
" https://github.com/spulec/moto/issues".format(filter_name)
|
|
||||||
raise NotImplementedError(msg)
|
|
||||||
elif filter_name == 'private-ip-address' and self.eni:
|
elif filter_name == 'private-ip-address' and self.eni:
|
||||||
return self.eni.private_ip_address
|
return self.eni.private_ip_address
|
||||||
elif filter_name == 'public-ip':
|
elif filter_name == 'public-ip':
|
||||||
return self.public_ip
|
return self.public_ip
|
||||||
|
else:
|
||||||
|
# TODO: implement network-interface-owner-id
|
||||||
|
raise FilterNotImplementedError(filter_name, 'DescribeAddresses')
|
||||||
|
|
||||||
|
|
||||||
class ElasticAddressBackend(object):
|
class ElasticAddressBackend(object):
|
||||||
@ -3134,15 +3078,9 @@ class DHCPOptionsSet(TaggedEC2Resource):
|
|||||||
elif filter_name == 'value':
|
elif filter_name == 'value':
|
||||||
values = [item for item in list(self._options.values()) if item]
|
values = [item for item in list(self._options.values()) if item]
|
||||||
return itertools.chain(*values)
|
return itertools.chain(*values)
|
||||||
|
else:
|
||||||
filter_value = super(
|
return super(DHCPOptionsSet, self).get_filter_value(
|
||||||
DHCPOptionsSet, self).get_filter_value(filter_name)
|
filter_name, 'DescribeDhcpOptions')
|
||||||
|
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeDhcpOptions".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def options(self):
|
def options(self):
|
||||||
@ -3229,6 +3167,10 @@ class VPNConnection(TaggedEC2Resource):
|
|||||||
self.options = None
|
self.options = None
|
||||||
self.static_routes = None
|
self.static_routes = None
|
||||||
|
|
||||||
|
def get_filter_value(self, filter_name):
|
||||||
|
return super(VPNConnection, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeVpnConnections')
|
||||||
|
|
||||||
|
|
||||||
class VPNConnectionBackend(object):
|
class VPNConnectionBackend(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -3408,14 +3350,9 @@ class NetworkAcl(TaggedEC2Resource):
|
|||||||
return self.id
|
return self.id
|
||||||
elif filter_name == "association.subnet-id":
|
elif filter_name == "association.subnet-id":
|
||||||
return [assoc.subnet_id for assoc in self.associations.values()]
|
return [assoc.subnet_id for assoc in self.associations.values()]
|
||||||
|
else:
|
||||||
filter_value = super(NetworkAcl, self).get_filter_value(filter_name)
|
return super(NetworkAcl, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeNetworkAcls')
|
||||||
if filter_value is None:
|
|
||||||
self.ec2_backend.raise_not_implemented_error(
|
|
||||||
"The filter '{0}' for DescribeNetworkAcls".format(filter_name))
|
|
||||||
|
|
||||||
return filter_value
|
|
||||||
|
|
||||||
|
|
||||||
class NetworkAclEntry(TaggedEC2Resource):
|
class NetworkAclEntry(TaggedEC2Resource):
|
||||||
@ -3444,6 +3381,10 @@ class VpnGateway(TaggedEC2Resource):
|
|||||||
self.attachments = {}
|
self.attachments = {}
|
||||||
super(VpnGateway, self).__init__()
|
super(VpnGateway, self).__init__()
|
||||||
|
|
||||||
|
def get_filter_value(self, filter_name):
|
||||||
|
return super(VpnGateway, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeVpnGateways')
|
||||||
|
|
||||||
|
|
||||||
class VpnGatewayAttachment(object):
|
class VpnGatewayAttachment(object):
|
||||||
def __init__(self, vpc_id, state):
|
def __init__(self, vpc_id, state):
|
||||||
@ -3505,6 +3446,10 @@ class CustomerGateway(TaggedEC2Resource):
|
|||||||
self.attachments = {}
|
self.attachments = {}
|
||||||
super(CustomerGateway, self).__init__()
|
super(CustomerGateway, self).__init__()
|
||||||
|
|
||||||
|
def get_filter_value(self, filter_name):
|
||||||
|
return super(CustomerGateway, self).get_filter_value(
|
||||||
|
filter_name, 'DescribeCustomerGateways')
|
||||||
|
|
||||||
|
|
||||||
class CustomerGatewayBackend(object):
|
class CustomerGatewayBackend(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -3648,10 +3593,7 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
|
|||||||
raise EC2ClientError(code, message)
|
raise EC2ClientError(code, message)
|
||||||
|
|
||||||
def raise_not_implemented_error(self, blurb):
|
def raise_not_implemented_error(self, blurb):
|
||||||
msg = "{0} has not been implemented in Moto yet." \
|
raise MotoNotImplementedError(blurb)
|
||||||
" Feel free to open an issue at" \
|
|
||||||
" https://github.com/spulec/moto/issues".format(blurb)
|
|
||||||
raise NotImplementedError(msg)
|
|
||||||
|
|
||||||
def do_resources_exist(self, resource_ids):
|
def do_resources_exist(self, resource_ids):
|
||||||
for resource_id in resource_ids:
|
for resource_id in resource_ids:
|
||||||
|
Loading…
Reference in New Issue
Block a user