Route Tables: Added support for associate/disassociate subnets.

This commit is contained in:
dreadpirateshawn 2014-10-13 16:19:54 -07:00
commit 5d046c76e5
4 changed files with 164 additions and 19 deletions

View file

@ -73,6 +73,7 @@ from .utils import (
random_snapshot_id,
random_spot_request_id,
random_subnet_id,
random_subnet_association_id,
random_volume_id,
random_vpc_id,
random_vpc_peering_connection_id,
@ -1560,8 +1561,7 @@ class RouteTable(TaggedEC2Resource):
self.id = route_table_id
self.vpc_id = vpc_id
self.main = main
self.association_id = None
self.subnet_id = None
self.associations = {}
self.routes = {}
@classmethod
@ -1588,6 +1588,12 @@ class RouteTable(TaggedEC2Resource):
return 'false'
elif filter_name == "vpc-id":
return self.vpc_id
elif filter_name == "association.route-table-id":
return self.id
elif filter_name == "association.route-table-association-id":
return self.associations.keys()
elif filter_name == "association.subnet-id":
return self.associations.values()
filter_value = super(RouteTable, self).get_filter_value(filter_name)
@ -1631,10 +1637,27 @@ class RouteTableBackend(object):
return generic_filter(filters, route_tables)
def delete_route_table(self, route_table_id):
deleted = self.route_tables.pop(route_table_id, None)
if not deleted:
raise InvalidRouteTableIdError(route_table_id)
return deleted
route_table = self.get_route_table(route_table_id)
if route_table.associations:
raise DependencyViolationError(
"The routeTable '{0}' has dependencies and cannot be deleted."
.format(route_table_id)
)
self.route_tables.pop(route_table_id)
return True
def associate_route_table(self, route_table_id, subnet_id):
route_table = self.get_route_table(route_table_id)
subnet = self.get_subnet(subnet_id) # Validate subnet exists
association_id = random_subnet_association_id()
route_table.associations[association_id] = subnet_id
return association_id
def disassociate_route_table(self, association_id):
for route_table in self.route_tables.values():
if association_id in route_table.associations:
return route_table.associations.pop(association_id, None)
raise InvalidAssociationIdError(association_id)
class Route(object):

View file

@ -8,7 +8,11 @@ from moto.ec2.utils import route_table_ids_from_querystring, filters_from_querys
class RouteTables(BaseResponse):
def associate_route_table(self):
raise NotImplementedError('RouteTables(AmazonVPC).associate_route_table is not yet implemented')
route_table_id = self.querystring.get('RouteTableId')[0]
subnet_id = self.querystring.get('SubnetId')[0]
association_id = ec2_backend.associate_route_table(route_table_id, subnet_id)
template = Template(ASSOCIATE_ROUTE_TABLE_RESPONSE)
return template.render(association_id=association_id)
def create_route(self):
route_table_id = self.querystring.get('RouteTableId')[0]
@ -55,7 +59,10 @@ class RouteTables(BaseResponse):
return template.render(route_tables=route_tables)
def disassociate_route_table(self):
raise NotImplementedError('RouteTables(AmazonVPC).disassociate_route_table is not yet implemented')
association_id = self.querystring.get('AssociationId')[0]
ec2_backend.disassociate_route_table(association_id)
template = Template(DISASSOCIATE_ROUTE_TABLE_RESPONSE)
return template.render()
def replace_route(self):
route_table_id = self.querystring.get('RouteTableId')[0]
@ -151,18 +158,14 @@ DESCRIBE_ROUTE_TABLES_RESPONSE = """
{% endfor %}
</routeSet>
<associationSet>
{% if route_table.association_id %}
{% for association_id,subnet_id in route_table.associations.items() %}
<item>
<routeTableAssociationId>{{ route_table.association_id }}</routeTableAssociationId>
<routeTableId>{{ route_table.id }}</routeTableId>
{% if not route_table.subnet_id %}
<main>true</main>
{% endif %}
{% if route_table.subnet_id %}
<subnetId>{{ route_table.subnet_id }}</subnetId>
{% endif %}
<routeTableAssociationId>{{ association_id }}</routeTableAssociationId>
<routeTableId>{{ route_table.id }}</routeTableId>
<main>false</main>
<subnetId>{{ subnet_id }}</subnetId>
</item>
{% endif %}
{% endfor %}
</associationSet>
<tagSet/>
</item>
@ -184,3 +187,17 @@ DELETE_ROUTE_TABLE_RESPONSE = """
<return>true</return>
</DeleteRouteTableResponse>
"""
ASSOCIATE_ROUTE_TABLE_RESPONSE = """
<AssociateRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<associationId>{{ association_id }}</associationId>
</AssociateRouteTableResponse>
"""
DISASSOCIATE_ROUTE_TABLE_RESPONSE = """
<DisassociateRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<return>true</return>
</DisassociateRouteTableResponse>
"""

View file

@ -14,6 +14,7 @@ EC2_RESOURCE_TO_PREFIX = {
'network-interface-attachment': 'eni-attach',
'reserved-instance': 'uuid4',
'route-table': 'rtb',
'route-table-association': 'rtbassoc',
'security-group': 'sg',
'snapshot': 'snap',
'spot-instance-request': 'sir',
@ -67,6 +68,10 @@ def random_subnet_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['subnet'])
def random_subnet_association_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['route-table-association'])
def random_volume_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['volume'])