From 89fd71eb1698afde264595de8f5b446cd985a7b3 Mon Sep 17 00:00:00 2001 From: dreadpirateshawn Date: Tue, 14 Oct 2014 14:23:14 -0700 Subject: [PATCH] Route Tables: Added support for associate/disassociate subnets. (fixed idempotency) --- moto/ec2/models.py | 16 ++++++++++++++++ tests/test_ec2/test_route_tables.py | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/moto/ec2/models.py b/moto/ec2/models.py index c9e76a14c..e78137ca3 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -1647,6 +1647,14 @@ class RouteTableBackend(object): return True def associate_route_table(self, route_table_id, subnet_id): + # Idempotent if association already exists. + route_tables_by_subnet = ec2_backend.get_all_route_tables(filters={'association.subnet-id':[subnet_id]}) + if route_tables_by_subnet: + for association_id,check_subnet_id in route_tables_by_subnet[0].associations.items(): + if subnet_id == check_subnet_id: + return association_id + + # Association does not yet exist, so create it. route_table = self.get_route_table(route_table_id) subnet = self.get_subnet(subnet_id) # Validate subnet exists association_id = random_subnet_association_id() @@ -1660,9 +1668,17 @@ class RouteTableBackend(object): raise InvalidAssociationIdError(association_id) def replace_route_table_association(self, association_id, route_table_id): + # Idempotent if association already exists. + new_route_table = ec2_backend.get_route_table(route_table_id) + if association_id in new_route_table.associations: + return association_id + + # Find route table which currently has the association, error if none. route_tables_by_association_id = ec2_backend.get_all_route_tables(filters={'association.route-table-association-id':[association_id]}) if not route_tables_by_association_id: raise InvalidAssociationIdError(association_id) + + # Remove existing association, create new one. previous_route_table = route_tables_by_association_id[0] subnet_id = previous_route_table.associations.pop(association_id,None) return self.associate_route_table(route_table_id, subnet_id) diff --git a/tests/test_ec2/test_route_tables.py b/tests/test_ec2/test_route_tables.py index 31236ad25..58b65bbb1 100644 --- a/tests/test_ec2/test_route_tables.py +++ b/tests/test_ec2/test_route_tables.py @@ -177,6 +177,10 @@ def test_route_table_associations(): route_table.associations[0].route_table_id.should.equal(route_table.id) route_table.associations[0].subnet_id.should.equal(subnet.id) + # Associate is idempotent + association_id_idempotent = conn.associate_route_table(route_table.id, subnet.id) + association_id_idempotent.should.equal(association_id) + # Error: Attempt delete associated route table. with assert_raises(EC2ResponseError) as cm: conn.delete_route_table(route_table.id) @@ -265,6 +269,10 @@ def test_route_table_replace_route_table_association(): route_table2.associations[0].route_table_id.should.equal(route_table2.id) route_table2.associations[0].subnet_id.should.equal(subnet.id) + # Replace Association is idempotent + association_id_idempotent = conn.replace_route_table_association_with_assoc(association_id2, route_table2.id) + association_id_idempotent.should.equal(association_id2) + # Error: Replace association with invalid association ID with assert_raises(EC2ResponseError) as cm: conn.replace_route_table_association_with_assoc("rtbassoc-1234abcd", route_table1.id)