Techdebt: MyPy EC2 (n-models) (#5907)

This commit is contained in:
Bert Blommers 2023-02-06 20:57:02 -01:00 committed by GitHub
parent bd96e42915
commit 8cc9518662
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 123 additions and 98 deletions

View File

@ -126,7 +126,7 @@ class FlowLogAlreadyExists(EC2ClientError):
class InvalidNetworkAclIdError(EC2ClientError): class InvalidNetworkAclIdError(EC2ClientError):
def __init__(self, network_acl_id): def __init__(self, network_acl_id: str):
super().__init__( super().__init__(
"InvalidNetworkAclID.NotFound", "InvalidNetworkAclID.NotFound",
f"The network acl ID '{network_acl_id}' does not exist", f"The network acl ID '{network_acl_id}' does not exist",
@ -212,7 +212,7 @@ class InvalidPermissionDuplicateError(EC2ClientError):
class InvalidRouteTableIdError(EC2ClientError): class InvalidRouteTableIdError(EC2ClientError):
def __init__(self, route_table_id): def __init__(self, route_table_id: str):
super().__init__( super().__init__(
"InvalidRouteTableID.NotFound", "InvalidRouteTableID.NotFound",
f"The routeTable ID '{route_table_id}' does not exist", f"The routeTable ID '{route_table_id}' does not exist",
@ -572,7 +572,7 @@ class AvailabilityZoneNotFromRegionError(EC2ClientError):
class NetworkAclEntryAlreadyExistsError(EC2ClientError): class NetworkAclEntryAlreadyExistsError(EC2ClientError):
def __init__(self, rule_number): def __init__(self, rule_number: str):
super().__init__( super().__init__(
"NetworkAclEntryAlreadyExists", "NetworkAclEntryAlreadyExists",
f"The network acl entry identified by {rule_number} already exists.", f"The network acl entry identified by {rule_number} already exists.",

View File

@ -205,7 +205,7 @@ class EC2Backend(
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["launch-template"]: elif resource_prefix == EC2_RESOURCE_TO_PREFIX["launch-template"]:
self.get_launch_template(resource_id) self.get_launch_template(resource_id)
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["network-acl"]: elif resource_prefix == EC2_RESOURCE_TO_PREFIX["network-acl"]:
self.get_all_network_acls() self.describe_network_acls()
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["network-interface"]: elif resource_prefix == EC2_RESOURCE_TO_PREFIX["network-interface"]:
self.describe_network_interfaces( self.describe_network_interfaces(
filters={"network-interface-id": resource_id} filters={"network-interface-id": resource_id}

View File

@ -1,4 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Any, Dict, List, Optional
from moto.core import CloudFormationModel from moto.core import CloudFormationModel
from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.core.utils import iso_8601_datetime_with_milliseconds
@ -9,17 +10,16 @@ from ..utils import random_nat_gateway_id, random_private_ip
class NatGateway(CloudFormationModel, TaggedEC2Resource): class NatGateway(CloudFormationModel, TaggedEC2Resource):
def __init__( def __init__(
self, self,
backend, backend: Any,
subnet_id, subnet_id: str,
allocation_id, allocation_id: str,
tags=None, tags: Optional[Dict[str, str]] = None,
connectivity_type="public", connectivity_type: str = "public",
address_set=None,
): ):
# public properties # public properties
self.id = random_nat_gateway_id() self.id = random_nat_gateway_id()
self.subnet_id = subnet_id self.subnet_id = subnet_id
self.address_set = address_set or [] self.address_set: List[Dict[str, Any]] = []
self.state = "available" self.state = "available"
self.private_ip = random_private_ip() self.private_ip = random_private_ip()
self.connectivity_type = connectivity_type self.connectivity_type = connectivity_type
@ -41,36 +41,31 @@ class NatGateway(CloudFormationModel, TaggedEC2Resource):
self.vpc_id = self.ec2_backend.get_subnet(subnet_id).vpc_id self.vpc_id = self.ec2_backend.get_subnet(subnet_id).vpc_id
@property @property
def physical_resource_id(self): def physical_resource_id(self) -> str:
return self.id return self.id
@property @property
def create_time(self): def create_time(self) -> str:
return iso_8601_datetime_with_milliseconds(self._created_at) return iso_8601_datetime_with_milliseconds(self._created_at)
@property @staticmethod
def network_interface_id(self): def cloudformation_name_type() -> str:
return self._eni.id return ""
@property
def public_ip(self):
if self.allocation_id:
eips = self._backend.address_by_allocation([self.allocation_id])
return eips[0].public_ip if self.allocation_id else None
@staticmethod @staticmethod
def cloudformation_name_type(): def cloudformation_type() -> str:
return None
@staticmethod
def cloudformation_type():
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-natgateway.html
return "AWS::EC2::NatGateway" return "AWS::EC2::NatGateway"
@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
) -> "NatGateway":
from ..models import ec2_backends from ..models import ec2_backends
ec2_backend = ec2_backends[account_id][region_name] ec2_backend = ec2_backends[account_id][region_name]
@ -82,10 +77,12 @@ class NatGateway(CloudFormationModel, TaggedEC2Resource):
class NatGatewayBackend: class NatGatewayBackend:
def __init__(self): def __init__(self) -> None:
self.nat_gateways = {} self.nat_gateways: Dict[str, NatGateway] = {}
def describe_nat_gateways(self, filters, nat_gateway_ids): def describe_nat_gateways(
self, filters: Any, nat_gateway_ids: Optional[List[str]]
) -> List[NatGateway]:
nat_gateways = list(self.nat_gateways.values()) nat_gateways = list(self.nat_gateways.values())
if nat_gateway_ids: if nat_gateway_ids:
@ -120,14 +117,18 @@ class NatGatewayBackend:
return nat_gateways return nat_gateways
def create_nat_gateway( def create_nat_gateway(
self, subnet_id, allocation_id, tags=None, connectivity_type="public" self,
): subnet_id: str,
allocation_id: str,
tags: Optional[Dict[str, str]] = None,
connectivity_type: str = "public",
) -> NatGateway:
nat_gateway = NatGateway( nat_gateway = NatGateway(
self, subnet_id, allocation_id, tags, connectivity_type self, subnet_id, allocation_id, tags, connectivity_type
) )
address_set = {} address_set: Dict[str, Any] = {}
if allocation_id: if allocation_id:
eips = self.address_by_allocation([allocation_id]) eips = self.address_by_allocation([allocation_id]) # type: ignore[attr-defined]
eip = eips[0] if len(eips) > 0 else None eip = eips[0] if len(eips) > 0 else None
if eip: if eip:
address_set["allocationId"] = allocation_id address_set["allocationId"] = allocation_id
@ -138,7 +139,7 @@ class NatGatewayBackend:
self.nat_gateways[nat_gateway.id] = nat_gateway self.nat_gateways[nat_gateway.id] = nat_gateway
return nat_gateway return nat_gateway
def delete_nat_gateway(self, nat_gateway_id): def delete_nat_gateway(self, nat_gateway_id: str) -> NatGateway:
nat_gw = self.nat_gateways.get(nat_gateway_id) nat_gw: NatGateway = self.nat_gateways.get(nat_gateway_id) # type: ignore
nat_gw.state = "deleted" nat_gw.state = "deleted"
return nat_gw return nat_gw

View File

@ -1,3 +1,5 @@
from typing import Any, Dict, List, Optional
from ..exceptions import ( from ..exceptions import (
InvalidNetworkAclIdError, InvalidNetworkAclIdError,
InvalidRouteTableIdError, InvalidRouteTableIdError,
@ -12,27 +14,32 @@ from ..utils import (
class NetworkAclBackend: class NetworkAclBackend:
def __init__(self): def __init__(self) -> None:
self.network_acls = {} self.network_acls: Dict[str, "NetworkAcl"] = {}
def get_network_acl(self, network_acl_id): def get_network_acl(self, network_acl_id: str) -> "NetworkAcl":
network_acl = self.network_acls.get(network_acl_id, None) network_acl = self.network_acls.get(network_acl_id, None)
if not network_acl: if not network_acl:
raise InvalidNetworkAclIdError(network_acl_id) raise InvalidNetworkAclIdError(network_acl_id)
return network_acl return network_acl
def create_network_acl(self, vpc_id, tags=None, default=False): def create_network_acl(
self,
vpc_id: str,
tags: Optional[List[Dict[str, str]]] = None,
default: bool = False,
) -> "NetworkAcl":
network_acl_id = random_network_acl_id() network_acl_id = random_network_acl_id()
self.get_vpc(vpc_id) self.get_vpc(vpc_id) # type: ignore[attr-defined]
network_acl = NetworkAcl(self, network_acl_id, vpc_id, default) network_acl = NetworkAcl(self, network_acl_id, vpc_id, default)
for tag in tags or []: for tag in tags or []:
network_acl.add_tag(tag.get("Key"), tag.get("Value")) network_acl.add_tag(tag["Key"], tag["Value"])
self.network_acls[network_acl_id] = network_acl self.network_acls[network_acl_id] = network_acl
if default: if default:
self.add_default_entries(network_acl_id) self.add_default_entries(network_acl_id)
return network_acl return network_acl
def add_default_entries(self, network_acl_id): def add_default_entries(self, network_acl_id: str) -> None:
default_acl_entries = [ default_acl_entries = [
{"rule_number": "100", "rule_action": "allow", "egress": "true"}, {"rule_number": "100", "rule_action": "allow", "egress": "true"},
{"rule_number": "32767", "rule_action": "deny", "egress": "true"}, {"rule_number": "32767", "rule_action": "deny", "egress": "true"},
@ -53,10 +60,7 @@ class NetworkAclBackend:
port_range_to=None, port_range_to=None,
) )
def get_all_network_acls(self, network_acl_ids=None, filters=None): def delete_network_acl(self, network_acl_id: str) -> "NetworkAcl":
self.describe_network_acls(network_acl_ids, filters)
def delete_network_acl(self, network_acl_id):
deleted = self.network_acls.pop(network_acl_id, None) deleted = self.network_acls.pop(network_acl_id, None)
if not deleted: if not deleted:
raise InvalidNetworkAclIdError(network_acl_id) raise InvalidNetworkAclIdError(network_acl_id)
@ -64,17 +68,17 @@ class NetworkAclBackend:
def create_network_acl_entry( def create_network_acl_entry(
self, self,
network_acl_id, network_acl_id: str,
rule_number, rule_number: str,
protocol, protocol: str,
rule_action, rule_action: str,
egress, egress: str,
cidr_block, cidr_block: str,
icmp_code, icmp_code: Optional[int],
icmp_type, icmp_type: Optional[int],
port_range_from, port_range_from: Optional[int],
port_range_to, port_range_to: Optional[int],
): ) -> "NetworkAclEntry":
network_acl = self.get_network_acl(network_acl_id) network_acl = self.get_network_acl(network_acl_id)
if any( if any(
@ -99,7 +103,9 @@ class NetworkAclBackend:
network_acl.network_acl_entries.append(network_acl_entry) network_acl.network_acl_entries.append(network_acl_entry)
return network_acl_entry return network_acl_entry
def delete_network_acl_entry(self, network_acl_id, rule_number, egress): def delete_network_acl_entry(
self, network_acl_id: str, rule_number: str, egress: str
) -> "NetworkAclEntry":
network_acl = self.get_network_acl(network_acl_id) network_acl = self.get_network_acl(network_acl_id)
entry = next( entry = next(
entry entry
@ -112,17 +118,17 @@ class NetworkAclBackend:
def replace_network_acl_entry( def replace_network_acl_entry(
self, self,
network_acl_id, network_acl_id: str,
rule_number, rule_number: str,
protocol, protocol: str,
rule_action, rule_action: str,
egress, egress: str,
cidr_block, cidr_block: str,
icmp_code, icmp_code: int,
icmp_type, icmp_type: int,
port_range_from, port_range_from: int,
port_range_to, port_range_to: int,
): ) -> "NetworkAclEntry":
self.delete_network_acl_entry(network_acl_id, rule_number, egress) self.delete_network_acl_entry(network_acl_id, rule_number, egress)
network_acl_entry = self.create_network_acl_entry( network_acl_entry = self.create_network_acl_entry(
@ -139,7 +145,9 @@ class NetworkAclBackend:
) )
return network_acl_entry return network_acl_entry
def replace_network_acl_association(self, association_id, network_acl_id): def replace_network_acl_association(
self, association_id: str, network_acl_id: str
) -> "NetworkAclAssociation":
# lookup existing association for subnet and delete it # lookup existing association for subnet and delete it
default_acl = next( default_acl = next(
@ -163,7 +171,9 @@ class NetworkAclBackend:
new_acl.associations[new_assoc_id] = association new_acl.associations[new_assoc_id] = association
return association return association
def associate_default_network_acl_with_subnet(self, subnet_id, vpc_id): def associate_default_network_acl_with_subnet(
self, subnet_id: str, vpc_id: str
) -> None:
association_id = random_network_acl_subnet_association_id() association_id = random_network_acl_subnet_association_id()
acl = next( acl = next(
acl acl
@ -174,8 +184,10 @@ class NetworkAclBackend:
self, association_id, subnet_id, acl.id self, association_id, subnet_id, acl.id
) )
def describe_network_acls(self, network_acl_ids=None, filters=None): def describe_network_acls(
network_acls = self.network_acls.copy().values() self, network_acl_ids: Optional[List[str]] = None, filters: Any = None
) -> List["NetworkAcl"]:
network_acls = list(self.network_acls.values())
if network_acl_ids: if network_acl_ids:
network_acls = [ network_acls = [
@ -194,29 +206,41 @@ class NetworkAclBackend:
return generic_filter(filters, network_acls) return generic_filter(filters, network_acls)
class NetworkAclAssociation(object): class NetworkAclAssociation:
def __init__(self, ec2_backend, new_association_id, subnet_id, network_acl_id): def __init__(
self,
ec2_backend: Any,
new_association_id: str,
subnet_id: Optional[str],
network_acl_id: str,
):
self.ec2_backend = ec2_backend self.ec2_backend = ec2_backend
self.id = new_association_id self.id = new_association_id
self.new_association_id = new_association_id self.new_association_id = new_association_id
self.subnet_id = subnet_id self.subnet_id = subnet_id
self.network_acl_id = network_acl_id self.network_acl_id = network_acl_id
super().__init__()
class NetworkAcl(TaggedEC2Resource): class NetworkAcl(TaggedEC2Resource):
def __init__( def __init__(
self, ec2_backend, network_acl_id, vpc_id, default=False, owner_id=None self,
ec2_backend: Any,
network_acl_id: str,
vpc_id: str,
default: bool = False,
owner_id: Optional[str] = None,
): ):
self.ec2_backend = ec2_backend self.ec2_backend = ec2_backend
self.id = network_acl_id self.id = network_acl_id
self.vpc_id = vpc_id self.vpc_id = vpc_id
self.owner_id = owner_id or ec2_backend.account_id self.owner_id = owner_id or ec2_backend.account_id
self.network_acl_entries = [] self.network_acl_entries: List[NetworkAclEntry] = []
self.associations = {} self.associations: Dict[str, NetworkAclAssociation] = {}
self.default = "true" if default is True else "false" self.default = "true" if default is True else "false"
def get_filter_value(self, filter_name): def get_filter_value(
self, filter_name: str, method_name: Optional[str] = None
) -> Any:
if filter_name == "default": if filter_name == "default":
return self.default return self.default
elif filter_name == "vpc-id": elif filter_name == "vpc-id":
@ -244,17 +268,17 @@ class NetworkAcl(TaggedEC2Resource):
class NetworkAclEntry(TaggedEC2Resource): class NetworkAclEntry(TaggedEC2Resource):
def __init__( def __init__(
self, self,
ec2_backend, ec2_backend: Any,
network_acl_id, network_acl_id: str,
rule_number, rule_number: str,
protocol, protocol: str,
rule_action, rule_action: str,
egress, egress: str,
cidr_block, cidr_block: str,
icmp_code, icmp_code: Optional[int],
icmp_type, icmp_type: Optional[int],
port_range_from, port_range_from: Optional[int],
port_range_to, port_range_to: Optional[int],
): ):
self.ec2_backend = ec2_backend self.ec2_backend = ec2_backend
self.network_acl_id = network_acl_id self.network_acl_id = network_acl_id

View File

@ -126,11 +126,11 @@ def random_subnet_association_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table-association"]) return random_id(prefix=EC2_RESOURCE_TO_PREFIX["route-table-association"])
def random_network_acl_id(): def random_network_acl_id() -> str:
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["network-acl"]) return random_id(prefix=EC2_RESOURCE_TO_PREFIX["network-acl"])
def random_network_acl_subnet_association_id(): def random_network_acl_subnet_association_id() -> str:
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["network-acl-subnet-assoc"]) return random_id(prefix=EC2_RESOURCE_TO_PREFIX["network-acl-subnet-assoc"])

View File

@ -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/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/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