Techdebt: MyPy EFS (#5954)
This commit is contained in:
parent
d001f6a226
commit
23d9430590
@ -197,6 +197,8 @@ class Subnet(TaggedEC2Resource, CloudFormationModel):
|
|||||||
|
|
||||||
return new_ip
|
return new_ip
|
||||||
|
|
||||||
|
# EFS calls this method as request_ip(str, MountTarget)
|
||||||
|
# So technically it's not just Instances that are stored
|
||||||
def request_ip(self, ip: str, instance: "Instance") -> None:
|
def request_ip(self, ip: str, instance: "Instance") -> None:
|
||||||
if ipaddress.ip_address(ip) not in self.cidr:
|
if ipaddress.ip_address(ip) not in self.cidr:
|
||||||
raise Exception(f"IP does not fall in the subnet CIDR of {self.cidr}")
|
raise Exception(f"IP does not fall in the subnet CIDR of {self.cidr}")
|
||||||
|
@ -8,7 +8,7 @@ class EFSError(JsonRESTError):
|
|||||||
class AccessPointNotFound(EFSError):
|
class AccessPointNotFound(EFSError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, access_point_id):
|
def __init__(self, access_point_id: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"AccessPointNotFound", f"Access Point {access_point_id} does not exist."
|
"AccessPointNotFound", f"Access Point {access_point_id} does not exist."
|
||||||
)
|
)
|
||||||
@ -17,93 +17,83 @@ class AccessPointNotFound(EFSError):
|
|||||||
class FileSystemAlreadyExists(EFSError):
|
class FileSystemAlreadyExists(EFSError):
|
||||||
code = 409
|
code = 409
|
||||||
|
|
||||||
def __init__(self, creation_token, *args, **kwargs):
|
def __init__(self, creation_token: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"FileSystemAlreadyExists",
|
"FileSystemAlreadyExists",
|
||||||
f"File system with {creation_token} already exists.",
|
f"File system with {creation_token} already exists.",
|
||||||
*args,
|
|
||||||
**kwargs,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class FileSystemNotFound(EFSError):
|
class FileSystemNotFound(EFSError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, file_system_id, *args, **kwargs):
|
def __init__(self, file_system_id: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"FileSystemNotFound",
|
"FileSystemNotFound",
|
||||||
f"File system {file_system_id} does not exist.",
|
f"File system {file_system_id} does not exist.",
|
||||||
*args,
|
|
||||||
**kwargs,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class FileSystemInUse(EFSError):
|
class FileSystemInUse(EFSError):
|
||||||
code = 409
|
code = 409
|
||||||
|
|
||||||
def __init__(self, msg, *args, **kwargs):
|
def __init__(self, msg: str):
|
||||||
super().__init__("FileSystemInUse", msg, *args, **kwargs)
|
super().__init__("FileSystemInUse", msg)
|
||||||
|
|
||||||
|
|
||||||
class MountTargetConflict(EFSError):
|
class MountTargetConflict(EFSError):
|
||||||
code = 409
|
code = 409
|
||||||
|
|
||||||
def __init__(self, msg, *args, **kwargs):
|
def __init__(self, msg: str):
|
||||||
super().__init__("MountTargetConflict", msg, *args, **kwargs)
|
super().__init__("MountTargetConflict", msg)
|
||||||
|
|
||||||
|
|
||||||
class MountTargetNotFound(EFSError):
|
class MountTargetNotFound(EFSError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, mount_target_id, *args, **kwargs):
|
def __init__(self, mount_target_id: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"MountTargetNotFound",
|
"MountTargetNotFound",
|
||||||
f"Mount target '{mount_target_id}' does not exist.",
|
f"Mount target '{mount_target_id}' does not exist.",
|
||||||
*args,
|
|
||||||
**kwargs,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class BadRequest(EFSError):
|
class BadRequest(EFSError):
|
||||||
code = 400
|
code = 400
|
||||||
|
|
||||||
def __init__(self, msg, *args, **kwargs):
|
def __init__(self, msg: str):
|
||||||
super().__init__("BadRequest", msg, *args, **kwargs)
|
super().__init__("BadRequest", msg)
|
||||||
|
|
||||||
|
|
||||||
class PolicyNotFound(EFSError):
|
class PolicyNotFound(EFSError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, msg: str):
|
||||||
super().__init__("PolicyNotFound", *args, **kwargs)
|
super().__init__("PolicyNotFound", msg)
|
||||||
|
|
||||||
|
|
||||||
class SubnetNotFound(EFSError):
|
class SubnetNotFound(EFSError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, subnet_id, *args, **kwargs):
|
def __init__(self, subnet_id: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"SubnetNotFound",
|
"SubnetNotFound",
|
||||||
f"The subnet ID '{subnet_id}' does not exist",
|
f"The subnet ID '{subnet_id}' does not exist",
|
||||||
*args,
|
|
||||||
**kwargs,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupNotFound(EFSError):
|
class SecurityGroupNotFound(EFSError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
def __init__(self, security_group_id, *args, **kwargs):
|
def __init__(self, security_group_id: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"SecurityGroupNotFound",
|
"SecurityGroupNotFound",
|
||||||
f"The SecurityGroup ID '{security_group_id}' does not exist",
|
f"The SecurityGroup ID '{security_group_id}' does not exist",
|
||||||
*args,
|
|
||||||
**kwargs,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SecurityGroupLimitExceeded(EFSError):
|
class SecurityGroupLimitExceeded(EFSError):
|
||||||
code = 400
|
code = 400
|
||||||
|
|
||||||
def __init__(self, msg, *args, **kwargs):
|
def __init__(self, msg: str):
|
||||||
super().__init__("SecurityGroupLimitExceeded", msg, *args, **kwargs)
|
super().__init__("SecurityGroupLimitExceeded", msg)
|
||||||
|
@ -7,10 +7,13 @@ https://docs.aws.amazon.com/efs/latest/ug/whatisefs.html
|
|||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from typing import Any, Dict, List, Optional, Tuple, Set, Iterator, Union
|
||||||
|
|
||||||
from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel
|
from moto.core import BaseBackend, BackendDict, BaseModel, CloudFormationModel
|
||||||
from moto.core.utils import camelcase_to_underscores, underscores_to_camelcase
|
from moto.core.utils import camelcase_to_underscores, underscores_to_camelcase
|
||||||
from moto.ec2 import ec2_backends
|
from moto.ec2 import ec2_backends
|
||||||
|
from moto.ec2.models.elastic_network_interfaces import NetworkInterface
|
||||||
|
from moto.ec2.models.subnets import Subnet
|
||||||
from moto.ec2.exceptions import InvalidSubnetIdError
|
from moto.ec2.exceptions import InvalidSubnetIdError
|
||||||
from moto.efs.exceptions import (
|
from moto.efs.exceptions import (
|
||||||
AccessPointNotFound,
|
AccessPointNotFound,
|
||||||
@ -30,25 +33,26 @@ from moto.utilities.tagging_service import TaggingService
|
|||||||
from moto.utilities.utils import md5_hash
|
from moto.utilities.utils import md5_hash
|
||||||
|
|
||||||
|
|
||||||
def _lookup_az_id(account_id, az_name):
|
def _lookup_az_id(account_id: str, az_name: str) -> Optional[str]:
|
||||||
"""Find the Availability zone ID given the AZ name."""
|
"""Find the Availability zone ID given the AZ name."""
|
||||||
ec2 = ec2_backends[account_id][az_name[:-1]]
|
ec2 = ec2_backends[account_id][az_name[:-1]]
|
||||||
for zone in ec2.describe_availability_zones():
|
for zone in ec2.describe_availability_zones():
|
||||||
if zone.name == az_name:
|
if zone.name == az_name:
|
||||||
return zone.zone_id
|
return zone.zone_id
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class AccessPoint(BaseModel):
|
class AccessPoint(BaseModel):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
account_id,
|
account_id: str,
|
||||||
region_name,
|
region_name: str,
|
||||||
client_token,
|
client_token: str,
|
||||||
file_system_id,
|
file_system_id: str,
|
||||||
name,
|
name: Optional[str],
|
||||||
posix_user,
|
posix_user: Dict[str, Any],
|
||||||
root_directory,
|
root_directory: Dict[str, str],
|
||||||
context,
|
context: "EFSBackend",
|
||||||
):
|
):
|
||||||
self.access_point_id = mock_random.get_random_hex(8)
|
self.access_point_id = mock_random.get_random_hex(8)
|
||||||
self.access_point_arn = f"arn:aws:elasticfilesystem:{region_name}:{account_id}:access-point/fsap-{self.access_point_id}"
|
self.access_point_arn = f"arn:aws:elasticfilesystem:{region_name}:{account_id}:access-point/fsap-{self.access_point_id}"
|
||||||
@ -64,7 +68,7 @@ class AccessPoint(BaseModel):
|
|||||||
self.root_directory = root_directory
|
self.root_directory = root_directory
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
def info_json(self):
|
def info_json(self) -> Dict[str, Any]:
|
||||||
tags = self.context.list_tags_for_resource(self.access_point_id)
|
tags = self.context.list_tags_for_resource(self.access_point_id)
|
||||||
return {
|
return {
|
||||||
"ClientToken": self.client_token,
|
"ClientToken": self.client_token,
|
||||||
@ -85,20 +89,18 @@ class FileSystem(CloudFormationModel):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
account_id,
|
account_id: str,
|
||||||
region_name,
|
region_name: str,
|
||||||
creation_token,
|
creation_token: str,
|
||||||
file_system_id,
|
file_system_id: str,
|
||||||
context,
|
context: "EFSBackend",
|
||||||
performance_mode,
|
performance_mode: str,
|
||||||
encrypted,
|
encrypted: bool,
|
||||||
kms_key_id,
|
kms_key_id: str,
|
||||||
throughput_mode,
|
throughput_mode: str,
|
||||||
provisioned_throughput_in_mibps,
|
provisioned_throughput_in_mibps: int,
|
||||||
availability_zone_name,
|
availability_zone_name: str,
|
||||||
backup,
|
backup: bool,
|
||||||
lifecycle_policies=None,
|
|
||||||
file_system_policy=None,
|
|
||||||
):
|
):
|
||||||
if availability_zone_name:
|
if availability_zone_name:
|
||||||
backup = True
|
backup = True
|
||||||
@ -119,8 +121,8 @@ class FileSystem(CloudFormationModel):
|
|||||||
account_id, self.availability_zone_name
|
account_id, self.availability_zone_name
|
||||||
)
|
)
|
||||||
self._backup = backup
|
self._backup = backup
|
||||||
self.lifecycle_policies = lifecycle_policies or []
|
self.lifecycle_policies: List[Dict[str, str]] = []
|
||||||
self.file_system_policy = file_system_policy
|
self.file_system_policy: Optional[str] = None
|
||||||
|
|
||||||
self._context = context
|
self._context = context
|
||||||
|
|
||||||
@ -132,11 +134,11 @@ class FileSystem(CloudFormationModel):
|
|||||||
|
|
||||||
# Initialize some state parameters
|
# Initialize some state parameters
|
||||||
self.life_cycle_state = "available"
|
self.life_cycle_state = "available"
|
||||||
self._mount_targets = {}
|
self._mount_targets: Dict[str, MountTarget] = {}
|
||||||
self._size_value = 0
|
self._size_value = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size_in_bytes(self):
|
def size_in_bytes(self) -> Dict[str, Any]: # type: ignore[misc]
|
||||||
return {
|
return {
|
||||||
"Value": self._size_value,
|
"Value": self._size_value,
|
||||||
"ValueInIA": 0,
|
"ValueInIA": 0,
|
||||||
@ -145,21 +147,21 @@ class FileSystem(CloudFormationModel):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def physical_resource_id(self):
|
def physical_resource_id(self) -> str:
|
||||||
return self.file_system_id
|
return self.file_system_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def number_of_mount_targets(self):
|
def number_of_mount_targets(self) -> int:
|
||||||
return len(self._mount_targets)
|
return len(self._mount_targets)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def backup_policy(self):
|
def backup_policy(self) -> Optional[Dict[str, str]]:
|
||||||
if self._backup:
|
if self._backup:
|
||||||
return {"Status": "ENABLED"}
|
return {"Status": "ENABLED"}
|
||||||
else:
|
else:
|
||||||
return
|
return None
|
||||||
|
|
||||||
def info_json(self):
|
def info_json(self) -> Dict[str, Any]:
|
||||||
ret = {
|
ret = {
|
||||||
underscores_to_camelcase(k.capitalize()): v
|
underscores_to_camelcase(k.capitalize()): v
|
||||||
for k, v in self.__dict__.items()
|
for k, v in self.__dict__.items()
|
||||||
@ -180,7 +182,7 @@ class FileSystem(CloudFormationModel):
|
|||||||
)
|
)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def add_mount_target(self, subnet, mount_target):
|
def add_mount_target(self, subnet: Subnet, mount_target: "MountTarget") -> None:
|
||||||
# Check that the mount target doesn't violate constraints.
|
# Check that the mount target doesn't violate constraints.
|
||||||
for other_mount_target in self._mount_targets.values():
|
for other_mount_target in self._mount_targets.values():
|
||||||
if other_mount_target.subnet_vpc_id != subnet.vpc_id:
|
if other_mount_target.subnet_vpc_id != subnet.vpc_id:
|
||||||
@ -193,28 +195,33 @@ class FileSystem(CloudFormationModel):
|
|||||||
|
|
||||||
self._mount_targets[subnet.availability_zone] = mount_target
|
self._mount_targets[subnet.availability_zone] = mount_target
|
||||||
|
|
||||||
def has_mount_target(self, subnet):
|
def has_mount_target(self, subnet: Subnet) -> bool:
|
||||||
return subnet.availability_zone in self._mount_targets
|
return subnet.availability_zone in self._mount_targets
|
||||||
|
|
||||||
def iter_mount_targets(self):
|
def iter_mount_targets(self) -> Iterator["MountTarget"]:
|
||||||
for mt in self._mount_targets.values():
|
for mt in self._mount_targets.values():
|
||||||
yield mt
|
yield mt
|
||||||
|
|
||||||
def remove_mount_target(self, subnet):
|
def remove_mount_target(self, subnet: Subnet) -> None:
|
||||||
del self._mount_targets[subnet.availability_zone]
|
del self._mount_targets[subnet.availability_zone]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_name_type():
|
def cloudformation_name_type() -> str:
|
||||||
return
|
return ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_type():
|
def cloudformation_type() -> str:
|
||||||
return "AWS::EFS::FileSystem"
|
return "AWS::EFS::FileSystem"
|
||||||
|
|
||||||
@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,
|
||||||
|
) -> "FileSystem":
|
||||||
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html
|
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html
|
||||||
props = deepcopy(cloudformation_json["Properties"])
|
props = deepcopy(cloudformation_json["Properties"])
|
||||||
props = {camelcase_to_underscores(k): v for k, v in props.items()}
|
props = {camelcase_to_underscores(k): v for k, v in props.items()}
|
||||||
@ -238,29 +245,40 @@ class FileSystem(CloudFormationModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_from_cloudformation_json(
|
def update_from_cloudformation_json( # type: ignore[misc]
|
||||||
cls,
|
cls,
|
||||||
original_resource,
|
original_resource: Any,
|
||||||
new_resource_name,
|
new_resource_name: str,
|
||||||
cloudformation_json,
|
cloudformation_json: Any,
|
||||||
account_id,
|
account_id: str,
|
||||||
region_name,
|
region_name: str,
|
||||||
):
|
) -> None:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Update of EFS File System via cloudformation is not yet implemented."
|
"Update of EFS File System via cloudformation is not yet implemented."
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_from_cloudformation_json(
|
def delete_from_cloudformation_json( # type: ignore[misc]
|
||||||
cls, resource_name, cloudformation_json, account_id, region_name
|
cls,
|
||||||
):
|
resource_name: str,
|
||||||
return efs_backends[account_id][region_name].delete_file_system(resource_name)
|
cloudformation_json: Any,
|
||||||
|
account_id: str,
|
||||||
|
region_name: str,
|
||||||
|
) -> None:
|
||||||
|
efs_backends[account_id][region_name].delete_file_system(resource_name)
|
||||||
|
|
||||||
|
|
||||||
class MountTarget(CloudFormationModel):
|
class MountTarget(CloudFormationModel):
|
||||||
"""A model for an EFS Mount Target."""
|
"""A model for an EFS Mount Target."""
|
||||||
|
|
||||||
def __init__(self, account_id, file_system, subnet, ip_address, security_groups):
|
def __init__(
|
||||||
|
self,
|
||||||
|
account_id: str,
|
||||||
|
file_system: FileSystem,
|
||||||
|
subnet: Subnet,
|
||||||
|
ip_address: Optional[str],
|
||||||
|
security_groups: Optional[List[str]],
|
||||||
|
):
|
||||||
# Set the simple given parameters.
|
# Set the simple given parameters.
|
||||||
self.file_system_id = file_system.file_system_id
|
self.file_system_id = file_system.file_system_id
|
||||||
self._file_system = file_system
|
self._file_system = file_system
|
||||||
@ -278,10 +296,10 @@ class MountTarget(CloudFormationModel):
|
|||||||
|
|
||||||
# Get an IP address if needed, otherwise validate the one we're given.
|
# Get an IP address if needed, otherwise validate the one we're given.
|
||||||
if ip_address is None:
|
if ip_address is None:
|
||||||
ip_address = subnet.get_available_subnet_ip(self)
|
ip_address = subnet.get_available_subnet_ip(self) # type: ignore[arg-type]
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
subnet.request_ip(ip_address, self)
|
subnet.request_ip(ip_address, self) # type: ignore[arg-type]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "IP" in str(e) and "CIDR" in str(e):
|
if "IP" in str(e) and "CIDR" in str(e):
|
||||||
raise BadRequest(
|
raise BadRequest(
|
||||||
@ -295,68 +313,76 @@ class MountTarget(CloudFormationModel):
|
|||||||
self.owner_id = account_id
|
self.owner_id = account_id
|
||||||
self.mount_target_id = f"fsmt-{mock_random.get_random_hex()}"
|
self.mount_target_id = f"fsmt-{mock_random.get_random_hex()}"
|
||||||
self.life_cycle_state = "available"
|
self.life_cycle_state = "available"
|
||||||
self.network_interface_id = None
|
self.network_interface_id: Optional[str] = None
|
||||||
self.availability_zone_id = subnet.availability_zone_id
|
self.availability_zone_id = subnet.availability_zone_id
|
||||||
self.availability_zone_name = subnet.availability_zone
|
self.availability_zone_name = subnet.availability_zone
|
||||||
|
|
||||||
def clean_up(self):
|
def clean_up(self) -> None:
|
||||||
self._file_system.remove_mount_target(self._subnet)
|
self._file_system.remove_mount_target(self._subnet)
|
||||||
self._subnet.del_subnet_ip(self.ip_address)
|
self._subnet.del_subnet_ip(self.ip_address)
|
||||||
|
|
||||||
def set_network_interface(self, network_interface):
|
def set_network_interface(self, network_interface: NetworkInterface) -> None:
|
||||||
self.network_interface_id = network_interface.id
|
self.network_interface_id = network_interface.id
|
||||||
|
|
||||||
def info_json(self):
|
def info_json(self) -> Dict[str, Any]:
|
||||||
ret = {
|
return {
|
||||||
underscores_to_camelcase(k.capitalize()): v
|
underscores_to_camelcase(k.capitalize()): v
|
||||||
for k, v in self.__dict__.items()
|
for k, v in self.__dict__.items()
|
||||||
if not k.startswith("_")
|
if not k.startswith("_")
|
||||||
}
|
}
|
||||||
return ret
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def physical_resource_id(self):
|
def physical_resource_id(self) -> str:
|
||||||
return self.mounted_target_id
|
return self.mount_target_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def subnet_vpc_id(self):
|
def subnet_vpc_id(self) -> str:
|
||||||
return self._subnet.vpc_id
|
return self._subnet.vpc_id
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_name_type():
|
def cloudformation_name_type() -> str:
|
||||||
pass
|
return ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_type():
|
def cloudformation_type() -> str:
|
||||||
return "AWS::EFS::MountTarget"
|
return "AWS::EFS::MountTarget"
|
||||||
|
|
||||||
@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,
|
||||||
|
) -> "MountTarget":
|
||||||
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-mounttarget.html
|
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-mounttarget.html
|
||||||
props = deepcopy(cloudformation_json["Properties"])
|
props = deepcopy(cloudformation_json["Properties"])
|
||||||
props = {camelcase_to_underscores(k): v for k, v in props.items()}
|
props = {camelcase_to_underscores(k): v for k, v in props.items()}
|
||||||
return efs_backends[account_id][region_name].create_mount_target(**props)
|
return efs_backends[account_id][region_name].create_mount_target(**props)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_from_cloudformation_json(
|
def update_from_cloudformation_json( # type: ignore[misc]
|
||||||
cls,
|
cls,
|
||||||
original_resource,
|
original_resource: Any,
|
||||||
new_resource_name,
|
new_resource_name: str,
|
||||||
cloudformation_json,
|
cloudformation_json: Any,
|
||||||
account_id,
|
account_id: str,
|
||||||
region_name,
|
region_name: str,
|
||||||
):
|
) -> None:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Updates of EFS Mount Target via cloudformation are not yet implemented."
|
"Updates of EFS Mount Target via cloudformation are not yet implemented."
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_from_cloudformation_json(
|
def delete_from_cloudformation_json( # type: ignore[misc]
|
||||||
cls, resource_name, cloudformation_json, account_id, region_name
|
cls,
|
||||||
):
|
resource_name: str,
|
||||||
return efs_backends[account_id][region_name].delete_mount_target(resource_name)
|
cloudformation_json: Any,
|
||||||
|
account_id: str,
|
||||||
|
region_name: str,
|
||||||
|
) -> None:
|
||||||
|
efs_backends[account_id][region_name].delete_mount_target(resource_name)
|
||||||
|
|
||||||
|
|
||||||
class EFSBackend(BaseBackend):
|
class EFSBackend(BaseBackend):
|
||||||
@ -367,16 +393,18 @@ class EFSBackend(BaseBackend):
|
|||||||
such resources should always go through this class.
|
such resources should always go through this class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, region_name, account_id):
|
def __init__(self, region_name: str, account_id: str):
|
||||||
super().__init__(region_name, account_id)
|
super().__init__(region_name, account_id)
|
||||||
self.creation_tokens = set()
|
self.creation_tokens: Set[str] = set()
|
||||||
self.access_points = dict()
|
self.access_points: Dict[str, AccessPoint] = dict()
|
||||||
self.file_systems_by_id = {}
|
self.file_systems_by_id: Dict[str, FileSystem] = {}
|
||||||
self.mount_targets_by_id = {}
|
self.mount_targets_by_id: Dict[str, MountTarget] = {}
|
||||||
self.next_markers = {}
|
self.next_markers: Dict[str, Union[List[MountTarget], List[FileSystem]]] = {}
|
||||||
self.tagging_service = TaggingService()
|
self.tagging_service = TaggingService()
|
||||||
|
|
||||||
def _mark_description(self, corpus, max_items):
|
def _mark_description(
|
||||||
|
self, corpus: Union[List[MountTarget], List[FileSystem]], max_items: int
|
||||||
|
) -> Optional[str]:
|
||||||
if max_items < len(corpus):
|
if max_items < len(corpus):
|
||||||
new_corpus = corpus[max_items:]
|
new_corpus = corpus[max_items:]
|
||||||
new_corpus_dict = [c.info_json() for c in new_corpus]
|
new_corpus_dict = [c.info_json() for c in new_corpus]
|
||||||
@ -388,21 +416,21 @@ class EFSBackend(BaseBackend):
|
|||||||
return next_marker
|
return next_marker
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ec2_backend(self):
|
def ec2_backend(self) -> Any: # type: ignore[misc]
|
||||||
return ec2_backends[self.account_id][self.region_name]
|
return ec2_backends[self.account_id][self.region_name]
|
||||||
|
|
||||||
def create_file_system(
|
def create_file_system(
|
||||||
self,
|
self,
|
||||||
creation_token,
|
creation_token: str,
|
||||||
performance_mode,
|
performance_mode: str,
|
||||||
encrypted,
|
encrypted: bool,
|
||||||
kms_key_id,
|
kms_key_id: str,
|
||||||
throughput_mode,
|
throughput_mode: str,
|
||||||
provisioned_throughput_in_mibps,
|
provisioned_throughput_in_mibps: int,
|
||||||
availability_zone_name,
|
availability_zone_name: str,
|
||||||
backup,
|
backup: bool,
|
||||||
tags,
|
tags: List[Dict[str, str]],
|
||||||
):
|
) -> FileSystem:
|
||||||
"""Create a new EFS File System Volume.
|
"""Create a new EFS File System Volume.
|
||||||
|
|
||||||
https://docs.aws.amazon.com/efs/latest/ug/API_CreateFileSystem.html
|
https://docs.aws.amazon.com/efs/latest/ug/API_CreateFileSystem.html
|
||||||
@ -413,7 +441,7 @@ class EFSBackend(BaseBackend):
|
|||||||
raise FileSystemAlreadyExists(creation_token)
|
raise FileSystemAlreadyExists(creation_token)
|
||||||
|
|
||||||
# Create a new file system ID:
|
# Create a new file system ID:
|
||||||
def make_id():
|
def make_id() -> str:
|
||||||
return f"fs-{mock_random.get_random_hex()}"
|
return f"fs-{mock_random.get_random_hex()}"
|
||||||
|
|
||||||
fsid = make_id()
|
fsid = make_id()
|
||||||
@ -438,13 +466,17 @@ class EFSBackend(BaseBackend):
|
|||||||
return self.file_systems_by_id[fsid]
|
return self.file_systems_by_id[fsid]
|
||||||
|
|
||||||
def describe_file_systems(
|
def describe_file_systems(
|
||||||
self, marker=None, max_items=10, creation_token=None, file_system_id=None
|
self,
|
||||||
):
|
marker: Optional[str] = None,
|
||||||
|
max_items: int = 10,
|
||||||
|
creation_token: Optional[str] = None,
|
||||||
|
file_system_id: Optional[str] = None,
|
||||||
|
) -> Tuple[Optional[str], List[FileSystem]]:
|
||||||
"""Describe all the EFS File Systems, or specific File Systems.
|
"""Describe all the EFS File Systems, or specific File Systems.
|
||||||
|
|
||||||
https://docs.aws.amazon.com/efs/latest/ug/API_DescribeFileSystems.html
|
https://docs.aws.amazon.com/efs/latest/ug/API_DescribeFileSystems.html
|
||||||
"""
|
"""
|
||||||
# Restrict the possible corpus of resules based on inputs.
|
# Restrict the possible corpus of results based on inputs.
|
||||||
if creation_token and file_system_id:
|
if creation_token and file_system_id:
|
||||||
raise BadRequest(
|
raise BadRequest(
|
||||||
"Request cannot contain both a file system ID and a creation token."
|
"Request cannot contain both a file system ID and a creation token."
|
||||||
@ -464,7 +496,7 @@ class EFSBackend(BaseBackend):
|
|||||||
# Handle the case that a marker is given.
|
# Handle the case that a marker is given.
|
||||||
if marker not in self.next_markers:
|
if marker not in self.next_markers:
|
||||||
raise BadRequest("Invalid Marker")
|
raise BadRequest("Invalid Marker")
|
||||||
corpus = self.next_markers[marker]
|
corpus = self.next_markers[marker] # type: ignore[assignment]
|
||||||
else:
|
else:
|
||||||
# Handle the vanilla case.
|
# Handle the vanilla case.
|
||||||
corpus = [fs for fs in self.file_systems_by_id.values()]
|
corpus = [fs for fs in self.file_systems_by_id.values()]
|
||||||
@ -475,8 +507,12 @@ class EFSBackend(BaseBackend):
|
|||||||
return next_marker, file_systems
|
return next_marker, file_systems
|
||||||
|
|
||||||
def create_mount_target(
|
def create_mount_target(
|
||||||
self, file_system_id, subnet_id, ip_address=None, security_groups=None
|
self,
|
||||||
):
|
file_system_id: str,
|
||||||
|
subnet_id: str,
|
||||||
|
ip_address: Optional[str] = None,
|
||||||
|
security_groups: Optional[List[str]] = None,
|
||||||
|
) -> MountTarget:
|
||||||
"""Create a new EFS Mount Target for a given File System to a given subnet.
|
"""Create a new EFS Mount Target for a given File System to a given subnet.
|
||||||
|
|
||||||
Note that you can only create one mount target for each availability zone
|
Note that you can only create one mount target for each availability zone
|
||||||
@ -516,8 +552,13 @@ class EFSBackend(BaseBackend):
|
|||||||
return mount_target
|
return mount_target
|
||||||
|
|
||||||
def describe_mount_targets(
|
def describe_mount_targets(
|
||||||
self, max_items, file_system_id, mount_target_id, access_point_id, marker
|
self,
|
||||||
):
|
max_items: int,
|
||||||
|
file_system_id: Optional[str],
|
||||||
|
mount_target_id: Optional[str],
|
||||||
|
access_point_id: Optional[str],
|
||||||
|
marker: Optional[str],
|
||||||
|
) -> Tuple[Optional[str], List[MountTarget]]:
|
||||||
"""Describe the mount targets given an access point ID, mount target ID or a file system ID.
|
"""Describe the mount targets given an access point ID, mount target ID or a file system ID.
|
||||||
|
|
||||||
https://docs.aws.amazon.com/efs/latest/ug/API_DescribeMountTargets.html
|
https://docs.aws.amazon.com/efs/latest/ug/API_DescribeMountTargets.html
|
||||||
@ -549,7 +590,7 @@ class EFSBackend(BaseBackend):
|
|||||||
if marker not in self.next_markers:
|
if marker not in self.next_markers:
|
||||||
raise BadRequest("Invalid Marker")
|
raise BadRequest("Invalid Marker")
|
||||||
corpus_mtids = {m.mount_target_id for m in corpus}
|
corpus_mtids = {m.mount_target_id for m in corpus}
|
||||||
marked_mtids = {m.mount_target_id for m in self.next_markers[marker]}
|
marked_mtids = {m.mount_target_id for m in self.next_markers[marker]} # type: ignore[union-attr]
|
||||||
mt_ids = corpus_mtids & marked_mtids
|
mt_ids = corpus_mtids & marked_mtids
|
||||||
corpus = [self.mount_targets_by_id[mt_id] for mt_id in mt_ids]
|
corpus = [self.mount_targets_by_id[mt_id] for mt_id in mt_ids]
|
||||||
|
|
||||||
@ -558,7 +599,7 @@ class EFSBackend(BaseBackend):
|
|||||||
next_marker = self._mark_description(corpus, max_items)
|
next_marker = self._mark_description(corpus, max_items)
|
||||||
return next_marker, mount_targets
|
return next_marker, mount_targets
|
||||||
|
|
||||||
def delete_file_system(self, file_system_id):
|
def delete_file_system(self, file_system_id: str) -> None:
|
||||||
"""Delete the file system specified by the given file_system_id.
|
"""Delete the file system specified by the given file_system_id.
|
||||||
|
|
||||||
Note that mount targets must be deleted first.
|
Note that mount targets must be deleted first.
|
||||||
@ -576,9 +617,8 @@ class EFSBackend(BaseBackend):
|
|||||||
|
|
||||||
del self.file_systems_by_id[file_system_id]
|
del self.file_systems_by_id[file_system_id]
|
||||||
self.creation_tokens.remove(file_system.creation_token)
|
self.creation_tokens.remove(file_system.creation_token)
|
||||||
return
|
|
||||||
|
|
||||||
def delete_mount_target(self, mount_target_id):
|
def delete_mount_target(self, mount_target_id: str) -> None:
|
||||||
"""Delete a mount target specified by the given mount_target_id.
|
"""Delete a mount target specified by the given mount_target_id.
|
||||||
|
|
||||||
Note that this will also delete a network interface.
|
Note that this will also delete a network interface.
|
||||||
@ -592,32 +632,39 @@ class EFSBackend(BaseBackend):
|
|||||||
self.ec2_backend.delete_network_interface(mount_target.network_interface_id)
|
self.ec2_backend.delete_network_interface(mount_target.network_interface_id)
|
||||||
del self.mount_targets_by_id[mount_target_id]
|
del self.mount_targets_by_id[mount_target_id]
|
||||||
mount_target.clean_up()
|
mount_target.clean_up()
|
||||||
return
|
|
||||||
|
|
||||||
def describe_backup_policy(self, file_system_id):
|
def describe_backup_policy(self, file_system_id: str) -> Dict[str, str]:
|
||||||
backup_policy = self.file_systems_by_id[file_system_id].backup_policy
|
backup_policy = self.file_systems_by_id[file_system_id].backup_policy
|
||||||
if not backup_policy:
|
if not backup_policy:
|
||||||
raise PolicyNotFound("None")
|
raise PolicyNotFound("None")
|
||||||
return backup_policy
|
return backup_policy
|
||||||
|
|
||||||
def put_lifecycle_configuration(self, file_system_id, policies):
|
def put_lifecycle_configuration(
|
||||||
|
self, file_system_id: str, policies: List[Dict[str, str]]
|
||||||
|
) -> None:
|
||||||
_, fss = self.describe_file_systems(file_system_id=file_system_id)
|
_, fss = self.describe_file_systems(file_system_id=file_system_id)
|
||||||
file_system = fss[0]
|
file_system = fss[0]
|
||||||
file_system.lifecycle_policies = policies
|
file_system.lifecycle_policies = policies
|
||||||
|
|
||||||
def describe_lifecycle_configuration(self, file_system_id):
|
def describe_lifecycle_configuration(
|
||||||
|
self, file_system_id: str
|
||||||
|
) -> List[Dict[str, str]]:
|
||||||
_, fss = self.describe_file_systems(file_system_id=file_system_id)
|
_, fss = self.describe_file_systems(file_system_id=file_system_id)
|
||||||
file_system = fss[0]
|
file_system = fss[0]
|
||||||
return file_system.lifecycle_policies
|
return file_system.lifecycle_policies
|
||||||
|
|
||||||
def describe_mount_target_security_groups(self, mount_target_id):
|
def describe_mount_target_security_groups(
|
||||||
|
self, mount_target_id: str
|
||||||
|
) -> Optional[List[str]]:
|
||||||
if mount_target_id not in self.mount_targets_by_id:
|
if mount_target_id not in self.mount_targets_by_id:
|
||||||
raise MountTargetNotFound(mount_target_id)
|
raise MountTargetNotFound(mount_target_id)
|
||||||
|
|
||||||
mount_target = self.mount_targets_by_id[mount_target_id]
|
mount_target = self.mount_targets_by_id[mount_target_id]
|
||||||
return mount_target.security_groups
|
return mount_target.security_groups
|
||||||
|
|
||||||
def modify_mount_target_security_groups(self, mount_target_id, security_groups):
|
def modify_mount_target_security_groups(
|
||||||
|
self, mount_target_id: str, security_groups: List[str]
|
||||||
|
) -> None:
|
||||||
if mount_target_id not in self.mount_targets_by_id:
|
if mount_target_id not in self.mount_targets_by_id:
|
||||||
raise MountTargetNotFound(mount_target_id)
|
raise MountTargetNotFound(mount_target_id)
|
||||||
|
|
||||||
@ -629,8 +676,13 @@ class EFSBackend(BaseBackend):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def create_access_point(
|
def create_access_point(
|
||||||
self, client_token, tags, file_system_id, posix_user, root_directory
|
self,
|
||||||
):
|
client_token: str,
|
||||||
|
tags: List[Dict[str, str]],
|
||||||
|
file_system_id: str,
|
||||||
|
posix_user: Dict[str, Any],
|
||||||
|
root_directory: Dict[str, Any],
|
||||||
|
) -> AccessPoint:
|
||||||
name = next((tag["Value"] for tag in tags if tag["Key"] == "Name"), None)
|
name = next((tag["Value"] for tag in tags if tag["Key"] == "Name"), None)
|
||||||
access_point = AccessPoint(
|
access_point = AccessPoint(
|
||||||
self.account_id,
|
self.account_id,
|
||||||
@ -646,7 +698,7 @@ class EFSBackend(BaseBackend):
|
|||||||
self.access_points[access_point.access_point_id] = access_point
|
self.access_points[access_point.access_point_id] = access_point
|
||||||
return access_point
|
return access_point
|
||||||
|
|
||||||
def describe_access_points(self, access_point_id):
|
def describe_access_points(self, access_point_id: str) -> List[AccessPoint]:
|
||||||
"""
|
"""
|
||||||
Pagination is not yet implemented
|
Pagination is not yet implemented
|
||||||
"""
|
"""
|
||||||
@ -654,18 +706,18 @@ class EFSBackend(BaseBackend):
|
|||||||
if access_point_id not in self.access_points:
|
if access_point_id not in self.access_points:
|
||||||
raise AccessPointNotFound(access_point_id)
|
raise AccessPointNotFound(access_point_id)
|
||||||
return [self.access_points[access_point_id]]
|
return [self.access_points[access_point_id]]
|
||||||
return self.access_points.values()
|
return list(self.access_points.values())
|
||||||
|
|
||||||
def delete_access_point(self, access_point_id):
|
def delete_access_point(self, access_point_id: str) -> None:
|
||||||
self.access_points.pop(access_point_id, None)
|
self.access_points.pop(access_point_id, None)
|
||||||
|
|
||||||
def list_tags_for_resource(self, resource_id):
|
def list_tags_for_resource(self, resource_id: str) -> List[Dict[str, str]]:
|
||||||
return self.tagging_service.list_tags_for_resource(resource_id)["Tags"]
|
return self.tagging_service.list_tags_for_resource(resource_id)["Tags"]
|
||||||
|
|
||||||
def tag_resource(self, resource_id, tags):
|
def tag_resource(self, resource_id: str, tags: List[Dict[str, str]]) -> None:
|
||||||
self.tagging_service.tag_resource(resource_id, tags)
|
self.tagging_service.tag_resource(resource_id, tags)
|
||||||
|
|
||||||
def untag_resource(self, resource_id, tag_keys):
|
def untag_resource(self, resource_id: str, tag_keys: List[str]) -> None:
|
||||||
self.tagging_service.untag_resource_using_names(resource_id, tag_keys)
|
self.tagging_service.untag_resource_using_names(resource_id, tag_keys)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
import json
|
import json
|
||||||
|
from typing import Any, Dict, Tuple, Union
|
||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
|
|
||||||
from .models import efs_backends
|
from .models import efs_backends, EFSBackend
|
||||||
|
|
||||||
|
|
||||||
|
TYPE_RESPONSE = Tuple[str, Dict[str, Union[str, int]]]
|
||||||
|
|
||||||
|
|
||||||
class EFSResponse(BaseResponse):
|
class EFSResponse(BaseResponse):
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__(service_name="efs")
|
super().__init__(service_name="efs")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def efs_backend(self):
|
def efs_backend(self) -> EFSBackend:
|
||||||
return efs_backends[self.current_account][self.region]
|
return efs_backends[self.current_account][self.region]
|
||||||
|
|
||||||
def create_file_system(self):
|
def create_file_system(self) -> TYPE_RESPONSE:
|
||||||
creation_token = self._get_param("CreationToken")
|
creation_token = self._get_param("CreationToken")
|
||||||
performance_mode = self._get_param("PerformanceMode")
|
performance_mode = self._get_param("PerformanceMode")
|
||||||
encrypted = self._get_param("Encrypted")
|
encrypted = self._get_param("Encrypted")
|
||||||
@ -41,7 +45,7 @@ class EFSResponse(BaseResponse):
|
|||||||
{"status": 201, "Content-Type": "application/json"},
|
{"status": 201, "Content-Type": "application/json"},
|
||||||
)
|
)
|
||||||
|
|
||||||
def describe_file_systems(self):
|
def describe_file_systems(self) -> TYPE_RESPONSE:
|
||||||
max_items = self._get_int_param("MaxItems", 10)
|
max_items = self._get_int_param("MaxItems", 10)
|
||||||
marker = self._get_param("Marker")
|
marker = self._get_param("Marker")
|
||||||
creation_token = self._get_param("CreationToken")
|
creation_token = self._get_param("CreationToken")
|
||||||
@ -52,14 +56,16 @@ class EFSResponse(BaseResponse):
|
|||||||
creation_token=creation_token,
|
creation_token=creation_token,
|
||||||
file_system_id=file_system_id,
|
file_system_id=file_system_id,
|
||||||
)
|
)
|
||||||
resp_json = {"FileSystems": [fs.info_json() for fs in file_systems]}
|
resp_json: Dict[str, Any] = {
|
||||||
|
"FileSystems": [fs.info_json() for fs in file_systems]
|
||||||
|
}
|
||||||
if marker:
|
if marker:
|
||||||
resp_json["Marker"] = marker
|
resp_json["Marker"] = marker
|
||||||
if next_marker:
|
if next_marker:
|
||||||
resp_json["NextMarker"] = next_marker
|
resp_json["NextMarker"] = next_marker
|
||||||
return json.dumps(resp_json), {"Content-Type": "application/json"}
|
return json.dumps(resp_json), {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def create_mount_target(self):
|
def create_mount_target(self) -> TYPE_RESPONSE:
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
subnet_id = self._get_param("SubnetId")
|
subnet_id = self._get_param("SubnetId")
|
||||||
ip_address = self._get_param("IpAddress")
|
ip_address = self._get_param("IpAddress")
|
||||||
@ -75,7 +81,7 @@ class EFSResponse(BaseResponse):
|
|||||||
{"Content-Type": "application/json"},
|
{"Content-Type": "application/json"},
|
||||||
)
|
)
|
||||||
|
|
||||||
def describe_mount_targets(self):
|
def describe_mount_targets(self) -> TYPE_RESPONSE:
|
||||||
max_items = self._get_int_param("MaxItems", 10)
|
max_items = self._get_int_param("MaxItems", 10)
|
||||||
marker = self._get_param("Marker")
|
marker = self._get_param("Marker")
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
@ -88,30 +94,32 @@ class EFSResponse(BaseResponse):
|
|||||||
access_point_id=access_point_id,
|
access_point_id=access_point_id,
|
||||||
marker=marker,
|
marker=marker,
|
||||||
)
|
)
|
||||||
resp_json = {"MountTargets": [mt.info_json() for mt in mount_targets]}
|
resp_json: Dict[str, Any] = {
|
||||||
|
"MountTargets": [mt.info_json() for mt in mount_targets]
|
||||||
|
}
|
||||||
if marker:
|
if marker:
|
||||||
resp_json["Marker"] = marker
|
resp_json["Marker"] = marker
|
||||||
if next_marker:
|
if next_marker:
|
||||||
resp_json["NextMarker"] = next_marker
|
resp_json["NextMarker"] = next_marker
|
||||||
return json.dumps(resp_json), {"Content-Type": "application/json"}
|
return json.dumps(resp_json), {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def delete_file_system(self):
|
def delete_file_system(self) -> TYPE_RESPONSE:
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
self.efs_backend.delete_file_system(file_system_id)
|
self.efs_backend.delete_file_system(file_system_id)
|
||||||
return json.dumps(dict()), {"status": 204, "Content-Type": "application/json"}
|
return json.dumps(dict()), {"status": 204, "Content-Type": "application/json"}
|
||||||
|
|
||||||
def delete_mount_target(self):
|
def delete_mount_target(self) -> TYPE_RESPONSE:
|
||||||
mount_target_id = self._get_param("MountTargetId")
|
mount_target_id = self._get_param("MountTargetId")
|
||||||
self.efs_backend.delete_mount_target(mount_target_id)
|
self.efs_backend.delete_mount_target(mount_target_id)
|
||||||
return json.dumps(dict()), {"status": 204, "Content-Type": "application/json"}
|
return json.dumps(dict()), {"status": 204, "Content-Type": "application/json"}
|
||||||
|
|
||||||
def describe_backup_policy(self):
|
def describe_backup_policy(self) -> TYPE_RESPONSE:
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
backup_policy = self.efs_backend.describe_backup_policy(file_system_id)
|
backup_policy = self.efs_backend.describe_backup_policy(file_system_id)
|
||||||
resp = {"BackupPolicy": backup_policy}
|
resp = {"BackupPolicy": backup_policy}
|
||||||
return json.dumps(resp), {"Content-Type": "application/json"}
|
return json.dumps(resp), {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def put_lifecycle_configuration(self):
|
def put_lifecycle_configuration(self) -> TYPE_RESPONSE:
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
policies = self._get_param("LifecyclePolicies")
|
policies = self._get_param("LifecyclePolicies")
|
||||||
self.efs_backend.put_lifecycle_configuration(file_system_id, policies)
|
self.efs_backend.put_lifecycle_configuration(file_system_id, policies)
|
||||||
@ -119,14 +127,14 @@ class EFSResponse(BaseResponse):
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
def describe_lifecycle_configuration(self):
|
def describe_lifecycle_configuration(self) -> TYPE_RESPONSE:
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
policies = self.efs_backend.describe_lifecycle_configuration(file_system_id)
|
policies = self.efs_backend.describe_lifecycle_configuration(file_system_id)
|
||||||
return json.dumps({"LifecyclePolicies": policies}), {
|
return json.dumps({"LifecyclePolicies": policies}), {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
def describe_mount_target_security_groups(self):
|
def describe_mount_target_security_groups(self) -> TYPE_RESPONSE:
|
||||||
mount_target_id = self._get_param("MountTargetId")
|
mount_target_id = self._get_param("MountTargetId")
|
||||||
security_groups = self.efs_backend.describe_mount_target_security_groups(
|
security_groups = self.efs_backend.describe_mount_target_security_groups(
|
||||||
mount_target_id
|
mount_target_id
|
||||||
@ -135,7 +143,7 @@ class EFSResponse(BaseResponse):
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
def modify_mount_target_security_groups(self):
|
def modify_mount_target_security_groups(self) -> TYPE_RESPONSE:
|
||||||
mount_target_id = self._get_param("MountTargetId")
|
mount_target_id = self._get_param("MountTargetId")
|
||||||
security_groups = self._get_param("SecurityGroups")
|
security_groups = self._get_param("SecurityGroups")
|
||||||
self.efs_backend.modify_mount_target_security_groups(
|
self.efs_backend.modify_mount_target_security_groups(
|
||||||
@ -143,7 +151,7 @@ class EFSResponse(BaseResponse):
|
|||||||
)
|
)
|
||||||
return "{}", {"Content-Type": "application/json"}
|
return "{}", {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def create_access_point(self):
|
def create_access_point(self) -> TYPE_RESPONSE:
|
||||||
client_token = self._get_param("ClientToken")
|
client_token = self._get_param("ClientToken")
|
||||||
tags = self._get_param("Tags") or []
|
tags = self._get_param("Tags") or []
|
||||||
file_system_id = self._get_param("FileSystemId")
|
file_system_id = self._get_param("FileSystemId")
|
||||||
@ -160,29 +168,29 @@ class EFSResponse(BaseResponse):
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
def describe_access_points(self):
|
def describe_access_points(self) -> TYPE_RESPONSE:
|
||||||
access_point_id = self._get_param("AccessPointId")
|
access_point_id = self._get_param("AccessPointId")
|
||||||
access_points = self.efs_backend.describe_access_points(access_point_id)
|
access_points = self.efs_backend.describe_access_points(access_point_id)
|
||||||
resp = [ap.info_json() for ap in access_points]
|
resp = [ap.info_json() for ap in access_points]
|
||||||
return json.dumps({"AccessPoints": resp}), {"Content-Type": "application/json"}
|
return json.dumps({"AccessPoints": resp}), {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def delete_access_point(self):
|
def delete_access_point(self) -> TYPE_RESPONSE:
|
||||||
access_point_id = self._get_param("AccessPointId")
|
access_point_id = self._get_param("AccessPointId")
|
||||||
self.efs_backend.delete_access_point(access_point_id)
|
self.efs_backend.delete_access_point(access_point_id)
|
||||||
return "{}", {"Content-Type": "application/json"}
|
return "{}", {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def list_tags_for_resource(self):
|
def list_tags_for_resource(self) -> TYPE_RESPONSE:
|
||||||
resource_id = self._get_param("ResourceId")
|
resource_id = self._get_param("ResourceId")
|
||||||
tags = self.efs_backend.list_tags_for_resource(resource_id)
|
tags = self.efs_backend.list_tags_for_resource(resource_id)
|
||||||
return json.dumps({"Tags": tags}), {"Content-Type": "application/json"}
|
return json.dumps({"Tags": tags}), {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def tag_resource(self):
|
def tag_resource(self) -> TYPE_RESPONSE:
|
||||||
resource_id = self._get_param("ResourceId")
|
resource_id = self._get_param("ResourceId")
|
||||||
tags = self._get_param("Tags")
|
tags = self._get_param("Tags")
|
||||||
self.efs_backend.tag_resource(resource_id, tags)
|
self.efs_backend.tag_resource(resource_id, tags)
|
||||||
return "{}", {"Content-Type": "application/json"}
|
return "{}", {"Content-Type": "application/json"}
|
||||||
|
|
||||||
def untag_resource(self):
|
def untag_resource(self) -> TYPE_RESPONSE:
|
||||||
resource_id = self._get_param("ResourceId")
|
resource_id = self._get_param("ResourceId")
|
||||||
tag_keys = self.querystring.get("tagKeys", [])
|
tag_keys = self.querystring.get("tagKeys", [])
|
||||||
self.efs_backend.untag_resource(resource_id, tag_keys)
|
self.efs_backend.untag_resource(resource_id, tag_keys)
|
||||||
|
@ -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,moto/ec2instanceconnect,moto/ecr,moto/ecs,moto/es,moto/moto_api
|
files= moto/a*,moto/b*,moto/c*,moto/d*,moto/ebs/,moto/ec2,moto/ec2instanceconnect,moto/ecr,moto/ecs,moto/efs,moto/es,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