362 lines
12 KiB
Python
362 lines
12 KiB
Python
import re
|
|
from os import environ
|
|
|
|
import boto3
|
|
import pytest
|
|
from botocore.exceptions import ClientError
|
|
|
|
from moto import mock_efs
|
|
from tests.test_efs.junk_drawer import has_status_code
|
|
|
|
ARN_PATT = r"^arn:(?P<Partition>[^:\n]*):(?P<Service>[^:\n]*):(?P<Region>[^:\n]*):(?P<AccountID>[^:\n]*):(?P<Ignore>(?P<ResourceType>[^:\/\n]*)[:\/])?(?P<Resource>.*)$"
|
|
STRICT_ARN_PATT = r"^arn:aws:[a-z]+:[a-z]{2}-[a-z]+-[0-9]:[0-9]+:[a-z-]+\/[a-z0-9-]+$"
|
|
|
|
SAMPLE_1_PARAMS = {
|
|
"CreationToken": "myFileSystem1",
|
|
"PerformanceMode": "generalPurpose",
|
|
"Backup": True,
|
|
"Encrypted": True,
|
|
"Tags": [{"Key": "Name", "Value": "Test Group1"}],
|
|
}
|
|
|
|
SAMPLE_2_PARAMS = {
|
|
"CreationToken": "myFileSystem2",
|
|
"PerformanceMode": "generalPurpose",
|
|
"Backup": True,
|
|
"AvailabilityZoneName": "us-west-2b",
|
|
"Encrypted": True,
|
|
"ThroughputMode": "provisioned",
|
|
"ProvisionedThroughputInMibps": 60,
|
|
"Tags": [{"Key": "Name", "Value": "Test Group1"}],
|
|
}
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def aws_credentials():
|
|
"""Mocked AWS Credentials for moto."""
|
|
environ["AWS_ACCESS_KEY_ID"] = "testing"
|
|
environ["AWS_SECRET_ACCESS_KEY"] = "testing"
|
|
environ["AWS_SECURITY_TOKEN"] = "testing"
|
|
environ["AWS_SESSION_TOKEN"] = "testing"
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def efs(aws_credentials): # pylint: disable=unused-argument
|
|
with mock_efs():
|
|
yield boto3.client("efs", region_name="us-east-1")
|
|
|
|
|
|
# Testing Create
|
|
# ==============
|
|
|
|
|
|
def test_create_file_system_correct_use(efs):
|
|
from datetime import datetime
|
|
|
|
creation_token = "test_efs_create"
|
|
create_fs_resp = efs.create_file_system(
|
|
CreationToken=creation_token,
|
|
Tags=[{"Key": "Name", "Value": "Test EFS Container"}],
|
|
)
|
|
|
|
# Check the response.
|
|
assert has_status_code(create_fs_resp, 201)
|
|
assert create_fs_resp["CreationToken"] == creation_token
|
|
assert "fs-" in create_fs_resp["FileSystemId"]
|
|
assert isinstance(create_fs_resp["CreationTime"], datetime)
|
|
assert create_fs_resp["LifeCycleState"] == "available"
|
|
assert create_fs_resp["Tags"][0] == {"Key": "Name", "Value": "Test EFS Container"}
|
|
assert create_fs_resp["ThroughputMode"] == "bursting"
|
|
assert create_fs_resp["PerformanceMode"] == "generalPurpose"
|
|
assert create_fs_resp["Encrypted"] is False
|
|
assert create_fs_resp["NumberOfMountTargets"] == 0
|
|
for key_name in ["Value", "ValueInIA", "ValueInStandard"]:
|
|
assert key_name in create_fs_resp["SizeInBytes"]
|
|
assert create_fs_resp["SizeInBytes"][key_name] == 0
|
|
assert re.match(STRICT_ARN_PATT, create_fs_resp["FileSystemArn"])
|
|
|
|
# Check the (lack of the) backup policy.
|
|
with pytest.raises(ClientError) as exc_info:
|
|
efs.describe_backup_policy(FileSystemId=create_fs_resp["FileSystemId"])
|
|
resp = exc_info.value.response
|
|
assert resp["ResponseMetadata"]["HTTPStatusCode"] == 404
|
|
assert "PolicyNotFound" in resp["Error"]["Message"]
|
|
|
|
# Check the arn in detail
|
|
match_obj = re.match(ARN_PATT, create_fs_resp["FileSystemArn"])
|
|
arn_parts = match_obj.groupdict()
|
|
assert arn_parts["ResourceType"] == "file-system"
|
|
assert arn_parts["Resource"] == create_fs_resp["FileSystemId"]
|
|
assert arn_parts["Service"] == "elasticfilesystem"
|
|
assert arn_parts["AccountID"] == create_fs_resp["OwnerId"]
|
|
|
|
|
|
def test_create_file_system_aws_sample_1(efs):
|
|
resp = efs.create_file_system(**SAMPLE_1_PARAMS)
|
|
resp_metadata = resp.pop("ResponseMetadata")
|
|
assert resp_metadata["HTTPStatusCode"] == 201
|
|
assert set(resp.keys()) == {
|
|
"OwnerId",
|
|
"CreationToken",
|
|
"Encrypted",
|
|
"PerformanceMode",
|
|
"FileSystemId",
|
|
"FileSystemArn",
|
|
"CreationTime",
|
|
"LifeCycleState",
|
|
"NumberOfMountTargets",
|
|
"SizeInBytes",
|
|
"Tags",
|
|
"ThroughputMode",
|
|
}
|
|
assert resp["Tags"] == [{"Key": "Name", "Value": "Test Group1"}]
|
|
assert resp["PerformanceMode"] == "generalPurpose"
|
|
assert resp["Encrypted"]
|
|
|
|
policy_resp = efs.describe_backup_policy(FileSystemId=resp["FileSystemId"])
|
|
assert policy_resp["BackupPolicy"]["Status"] == "ENABLED"
|
|
|
|
|
|
def test_create_file_system_aws_sample_2(efs):
|
|
resp = efs.create_file_system(**SAMPLE_2_PARAMS)
|
|
resp_metadata = resp.pop("ResponseMetadata")
|
|
assert resp_metadata["HTTPStatusCode"] == 201
|
|
assert set(resp.keys()) == {
|
|
"AvailabilityZoneId",
|
|
"AvailabilityZoneName",
|
|
"PerformanceMode",
|
|
"ProvisionedThroughputInMibps",
|
|
"SizeInBytes",
|
|
"Tags",
|
|
"ThroughputMode",
|
|
"CreationTime",
|
|
"CreationToken",
|
|
"Encrypted",
|
|
"LifeCycleState",
|
|
"FileSystemId",
|
|
"FileSystemArn",
|
|
"NumberOfMountTargets",
|
|
"OwnerId",
|
|
}
|
|
assert resp["ProvisionedThroughputInMibps"] == 60
|
|
assert resp["AvailabilityZoneId"] == "usw2-az1"
|
|
assert resp["AvailabilityZoneName"] == "us-west-2b"
|
|
assert resp["ThroughputMode"] == "provisioned"
|
|
|
|
policy_resp = efs.describe_backup_policy(FileSystemId=resp["FileSystemId"])
|
|
assert policy_resp["BackupPolicy"]["Status"] == "ENABLED"
|
|
|
|
|
|
def test_create_file_system_az_name_given_backup_default(efs):
|
|
resp = efs.create_file_system(AvailabilityZoneName="us-east-1e")
|
|
policy_resp = efs.describe_backup_policy(FileSystemId=resp["FileSystemId"])
|
|
assert policy_resp["BackupPolicy"]["Status"] == "ENABLED"
|
|
|
|
|
|
def test_create_file_system_no_creation_token_given(efs):
|
|
# Note that from the API docs, it would seem this should create an error. However it
|
|
# turns out that botocore just automatically assigns a UUID.
|
|
resp = efs.create_file_system()
|
|
assert resp["ResponseMetadata"]["HTTPStatusCode"] == 201
|
|
assert "CreationToken" in resp
|
|
|
|
|
|
def test_create_file_system_file_system_already_exists(efs):
|
|
efs.create_file_system(CreationToken="foo")
|
|
with pytest.raises(ClientError) as exc_info:
|
|
efs.create_file_system(CreationToken="foo")
|
|
resp = exc_info.value.response
|
|
assert resp["ResponseMetadata"]["HTTPStatusCode"] == 409
|
|
assert "FileSystemAlreadyExists" in resp["Error"]["Message"]
|
|
|
|
|
|
# Testing Describe
|
|
# ================
|
|
|
|
|
|
def test_describe_file_systems_minimal_case(efs):
|
|
# Create the file system.
|
|
create_fs_resp = efs.create_file_system(CreationToken="foobar")
|
|
create_fs_resp.pop("ResponseMetadata")
|
|
|
|
# Describe the file systems.
|
|
desc_fs_resp = efs.describe_file_systems()
|
|
desc_fs_resp_metadata = desc_fs_resp.pop("ResponseMetadata")
|
|
assert desc_fs_resp_metadata["HTTPStatusCode"] == 200
|
|
|
|
# Check the list results.
|
|
fs_list = desc_fs_resp["FileSystems"]
|
|
assert len(fs_list) == 1
|
|
file_system = fs_list[0]
|
|
assert set(file_system.keys()) == {
|
|
"CreationTime",
|
|
"CreationToken",
|
|
"Encrypted",
|
|
"LifeCycleState",
|
|
"PerformanceMode",
|
|
"SizeInBytes",
|
|
"Tags",
|
|
"ThroughputMode",
|
|
"FileSystemId",
|
|
"FileSystemArn",
|
|
"NumberOfMountTargets",
|
|
"OwnerId",
|
|
}
|
|
assert file_system["FileSystemId"] == create_fs_resp["FileSystemId"]
|
|
|
|
# Pop out the timestamps and see if the rest of the description is the same.
|
|
create_fs_resp["SizeInBytes"].pop("Timestamp")
|
|
file_system["SizeInBytes"].pop("Timestamp")
|
|
assert file_system == create_fs_resp
|
|
|
|
|
|
def test_describe_file_systems_aws_create_sample_2(efs):
|
|
efs.create_file_system(**SAMPLE_2_PARAMS)
|
|
|
|
# Describe the file systems.
|
|
desc_resp = efs.describe_file_systems()
|
|
desc_fs_resp_metadata = desc_resp.pop("ResponseMetadata")
|
|
assert desc_fs_resp_metadata["HTTPStatusCode"] == 200
|
|
|
|
# Check the list results.
|
|
fs_list = desc_resp["FileSystems"]
|
|
assert len(fs_list) == 1
|
|
file_system = fs_list[0]
|
|
|
|
assert set(file_system.keys()) == {
|
|
"AvailabilityZoneId",
|
|
"AvailabilityZoneName",
|
|
"CreationTime",
|
|
"CreationToken",
|
|
"Encrypted",
|
|
"LifeCycleState",
|
|
"PerformanceMode",
|
|
"ProvisionedThroughputInMibps",
|
|
"SizeInBytes",
|
|
"Tags",
|
|
"ThroughputMode",
|
|
"FileSystemId",
|
|
"FileSystemArn",
|
|
"NumberOfMountTargets",
|
|
"OwnerId",
|
|
}
|
|
assert file_system["ProvisionedThroughputInMibps"] == 60
|
|
assert file_system["AvailabilityZoneId"] == "usw2-az1"
|
|
assert file_system["AvailabilityZoneName"] == "us-west-2b"
|
|
assert file_system["ThroughputMode"] == "provisioned"
|
|
|
|
|
|
def test_describe_file_systems_paging(efs):
|
|
# Create several file systems.
|
|
for i in range(10):
|
|
efs.create_file_system(CreationToken="foobar_{}".format(i))
|
|
|
|
# First call (Start)
|
|
# ------------------
|
|
|
|
# Call the tested function
|
|
resp1 = efs.describe_file_systems(MaxItems=4)
|
|
|
|
# Check the response status
|
|
assert has_status_code(resp1, 200)
|
|
|
|
# Check content of the result.
|
|
resp1.pop("ResponseMetadata")
|
|
assert set(resp1.keys()) == {"NextMarker", "FileSystems"}
|
|
assert len(resp1["FileSystems"]) == 4
|
|
fs_id_set_1 = {fs["FileSystemId"] for fs in resp1["FileSystems"]}
|
|
|
|
# Second call (Middle)
|
|
# --------------------
|
|
|
|
# Get the next marker.
|
|
resp2 = efs.describe_file_systems(MaxItems=4, Marker=resp1["NextMarker"])
|
|
|
|
# Check the response status
|
|
resp2_metadata = resp2.pop("ResponseMetadata")
|
|
assert resp2_metadata["HTTPStatusCode"] == 200
|
|
|
|
# Check the response contents.
|
|
assert set(resp2.keys()) == {"NextMarker", "FileSystems", "Marker"}
|
|
assert len(resp2["FileSystems"]) == 4
|
|
assert resp2["Marker"] == resp1["NextMarker"]
|
|
fs_id_set_2 = {fs["FileSystemId"] for fs in resp2["FileSystems"]}
|
|
assert fs_id_set_1 & fs_id_set_2 == set()
|
|
|
|
# Third call (End)
|
|
# ----------------
|
|
|
|
# Get the last marker results
|
|
resp3 = efs.describe_file_systems(MaxItems=4, Marker=resp2["NextMarker"])
|
|
|
|
# Check the response status
|
|
resp3_metadata = resp3.pop("ResponseMetadata")
|
|
assert resp3_metadata["HTTPStatusCode"] == 200
|
|
|
|
# Check the response contents.
|
|
assert set(resp3.keys()) == {"FileSystems", "Marker"}
|
|
assert len(resp3["FileSystems"]) == 2
|
|
assert resp3["Marker"] == resp2["NextMarker"]
|
|
fs_id_set_3 = {fs["FileSystemId"] for fs in resp3["FileSystems"]}
|
|
assert fs_id_set_3 & (fs_id_set_1 | fs_id_set_2) == set()
|
|
|
|
|
|
def test_describe_file_systems_invalid_marker(efs):
|
|
with pytest.raises(ClientError) as exc_info:
|
|
efs.describe_file_systems(Marker="fiddlesticks")
|
|
resp = exc_info.value.response
|
|
assert has_status_code(resp, 400)
|
|
assert "BadRequest" in resp["Error"]["Message"]
|
|
|
|
|
|
def test_describe_file_systems_invalid_creation_token(efs):
|
|
resp = efs.describe_file_systems(CreationToken="fizzle")
|
|
assert has_status_code(resp, 200)
|
|
assert len(resp["FileSystems"]) == 0
|
|
|
|
|
|
def test_describe_file_systems_invalid_file_system_id(efs):
|
|
with pytest.raises(ClientError) as exc_info:
|
|
efs.describe_file_systems(FileSystemId="fs-29879313")
|
|
resp = exc_info.value.response
|
|
assert has_status_code(resp, 404)
|
|
assert "FileSystemNotFound" in resp["Error"]["Message"]
|
|
|
|
|
|
def test_describe_file_system_creation_token_and_file_system_id(efs):
|
|
with pytest.raises(ClientError) as exc_info:
|
|
efs.describe_file_systems(CreationToken="fizzle", FileSystemId="fs-07987987")
|
|
resp = exc_info.value.response
|
|
assert has_status_code(resp, 400)
|
|
assert "BadRequest" in resp["Error"]["Message"]
|
|
|
|
|
|
# Testing Delete
|
|
# ==============
|
|
|
|
|
|
def test_delete_file_system_minimal_case(efs):
|
|
# Create the file system
|
|
resp = efs.create_file_system()
|
|
|
|
# Describe the file system, prove it shows up.
|
|
desc1 = efs.describe_file_systems()
|
|
assert len(desc1["FileSystems"]) == 1
|
|
assert resp["FileSystemId"] in {fs["FileSystemId"] for fs in desc1["FileSystems"]}
|
|
|
|
# Delete the file system.
|
|
del_resp = efs.delete_file_system(FileSystemId=resp["FileSystemId"])
|
|
assert has_status_code(del_resp, 204)
|
|
|
|
# Check that the file system is no longer there.
|
|
desc2 = efs.describe_file_systems()
|
|
assert len(desc2["FileSystems"]) == 0
|
|
|
|
|
|
def test_delete_file_system_invalid_file_system_id(efs):
|
|
with pytest.raises(ClientError) as exc_info:
|
|
efs.delete_file_system(FileSystemId="fs-2394287")
|
|
resp = exc_info.value.response
|
|
assert has_status_code(resp, 404)
|
|
assert "FileSystemNotFound" in resp["Error"]["Message"]
|