Techdebt: MyPy EC2 (r-models) (#5909)
This commit is contained in:
parent
749a8572ba
commit
2ee5dcea63
@ -220,7 +220,7 @@ class InvalidRouteTableIdError(EC2ClientError):
|
|||||||
|
|
||||||
|
|
||||||
class InvalidRouteError(EC2ClientError):
|
class InvalidRouteError(EC2ClientError):
|
||||||
def __init__(self, route_table_id, cidr):
|
def __init__(self, route_table_id: str, cidr: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"InvalidRoute.NotFound",
|
"InvalidRoute.NotFound",
|
||||||
f"no route with destination-cidr-block {cidr} in route table {route_table_id}",
|
f"no route with destination-cidr-block {cidr} in route table {route_table_id}",
|
||||||
@ -228,7 +228,7 @@ class InvalidRouteError(EC2ClientError):
|
|||||||
|
|
||||||
|
|
||||||
class RouteAlreadyExistsError(EC2ClientError):
|
class RouteAlreadyExistsError(EC2ClientError):
|
||||||
def __init__(self, cidr):
|
def __init__(self, cidr: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"RouteAlreadyExists", f"The route identified by {cidr} already exists"
|
"RouteAlreadyExists", f"The route identified by {cidr} already exists"
|
||||||
)
|
)
|
||||||
@ -593,7 +593,7 @@ class InvalidCIDRBlockParameterError(EC2ClientError):
|
|||||||
|
|
||||||
|
|
||||||
class InvalidDestinationCIDRBlockParameterError(EC2ClientError):
|
class InvalidDestinationCIDRBlockParameterError(EC2ClientError):
|
||||||
def __init__(self, cidr_block):
|
def __init__(self, cidr_block: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"InvalidParameterValue",
|
"InvalidParameterValue",
|
||||||
f"Value ({cidr_block}) for parameter destinationCidrBlock is invalid. This is not a valid CIDR block.",
|
f"Value ({cidr_block}) for parameter destinationCidrBlock is invalid. This is not a valid CIDR block.",
|
||||||
|
@ -28,7 +28,7 @@ from .instance_types import InstanceTypeBackend, InstanceTypeOfferingBackend
|
|||||||
from .nat_gateways import NatGatewayBackend
|
from .nat_gateways import NatGatewayBackend
|
||||||
from .network_acls import NetworkAclBackend
|
from .network_acls import NetworkAclBackend
|
||||||
from .availability_zones_and_regions import RegionsAndZonesBackend
|
from .availability_zones_and_regions import RegionsAndZonesBackend
|
||||||
from .route_tables import RouteBackend, RouteTableBackend
|
from .route_tables import RouteBackend
|
||||||
from .security_groups import SecurityGroupBackend
|
from .security_groups import SecurityGroupBackend
|
||||||
from .spot_requests import (
|
from .spot_requests import (
|
||||||
SpotRequestBackend,
|
SpotRequestBackend,
|
||||||
@ -101,7 +101,6 @@ class EC2Backend(
|
|||||||
VPNConnectionBackend,
|
VPNConnectionBackend,
|
||||||
VPCServiceConfigurationBackend,
|
VPCServiceConfigurationBackend,
|
||||||
VPCPeeringConnectionBackend,
|
VPCPeeringConnectionBackend,
|
||||||
RouteTableBackend,
|
|
||||||
RouteBackend,
|
RouteBackend,
|
||||||
InternetGatewayBackend,
|
InternetGatewayBackend,
|
||||||
EgressOnlyInternetGatewayBackend,
|
EgressOnlyInternetGatewayBackend,
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
|
from typing import Any, Dict, List, Optional, Set
|
||||||
|
|
||||||
from moto.core import CloudFormationModel
|
from moto.core import CloudFormationModel
|
||||||
|
from moto.ec2.models.carrier_gateways import CarrierGateway
|
||||||
|
from moto.ec2.models.elastic_network_interfaces import NetworkInterface
|
||||||
|
from moto.ec2.models.internet_gateways import EgressOnlyInternetGateway
|
||||||
|
from moto.ec2.models.instances import Instance
|
||||||
|
from moto.ec2.models.managed_prefixes import ManagedPrefixList
|
||||||
|
from moto.ec2.models.nat_gateways import NatGateway
|
||||||
|
from moto.ec2.models.transit_gateway import TransitGateway
|
||||||
|
from moto.ec2.models.vpc_peering_connections import VPCPeeringConnection
|
||||||
|
from moto.ec2.models.vpn_gateway import VpnGateway
|
||||||
from .core import TaggedEC2Resource
|
from .core import TaggedEC2Resource
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
DependencyViolationError,
|
DependencyViolationError,
|
||||||
@ -16,39 +26,42 @@ from ..utils import (
|
|||||||
generic_filter,
|
generic_filter,
|
||||||
random_subnet_association_id,
|
random_subnet_association_id,
|
||||||
random_route_table_id,
|
random_route_table_id,
|
||||||
split_route_id,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RouteTable(TaggedEC2Resource, CloudFormationModel):
|
class RouteTable(TaggedEC2Resource, CloudFormationModel):
|
||||||
def __init__(self, ec2_backend, route_table_id, vpc_id, main=False):
|
def __init__(
|
||||||
|
self, ec2_backend: Any, route_table_id: str, vpc_id: str, main: bool = False
|
||||||
|
):
|
||||||
self.ec2_backend = ec2_backend
|
self.ec2_backend = ec2_backend
|
||||||
self.id = route_table_id
|
self.id = route_table_id
|
||||||
self.vpc_id = vpc_id
|
self.vpc_id = vpc_id
|
||||||
if main:
|
self.main_association_id = random_subnet_association_id() if main else None
|
||||||
self.main_association_id = random_subnet_association_id()
|
self.associations: Dict[str, str] = {}
|
||||||
else:
|
self.routes: Dict[str, Route] = {}
|
||||||
self.main_association_id = None
|
|
||||||
self.associations = {}
|
|
||||||
self.routes = {}
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def owner_id(self):
|
def owner_id(self) -> str:
|
||||||
return self.ec2_backend.account_id
|
return self.ec2_backend.account_id
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_name_type():
|
def cloudformation_name_type() -> str:
|
||||||
return None
|
return ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_type():
|
def cloudformation_type() -> str:
|
||||||
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html
|
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html
|
||||||
return "AWS::EC2::RouteTable"
|
return "AWS::EC2::RouteTable"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_from_cloudformation_json(
|
def create_from_cloudformation_json( # type: ignore[misc]
|
||||||
cls, resource_name, cloudformation_json, account_id, region_name, **kwargs
|
cls,
|
||||||
):
|
resource_name: str,
|
||||||
|
cloudformation_json: Any,
|
||||||
|
account_id: str,
|
||||||
|
region_name: str,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> "RouteTable":
|
||||||
from ..models import ec2_backends
|
from ..models import ec2_backends
|
||||||
|
|
||||||
properties = cloudformation_json["Properties"]
|
properties = cloudformation_json["Properties"]
|
||||||
@ -59,10 +72,12 @@ class RouteTable(TaggedEC2Resource, CloudFormationModel):
|
|||||||
return route_table
|
return route_table
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def physical_resource_id(self):
|
def physical_resource_id(self) -> str:
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
def get_filter_value(self, filter_name):
|
def get_filter_value(
|
||||||
|
self, filter_name: str, method_name: Optional[str] = None
|
||||||
|
) -> Any:
|
||||||
if filter_name == "association.main":
|
if filter_name == "association.main":
|
||||||
# Note: Boto only supports 'true'.
|
# Note: Boto only supports 'true'.
|
||||||
# https://github.com/boto/boto/issues/1742
|
# https://github.com/boto/boto/issues/1742
|
||||||
@ -96,7 +111,7 @@ class RouteTable(TaggedEC2Resource, CloudFormationModel):
|
|||||||
return super().get_filter_value(filter_name, "DescribeRouteTables")
|
return super().get_filter_value(filter_name, "DescribeRouteTables")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def all_associations_ids(self):
|
def all_associations_ids(self) -> Set[str]:
|
||||||
# NOTE(yoctozepto): Doing an explicit copy to not touch the original.
|
# NOTE(yoctozepto): Doing an explicit copy to not touch the original.
|
||||||
all_associations = set(self.associations)
|
all_associations = set(self.associations)
|
||||||
if self.main_association_id is not None:
|
if self.main_association_id is not None:
|
||||||
@ -104,16 +119,108 @@ class RouteTable(TaggedEC2Resource, CloudFormationModel):
|
|||||||
return all_associations
|
return all_associations
|
||||||
|
|
||||||
|
|
||||||
class RouteTableBackend:
|
class Route(CloudFormationModel):
|
||||||
def __init__(self):
|
def __init__(
|
||||||
self.route_tables = {}
|
self,
|
||||||
|
route_table: RouteTable,
|
||||||
|
destination_cidr_block: Optional[str],
|
||||||
|
destination_ipv6_cidr_block: Optional[str],
|
||||||
|
destination_prefix_list: Optional[ManagedPrefixList] = None,
|
||||||
|
local: bool = False,
|
||||||
|
gateway: Optional[VpnGateway] = None,
|
||||||
|
instance: Optional[Instance] = None,
|
||||||
|
nat_gateway: Optional[NatGateway] = None,
|
||||||
|
egress_only_igw: Optional[EgressOnlyInternetGateway] = None,
|
||||||
|
transit_gateway: Optional[TransitGateway] = None,
|
||||||
|
interface: Optional[NetworkInterface] = None,
|
||||||
|
vpc_pcx: Optional[VPCPeeringConnection] = None,
|
||||||
|
carrier_gateway: Optional[CarrierGateway] = None,
|
||||||
|
):
|
||||||
|
self.id = generate_route_id(
|
||||||
|
route_table.id,
|
||||||
|
destination_cidr_block,
|
||||||
|
destination_ipv6_cidr_block,
|
||||||
|
destination_prefix_list.id if destination_prefix_list else None,
|
||||||
|
)
|
||||||
|
self.route_table = route_table
|
||||||
|
self.destination_cidr_block = destination_cidr_block
|
||||||
|
self.destination_ipv6_cidr_block = destination_ipv6_cidr_block
|
||||||
|
self.destination_prefix_list = destination_prefix_list
|
||||||
|
self.local = local
|
||||||
|
self.gateway = gateway
|
||||||
|
self.instance = instance
|
||||||
|
self.nat_gateway = nat_gateway
|
||||||
|
self.egress_only_igw = egress_only_igw
|
||||||
|
self.transit_gateway = transit_gateway
|
||||||
|
self.interface = interface
|
||||||
|
self.vpc_pcx = vpc_pcx
|
||||||
|
self.carrier_gateway = carrier_gateway
|
||||||
|
|
||||||
def create_route_table(self, vpc_id, tags=None, main=False):
|
@property
|
||||||
|
def physical_resource_id(self) -> str:
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cloudformation_name_type() -> str:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cloudformation_type() -> str:
|
||||||
|
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html
|
||||||
|
return "AWS::EC2::Route"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_cloudformation_json( # type: ignore[misc]
|
||||||
|
cls,
|
||||||
|
resource_name: str,
|
||||||
|
cloudformation_json: Any,
|
||||||
|
account_id: str,
|
||||||
|
region_name: str,
|
||||||
|
**kwargs: str,
|
||||||
|
) -> "Route":
|
||||||
|
from ..models import ec2_backends
|
||||||
|
|
||||||
|
properties = cloudformation_json["Properties"]
|
||||||
|
|
||||||
|
gateway_id = properties.get("GatewayId")
|
||||||
|
instance_id = properties.get("InstanceId")
|
||||||
|
interface_id = properties.get("NetworkInterfaceId")
|
||||||
|
nat_gateway_id = properties.get("NatGatewayId")
|
||||||
|
egress_only_igw_id = properties.get("EgressOnlyInternetGatewayId")
|
||||||
|
transit_gateway_id = properties.get("TransitGatewayId")
|
||||||
|
pcx_id = properties.get("VpcPeeringConnectionId")
|
||||||
|
|
||||||
|
route_table_id = properties["RouteTableId"]
|
||||||
|
ec2_backend = ec2_backends[account_id][region_name]
|
||||||
|
route = ec2_backend.create_route(
|
||||||
|
route_table_id=route_table_id,
|
||||||
|
destination_cidr_block=properties.get("DestinationCidrBlock"),
|
||||||
|
gateway_id=gateway_id,
|
||||||
|
instance_id=instance_id,
|
||||||
|
nat_gateway_id=nat_gateway_id,
|
||||||
|
egress_only_igw_id=egress_only_igw_id,
|
||||||
|
transit_gateway_id=transit_gateway_id,
|
||||||
|
interface_id=interface_id,
|
||||||
|
vpc_peering_connection_id=pcx_id,
|
||||||
|
)
|
||||||
|
return route
|
||||||
|
|
||||||
|
|
||||||
|
class RouteBackend:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.route_tables: Dict[str, RouteTable] = {}
|
||||||
|
|
||||||
|
def create_route_table(
|
||||||
|
self,
|
||||||
|
vpc_id: str,
|
||||||
|
tags: Optional[List[Dict[str, str]]] = None,
|
||||||
|
main: bool = False,
|
||||||
|
) -> RouteTable:
|
||||||
route_table_id = random_route_table_id()
|
route_table_id = random_route_table_id()
|
||||||
vpc = self.get_vpc(vpc_id) # Validate VPC exists
|
vpc = self.get_vpc(vpc_id) # type: ignore[attr-defined] # Validate VPC exists
|
||||||
route_table = RouteTable(self, route_table_id, vpc_id, main=main)
|
route_table = RouteTable(self, route_table_id, vpc_id, main=main)
|
||||||
for tag in tags or []:
|
for tag in tags or []:
|
||||||
route_table.add_tag(tag.get("Key"), tag.get("Value"))
|
route_table.add_tag(tag["Key"], tag["Value"])
|
||||||
self.route_tables[route_table_id] = route_table
|
self.route_tables[route_table_id] = route_table
|
||||||
|
|
||||||
# creating default routes for ipv4 cirds
|
# creating default routes for ipv4 cirds
|
||||||
@ -133,14 +240,16 @@ class RouteTableBackend:
|
|||||||
|
|
||||||
return route_table
|
return route_table
|
||||||
|
|
||||||
def get_route_table(self, route_table_id):
|
def get_route_table(self, route_table_id: str) -> RouteTable:
|
||||||
route_table = self.route_tables.get(route_table_id, None)
|
route_table = self.route_tables.get(route_table_id, None)
|
||||||
if not route_table:
|
if not route_table:
|
||||||
raise InvalidRouteTableIdError(route_table_id)
|
raise InvalidRouteTableIdError(route_table_id)
|
||||||
return route_table
|
return route_table
|
||||||
|
|
||||||
def describe_route_tables(self, route_table_ids=None, filters=None):
|
def describe_route_tables(
|
||||||
route_tables = self.route_tables.copy().values()
|
self, route_table_ids: Optional[List[str]] = None, filters: Any = None
|
||||||
|
) -> List[RouteTable]:
|
||||||
|
route_tables = list(self.route_tables.values())
|
||||||
|
|
||||||
if route_table_ids:
|
if route_table_ids:
|
||||||
route_tables = [
|
route_tables = [
|
||||||
@ -158,16 +267,20 @@ class RouteTableBackend:
|
|||||||
|
|
||||||
return generic_filter(filters, route_tables)
|
return generic_filter(filters, route_tables)
|
||||||
|
|
||||||
def delete_route_table(self, route_table_id):
|
def delete_route_table(self, route_table_id: str) -> None:
|
||||||
route_table = self.get_route_table(route_table_id)
|
route_table = self.get_route_table(route_table_id)
|
||||||
if route_table.associations:
|
if route_table.associations:
|
||||||
raise DependencyViolationError(
|
raise DependencyViolationError(
|
||||||
f"The routeTable '{route_table_id}' has dependencies and cannot be deleted."
|
f"The routeTable '{route_table_id}' has dependencies and cannot be deleted."
|
||||||
)
|
)
|
||||||
self.route_tables.pop(route_table_id)
|
self.route_tables.pop(route_table_id)
|
||||||
return True
|
|
||||||
|
|
||||||
def associate_route_table(self, route_table_id, gateway_id=None, subnet_id=None):
|
def associate_route_table(
|
||||||
|
self,
|
||||||
|
route_table_id: str,
|
||||||
|
gateway_id: Optional[str] = None,
|
||||||
|
subnet_id: Optional[str] = None,
|
||||||
|
) -> str:
|
||||||
# Idempotent if association already exists.
|
# Idempotent if association already exists.
|
||||||
route_tables_by_subnet = self.describe_route_tables(
|
route_tables_by_subnet = self.describe_route_tables(
|
||||||
filters={"association.subnet-id": [subnet_id]}
|
filters={"association.subnet-id": [subnet_id]}
|
||||||
@ -182,22 +295,24 @@ class RouteTableBackend:
|
|||||||
# Association does not yet exist, so create it.
|
# Association does not yet exist, so create it.
|
||||||
route_table = self.get_route_table(route_table_id)
|
route_table = self.get_route_table(route_table_id)
|
||||||
if gateway_id is None:
|
if gateway_id is None:
|
||||||
self.get_subnet(subnet_id) # Validate subnet exists
|
self.get_subnet(subnet_id) # type: ignore[attr-defined] # Validate subnet exists
|
||||||
association_id = random_subnet_association_id()
|
association_id = random_subnet_association_id()
|
||||||
route_table.associations[association_id] = subnet_id
|
route_table.associations[association_id] = subnet_id # type: ignore[assignment]
|
||||||
return association_id
|
return association_id
|
||||||
if subnet_id is None:
|
else:
|
||||||
association_id = random_subnet_association_id()
|
association_id = random_subnet_association_id()
|
||||||
route_table.associations[association_id] = gateway_id
|
route_table.associations[association_id] = gateway_id
|
||||||
return association_id
|
return association_id
|
||||||
|
|
||||||
def disassociate_route_table(self, association_id):
|
def disassociate_route_table(self, association_id: str) -> Optional[str]:
|
||||||
for route_table in self.route_tables.values():
|
for route_table in self.route_tables.values():
|
||||||
if association_id in route_table.associations:
|
if association_id in route_table.associations:
|
||||||
return route_table.associations.pop(association_id, None)
|
return route_table.associations.pop(association_id, None)
|
||||||
raise InvalidAssociationIdError(association_id)
|
raise InvalidAssociationIdError(association_id)
|
||||||
|
|
||||||
def replace_route_table_association(self, association_id, route_table_id):
|
def replace_route_table_association(
|
||||||
|
self, association_id: str, route_table_id: str
|
||||||
|
) -> str:
|
||||||
# Idempotent if association already exists.
|
# Idempotent if association already exists.
|
||||||
new_route_table = self.get_route_table(route_table_id)
|
new_route_table = self.get_route_table(route_table_id)
|
||||||
if association_id in new_route_table.all_associations_ids:
|
if association_id in new_route_table.all_associations_ids:
|
||||||
@ -223,107 +338,22 @@ class RouteTableBackend:
|
|||||||
new_route_table.associations[new_association_id] = association_target_id
|
new_route_table.associations[new_association_id] = association_target_id
|
||||||
return new_association_id
|
return new_association_id
|
||||||
|
|
||||||
|
|
||||||
# TODO: refractor to isloate class methods from backend logic
|
|
||||||
class Route(CloudFormationModel):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
route_table,
|
|
||||||
destination_cidr_block,
|
|
||||||
destination_ipv6_cidr_block,
|
|
||||||
destination_prefix_list=None,
|
|
||||||
local=False,
|
|
||||||
gateway=None,
|
|
||||||
instance=None,
|
|
||||||
nat_gateway=None,
|
|
||||||
egress_only_igw=None,
|
|
||||||
transit_gateway=None,
|
|
||||||
interface=None,
|
|
||||||
vpc_pcx=None,
|
|
||||||
carrier_gateway=None,
|
|
||||||
):
|
|
||||||
self.id = generate_route_id(
|
|
||||||
route_table.id,
|
|
||||||
destination_cidr_block,
|
|
||||||
destination_ipv6_cidr_block,
|
|
||||||
destination_prefix_list.id if destination_prefix_list else None,
|
|
||||||
)
|
|
||||||
self.route_table = route_table
|
|
||||||
self.destination_cidr_block = destination_cidr_block
|
|
||||||
self.destination_ipv6_cidr_block = destination_ipv6_cidr_block
|
|
||||||
self.destination_prefix_list = destination_prefix_list
|
|
||||||
self.local = local
|
|
||||||
self.gateway = gateway
|
|
||||||
self.instance = instance
|
|
||||||
self.nat_gateway = nat_gateway
|
|
||||||
self.egress_only_igw = egress_only_igw
|
|
||||||
self.transit_gateway = transit_gateway
|
|
||||||
self.interface = interface
|
|
||||||
self.vpc_pcx = vpc_pcx
|
|
||||||
self.carrier_gateway = carrier_gateway
|
|
||||||
|
|
||||||
@property
|
|
||||||
def physical_resource_id(self):
|
|
||||||
return self.id
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def cloudformation_name_type():
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def cloudformation_type():
|
|
||||||
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html
|
|
||||||
return "AWS::EC2::Route"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create_from_cloudformation_json(
|
|
||||||
cls, resource_name, cloudformation_json, account_id, region_name, **kwargs
|
|
||||||
):
|
|
||||||
from ..models import ec2_backends
|
|
||||||
|
|
||||||
properties = cloudformation_json["Properties"]
|
|
||||||
|
|
||||||
gateway_id = properties.get("GatewayId")
|
|
||||||
instance_id = properties.get("InstanceId")
|
|
||||||
interface_id = properties.get("NetworkInterfaceId")
|
|
||||||
nat_gateway_id = properties.get("NatGatewayId")
|
|
||||||
egress_only_igw_id = properties.get("EgressOnlyInternetGatewayId")
|
|
||||||
transit_gateway_id = properties.get("TransitGatewayId")
|
|
||||||
pcx_id = properties.get("VpcPeeringConnectionId")
|
|
||||||
|
|
||||||
route_table_id = properties["RouteTableId"]
|
|
||||||
ec2_backend = ec2_backends[account_id][region_name]
|
|
||||||
route_table = ec2_backend.create_route(
|
|
||||||
route_table_id=route_table_id,
|
|
||||||
destination_cidr_block=properties.get("DestinationCidrBlock"),
|
|
||||||
gateway_id=gateway_id,
|
|
||||||
instance_id=instance_id,
|
|
||||||
nat_gateway_id=nat_gateway_id,
|
|
||||||
egress_only_igw_id=egress_only_igw_id,
|
|
||||||
transit_gateway_id=transit_gateway_id,
|
|
||||||
interface_id=interface_id,
|
|
||||||
vpc_peering_connection_id=pcx_id,
|
|
||||||
)
|
|
||||||
return route_table
|
|
||||||
|
|
||||||
|
|
||||||
class RouteBackend:
|
|
||||||
def create_route(
|
def create_route(
|
||||||
self,
|
self,
|
||||||
route_table_id,
|
route_table_id: str,
|
||||||
destination_cidr_block,
|
destination_cidr_block: Optional[str],
|
||||||
destination_ipv6_cidr_block=None,
|
destination_ipv6_cidr_block: Optional[str] = None,
|
||||||
destination_prefix_list_id=None,
|
destination_prefix_list_id: Optional[str] = None,
|
||||||
local=False,
|
local: bool = False,
|
||||||
gateway_id=None,
|
gateway_id: Optional[str] = None,
|
||||||
instance_id=None,
|
instance_id: Optional[str] = None,
|
||||||
nat_gateway_id=None,
|
nat_gateway_id: Optional[str] = None,
|
||||||
egress_only_igw_id=None,
|
egress_only_igw_id: Optional[str] = None,
|
||||||
transit_gateway_id=None,
|
transit_gateway_id: Optional[str] = None,
|
||||||
interface_id=None,
|
interface_id: Optional[str] = None,
|
||||||
vpc_peering_connection_id=None,
|
vpc_peering_connection_id: Optional[str] = None,
|
||||||
carrier_gateway_id=None,
|
carrier_gateway_id: Optional[str] = None,
|
||||||
):
|
) -> Route:
|
||||||
gateway = None
|
gateway = None
|
||||||
nat_gateway = None
|
nat_gateway = None
|
||||||
transit_gateway = None
|
transit_gateway = None
|
||||||
@ -336,16 +366,16 @@ class RouteBackend:
|
|||||||
|
|
||||||
if interface_id:
|
if interface_id:
|
||||||
# for validating interface Id whether it is valid or not.
|
# for validating interface Id whether it is valid or not.
|
||||||
interface = self.get_network_interface(interface_id)
|
interface = self.get_network_interface(interface_id) # type: ignore[attr-defined]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if gateway_id:
|
if gateway_id:
|
||||||
if EC2_RESOURCE_TO_PREFIX["vpn-gateway"] in gateway_id:
|
if EC2_RESOURCE_TO_PREFIX["vpn-gateway"] in gateway_id:
|
||||||
gateway = self.get_vpn_gateway(gateway_id)
|
gateway = self.get_vpn_gateway(gateway_id) # type: ignore[attr-defined]
|
||||||
elif EC2_RESOURCE_TO_PREFIX["internet-gateway"] in gateway_id:
|
elif EC2_RESOURCE_TO_PREFIX["internet-gateway"] in gateway_id:
|
||||||
gateway = self.get_internet_gateway(gateway_id)
|
gateway = self.get_internet_gateway(gateway_id) # type: ignore[attr-defined]
|
||||||
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) # type: ignore[attr-defined]
|
||||||
|
|
||||||
if destination_cidr_block:
|
if destination_cidr_block:
|
||||||
self.__validate_destination_cidr_block(
|
self.__validate_destination_cidr_block(
|
||||||
@ -353,17 +383,17 @@ class RouteBackend:
|
|||||||
)
|
)
|
||||||
|
|
||||||
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) # type: ignore[attr-defined]
|
||||||
if egress_only_igw_id is not None:
|
if egress_only_igw_id is not None:
|
||||||
egress_only_igw = self.get_egress_only_igw(egress_only_igw_id)
|
egress_only_igw = self.get_egress_only_igw(egress_only_igw_id) # type: ignore[attr-defined]
|
||||||
if transit_gateway_id is not None:
|
if transit_gateway_id is not None:
|
||||||
transit_gateway = self.transit_gateways.get(transit_gateway_id)
|
transit_gateway = self.transit_gateways.get(transit_gateway_id) # type: ignore[attr-defined]
|
||||||
if destination_prefix_list_id is not None:
|
if destination_prefix_list_id is not None:
|
||||||
destination_prefix_list = self.managed_prefix_lists.get(
|
destination_prefix_list = self.managed_prefix_lists.get( # type: ignore[attr-defined]
|
||||||
destination_prefix_list_id
|
destination_prefix_list_id
|
||||||
)
|
)
|
||||||
if carrier_gateway_id is not None:
|
if carrier_gateway_id is not None:
|
||||||
carrier_gateway = self.carrier_gateways.get(carrier_gateway_id)
|
carrier_gateway = self.carrier_gateways.get(carrier_gateway_id) # type: ignore[attr-defined]
|
||||||
|
|
||||||
route = Route(
|
route = Route(
|
||||||
route_table,
|
route_table,
|
||||||
@ -372,13 +402,13 @@ class RouteBackend:
|
|||||||
destination_prefix_list,
|
destination_prefix_list,
|
||||||
local=local,
|
local=local,
|
||||||
gateway=gateway,
|
gateway=gateway,
|
||||||
instance=self.get_instance(instance_id) if instance_id else None,
|
instance=self.get_instance(instance_id) if instance_id else None, # type: ignore[attr-defined]
|
||||||
nat_gateway=nat_gateway,
|
nat_gateway=nat_gateway,
|
||||||
egress_only_igw=egress_only_igw,
|
egress_only_igw=egress_only_igw,
|
||||||
transit_gateway=transit_gateway,
|
transit_gateway=transit_gateway,
|
||||||
interface=interface,
|
interface=interface,
|
||||||
carrier_gateway=carrier_gateway,
|
carrier_gateway=carrier_gateway,
|
||||||
vpc_pcx=self.get_vpc_peering_connection(vpc_peering_connection_id)
|
vpc_pcx=self.get_vpc_peering_connection(vpc_peering_connection_id) # type: ignore[attr-defined]
|
||||||
if vpc_peering_connection_id
|
if vpc_peering_connection_id
|
||||||
else None,
|
else None,
|
||||||
)
|
)
|
||||||
@ -387,18 +417,18 @@ class RouteBackend:
|
|||||||
|
|
||||||
def replace_route(
|
def replace_route(
|
||||||
self,
|
self,
|
||||||
route_table_id,
|
route_table_id: str,
|
||||||
destination_cidr_block,
|
destination_cidr_block: str,
|
||||||
destination_ipv6_cidr_block=None,
|
destination_ipv6_cidr_block: Optional[str] = None,
|
||||||
destination_prefix_list_id=None,
|
destination_prefix_list_id: Optional[str] = None,
|
||||||
nat_gateway_id=None,
|
nat_gateway_id: Optional[str] = None,
|
||||||
egress_only_igw_id=None,
|
egress_only_igw_id: Optional[str] = None,
|
||||||
transit_gateway_id=None,
|
transit_gateway_id: Optional[str] = None,
|
||||||
gateway_id=None,
|
gateway_id: Optional[str] = None,
|
||||||
instance_id=None,
|
instance_id: Optional[str] = None,
|
||||||
interface_id=None,
|
interface_id: Optional[str] = None,
|
||||||
vpc_peering_connection_id=None,
|
vpc_peering_connection_id: Optional[str] = None,
|
||||||
):
|
) -> Route:
|
||||||
route_table = self.get_route_table(route_table_id)
|
route_table = self.get_route_table(route_table_id)
|
||||||
route_id = generate_route_id(
|
route_id = generate_route_id(
|
||||||
route_table.id, destination_cidr_block, destination_ipv6_cidr_block
|
route_table.id, destination_cidr_block, destination_ipv6_cidr_block
|
||||||
@ -406,7 +436,7 @@ class RouteBackend:
|
|||||||
route = route_table.routes[route_id]
|
route = route_table.routes[route_id]
|
||||||
|
|
||||||
if interface_id:
|
if interface_id:
|
||||||
self.raise_not_implemented_error("ReplaceRoute to NetworkInterfaceId")
|
self.raise_not_implemented_error("ReplaceRoute to NetworkInterfaceId") # type: ignore[attr-defined]
|
||||||
|
|
||||||
route.gateway = None
|
route.gateway = None
|
||||||
route.nat_gateway = None
|
route.nat_gateway = None
|
||||||
@ -414,25 +444,25 @@ class RouteBackend:
|
|||||||
route.transit_gateway = None
|
route.transit_gateway = None
|
||||||
if gateway_id:
|
if gateway_id:
|
||||||
if EC2_RESOURCE_TO_PREFIX["vpn-gateway"] in gateway_id:
|
if EC2_RESOURCE_TO_PREFIX["vpn-gateway"] in gateway_id:
|
||||||
route.gateway = self.get_vpn_gateway(gateway_id)
|
route.gateway = self.get_vpn_gateway(gateway_id) # type: ignore[attr-defined]
|
||||||
elif EC2_RESOURCE_TO_PREFIX["internet-gateway"] in gateway_id:
|
elif EC2_RESOURCE_TO_PREFIX["internet-gateway"] in gateway_id:
|
||||||
route.gateway = self.get_internet_gateway(gateway_id)
|
route.gateway = self.get_internet_gateway(gateway_id) # type: ignore[attr-defined]
|
||||||
|
|
||||||
if nat_gateway_id is not None:
|
if nat_gateway_id is not None:
|
||||||
route.nat_gateway = self.nat_gateways.get(nat_gateway_id)
|
route.nat_gateway = self.nat_gateways.get(nat_gateway_id) # type: ignore[attr-defined]
|
||||||
if egress_only_igw_id is not None:
|
if egress_only_igw_id is not None:
|
||||||
route.egress_only_igw = self.get_egress_only_igw(egress_only_igw_id)
|
route.egress_only_igw = self.get_egress_only_igw(egress_only_igw_id) # type: ignore[attr-defined]
|
||||||
if transit_gateway_id is not None:
|
if transit_gateway_id is not None:
|
||||||
route.transit_gateway = self.transit_gateways.get(transit_gateway_id)
|
route.transit_gateway = self.transit_gateways.get(transit_gateway_id) # type: ignore[attr-defined]
|
||||||
if destination_prefix_list_id is not None:
|
if destination_prefix_list_id is not None:
|
||||||
route.prefix_list = self.managed_prefix_lists.get(
|
route.prefix_list = self.managed_prefix_lists.get( # type: ignore[attr-defined]
|
||||||
destination_prefix_list_id
|
destination_prefix_list_id
|
||||||
)
|
)
|
||||||
|
|
||||||
route.instance = self.get_instance(instance_id) if instance_id else None
|
route.instance = self.get_instance(instance_id) if instance_id else None # type: ignore[attr-defined]
|
||||||
route.interface = None
|
route.interface = None
|
||||||
route.vpc_pcx = (
|
route.vpc_pcx = (
|
||||||
self.get_vpc_peering_connection(vpc_peering_connection_id)
|
self.get_vpc_peering_connection(vpc_peering_connection_id) # type: ignore[attr-defined]
|
||||||
if vpc_peering_connection_id
|
if vpc_peering_connection_id
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
@ -440,18 +470,13 @@ class RouteBackend:
|
|||||||
route_table.routes[route.id] = route
|
route_table.routes[route.id] = route
|
||||||
return route
|
return route
|
||||||
|
|
||||||
def get_route(self, route_id):
|
|
||||||
route_table_id, _ = split_route_id(route_id)
|
|
||||||
route_table = self.get_route_table(route_table_id)
|
|
||||||
return route_table.get(route_id)
|
|
||||||
|
|
||||||
def delete_route(
|
def delete_route(
|
||||||
self,
|
self,
|
||||||
route_table_id,
|
route_table_id: str,
|
||||||
destination_cidr_block,
|
destination_cidr_block: str,
|
||||||
destination_ipv6_cidr_block=None,
|
destination_ipv6_cidr_block: Optional[str] = None,
|
||||||
destination_prefix_list_id=None,
|
destination_prefix_list_id: Optional[str] = None,
|
||||||
):
|
) -> Route:
|
||||||
cidr = destination_cidr_block
|
cidr = destination_cidr_block
|
||||||
route_table = self.get_route_table(route_table_id)
|
route_table = self.get_route_table(route_table_id)
|
||||||
if destination_ipv6_cidr_block:
|
if destination_ipv6_cidr_block:
|
||||||
@ -464,7 +489,9 @@ class RouteBackend:
|
|||||||
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):
|
def __validate_destination_cidr_block(
|
||||||
|
self, destination_cidr_block: str, route_table: RouteTable
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Utility function to check the destination CIDR block
|
Utility function to check the destination CIDR block
|
||||||
Will validate the format and check for overlap with existing routes
|
Will validate the format and check for overlap with existing routes
|
||||||
|
@ -7,7 +7,7 @@ from datetime import datetime
|
|||||||
from cryptography.hazmat.primitives import serialization
|
from cryptography.hazmat.primitives import serialization
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
from typing import Any, Dict, List, TypeVar, Optional
|
from typing import Any, Dict, List, TypeVar, Tuple, Optional
|
||||||
|
|
||||||
from moto.iam import iam_backends
|
from moto.iam import iam_backends
|
||||||
from moto.moto_api._internal import mock_random as random
|
from moto.moto_api._internal import mock_random as random
|
||||||
@ -122,7 +122,7 @@ def random_subnet_ipv6_cidr_block_association_id():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def random_subnet_association_id():
|
def random_subnet_association_id() -> str:
|
||||||
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table-association"])
|
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table-association"])
|
||||||
|
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ def random_egress_only_internet_gateway_id() -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def random_route_table_id():
|
def random_route_table_id() -> str:
|
||||||
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table"])
|
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table"])
|
||||||
|
|
||||||
|
|
||||||
@ -281,7 +281,10 @@ def random_ipv6_cidr():
|
|||||||
|
|
||||||
|
|
||||||
def generate_route_id(
|
def generate_route_id(
|
||||||
route_table_id, cidr_block, ipv6_cidr_block=None, prefix_list=None
|
route_table_id: str,
|
||||||
|
cidr_block: Optional[str],
|
||||||
|
ipv6_cidr_block: Optional[str] = None,
|
||||||
|
prefix_list: Optional[str] = None,
|
||||||
):
|
):
|
||||||
if ipv6_cidr_block and not cidr_block:
|
if ipv6_cidr_block and not cidr_block:
|
||||||
cidr_block = ipv6_cidr_block
|
cidr_block = ipv6_cidr_block
|
||||||
@ -309,7 +312,7 @@ def utc_date_and_time() -> str:
|
|||||||
return f"{x.year}-{x.month:02d}-{x.day:02d}T{x.hour:02d}:{x.minute:02d}:{x.second:02d}.000Z"
|
return f"{x.year}-{x.month:02d}-{x.day:02d}T{x.hour:02d}:{x.minute:02d}:{x.second:02d}.000Z"
|
||||||
|
|
||||||
|
|
||||||
def split_route_id(route_id):
|
def split_route_id(route_id: str) -> Tuple[str, str]:
|
||||||
values = route_id.split("~")
|
values = route_id.split("~")
|
||||||
return values[0], values[1]
|
return values[0], values[1]
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ disable = W,C,R,E
|
|||||||
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
|
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
|
||||||
|
|
||||||
[mypy]
|
[mypy]
|
||||||
files= moto/a*,moto/b*,moto/c*,moto/d*,moto/ebs/,moto/ec2/models/a*,moto/ec2/models/c*,moto/ec2/models/d*,moto/ec2/models/e*,moto/ec2/models/f*,moto/ec2/models/h*,moto/ec2/models/i*,moto/ec2/models/k*,moto/ec2/models/l*,moto/ec2/models/m*,moto/ec2/models/n*,moto/moto_api
|
files= moto/a*,moto/b*,moto/c*,moto/d*,moto/ebs/,moto/ec2/models/a*,moto/ec2/models/c*,moto/ec2/models/d*,moto/ec2/models/e*,moto/ec2/models/f*,moto/ec2/models/h*,moto/ec2/models/i*,moto/ec2/models/k*,moto/ec2/models/l*,moto/ec2/models/m*,moto/ec2/models/n*,moto/ec2/models/r*,moto/moto_api
|
||||||
show_column_numbers=True
|
show_column_numbers=True
|
||||||
show_error_codes = True
|
show_error_codes = True
|
||||||
disable_error_code=abstract
|
disable_error_code=abstract
|
||||||
|
Loading…
Reference in New Issue
Block a user