parent
b66e04ffd5
commit
c3f06064ff
@ -239,6 +239,14 @@ class InvalidRouteError(EC2ClientError):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RouteAlreadyExistsError(EC2ClientError):
|
||||||
|
def __init__(self, cidr):
|
||||||
|
super().__init__(
|
||||||
|
"RouteAlreadyExists",
|
||||||
|
"The route identified by {0} already exists".format(cidr),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class InvalidInstanceIdError(EC2ClientError):
|
class InvalidInstanceIdError(EC2ClientError):
|
||||||
def __init__(self, instance_id):
|
def __init__(self, instance_id):
|
||||||
if isinstance(instance_id, str):
|
if isinstance(instance_id, str):
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
from moto.core import get_account_id, CloudFormationModel
|
from moto.core import get_account_id, CloudFormationModel
|
||||||
from .core import TaggedEC2Resource
|
from .core import TaggedEC2Resource
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
@ -7,6 +8,7 @@ from ..exceptions import (
|
|||||||
InvalidRouteTableIdError,
|
InvalidRouteTableIdError,
|
||||||
InvalidAssociationIdError,
|
InvalidAssociationIdError,
|
||||||
InvalidDestinationCIDRBlockParameterError,
|
InvalidDestinationCIDRBlockParameterError,
|
||||||
|
RouteAlreadyExistsError,
|
||||||
)
|
)
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
EC2_RESOURCE_TO_PREFIX,
|
EC2_RESOURCE_TO_PREFIX,
|
||||||
@ -323,11 +325,10 @@ class RouteBackend:
|
|||||||
elif EC2_RESOURCE_TO_PREFIX["vpc-endpoint"] in gateway_id:
|
elif EC2_RESOURCE_TO_PREFIX["vpc-endpoint"] in gateway_id:
|
||||||
gateway = self.get_vpc_end_point(gateway_id)
|
gateway = self.get_vpc_end_point(gateway_id)
|
||||||
|
|
||||||
try:
|
if destination_cidr_block:
|
||||||
if destination_cidr_block:
|
self.__validate_destination_cidr_block(
|
||||||
ipaddress.IPv4Network(str(destination_cidr_block), strict=False)
|
destination_cidr_block, route_table
|
||||||
except ValueError:
|
)
|
||||||
raise InvalidDestinationCIDRBlockParameterError(destination_cidr_block)
|
|
||||||
|
|
||||||
if nat_gateway_id is not None:
|
if nat_gateway_id is not None:
|
||||||
nat_gateway = self.nat_gateways.get(nat_gateway_id)
|
nat_gateway = self.nat_gateways.get(nat_gateway_id)
|
||||||
@ -440,3 +441,25 @@ class RouteBackend:
|
|||||||
if not deleted:
|
if not deleted:
|
||||||
raise InvalidRouteError(route_table_id, cidr)
|
raise InvalidRouteError(route_table_id, cidr)
|
||||||
return deleted
|
return deleted
|
||||||
|
|
||||||
|
def __validate_destination_cidr_block(self, destination_cidr_block, route_table):
|
||||||
|
"""
|
||||||
|
Utility function to check the destination CIDR block
|
||||||
|
Will validate the format and check for overlap with existing routes
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
ip_v4_network = ipaddress.IPv4Network(
|
||||||
|
str(destination_cidr_block), strict=False
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
raise InvalidDestinationCIDRBlockParameterError(destination_cidr_block)
|
||||||
|
|
||||||
|
if not route_table.routes:
|
||||||
|
return
|
||||||
|
for route in route_table.routes.values():
|
||||||
|
if not route.destination_cidr_block:
|
||||||
|
continue
|
||||||
|
if not route.local and ip_v4_network.overlaps(
|
||||||
|
ipaddress.IPv4Network(str(route.destination_cidr_block))
|
||||||
|
):
|
||||||
|
raise RouteAlreadyExistsError(destination_cidr_block)
|
||||||
|
@ -520,6 +520,56 @@ def test_routes_replace():
|
|||||||
ex.value.response["Error"]["Code"].should.equal("InvalidRouteTableID.NotFound")
|
ex.value.response["Error"]["Code"].should.equal("InvalidRouteTableID.NotFound")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_routes_already_exist():
|
||||||
|
client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
ec2 = boto3.resource("ec2", region_name="us-east-1")
|
||||||
|
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
|
||||||
|
|
||||||
|
main_route_table_id = client.describe_route_tables(
|
||||||
|
Filters=[
|
||||||
|
{"Name": "vpc-id", "Values": [vpc.id]},
|
||||||
|
{"Name": "association.main", "Values": ["true"]},
|
||||||
|
]
|
||||||
|
)["RouteTables"][0]["RouteTableId"]
|
||||||
|
main_route_table = ec2.RouteTable(main_route_table_id)
|
||||||
|
ROUTE_CIDR = "10.0.0.0/23"
|
||||||
|
ROUTE_SUB_CIDR = "10.0.0.0/24"
|
||||||
|
ROUTE_NO_CONFLICT_CIDR = "10.0.2.0/24"
|
||||||
|
|
||||||
|
# Various route targets
|
||||||
|
igw = ec2.create_internet_gateway()
|
||||||
|
|
||||||
|
# Create initial route
|
||||||
|
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=igw.id)
|
||||||
|
main_route_table.create_route(
|
||||||
|
DestinationCidrBlock=ROUTE_NO_CONFLICT_CIDR, GatewayId=igw.id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create
|
||||||
|
with pytest.raises(ClientError) as ex:
|
||||||
|
client.create_route(
|
||||||
|
RouteTableId=main_route_table.id,
|
||||||
|
DestinationCidrBlock=ROUTE_CIDR,
|
||||||
|
GatewayId=igw.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
|
||||||
|
ex.value.response["Error"]["Code"].should.equal("RouteAlreadyExists")
|
||||||
|
|
||||||
|
with pytest.raises(ClientError) as ex:
|
||||||
|
client.create_route(
|
||||||
|
RouteTableId=main_route_table.id,
|
||||||
|
DestinationCidrBlock=ROUTE_SUB_CIDR,
|
||||||
|
GatewayId=igw.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
|
||||||
|
ex.value.response["Error"]["Code"].should.equal("RouteAlreadyExists")
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_routes_not_supported():
|
def test_routes_not_supported():
|
||||||
client = boto3.client("ec2", region_name="us-east-1")
|
client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user