little update
This commit is contained in:
151
tests/test_networking_manager.py
Normal file
151
tests/test_networking_manager.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from cloud.models import AvailabilityZone, Subnet
|
||||
from cloud.vm_manager import VMAPIError
|
||||
from database.models import Base, NetworkPoolEntry
|
||||
from networking import NetworkingManager, NetworkPoolExhaustedError
|
||||
|
||||
|
||||
class Cloud:
|
||||
def __init__(self) -> None:
|
||||
self.subnets: dict[str, Subnet] = {}
|
||||
self.created: list[str] = []
|
||||
self.requests = []
|
||||
self.zones: list[AvailabilityZone] = []
|
||||
self.subnet_states: list[str] = []
|
||||
|
||||
def get_subnet(self, subnet_id: str) -> Subnet:
|
||||
if subnet_id not in self.subnets:
|
||||
raise VMAPIError(404, "not found")
|
||||
subnet = self.subnets[subnet_id]
|
||||
if self.subnet_states:
|
||||
subnet.state = self.subnet_states.pop(0)
|
||||
return subnet
|
||||
|
||||
def list_availability_zones(self) -> list[AvailabilityZone]:
|
||||
return self.zones
|
||||
|
||||
def create_subnet(self, request):
|
||||
self.requests.append(request)
|
||||
subnet = Subnet(
|
||||
id=f"subnet-{len(self.subnets) + 1}",
|
||||
name=request.name,
|
||||
subnet_address=request.subnet_address,
|
||||
)
|
||||
self.subnets[subnet.id] = subnet
|
||||
self.created.append(subnet.subnet_address)
|
||||
return subnet
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def session_factory():
|
||||
engine = create_engine("sqlite://")
|
||||
Base.metadata.create_all(engine)
|
||||
return sessionmaker(engine, expire_on_commit=False)
|
||||
|
||||
|
||||
def test_allocates_new_network_and_reuses_after_release(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
manager = NetworkingManager(session_factory, cloud, "project-id", availability_zone_id="zone-id")
|
||||
first_game = uuid4()
|
||||
|
||||
first = manager.getNetworkFromPool(first_game)
|
||||
assert first.cidr == "10.0.0.0/20"
|
||||
assert first.game_id == first_game
|
||||
assert cloud.created == ["10.0.0.0/20"]
|
||||
|
||||
manager.releaseNetworkToPool(first_game)
|
||||
reused = manager.getNetworkFromPool(uuid4())
|
||||
assert reused.cidr == first.cidr
|
||||
assert len(cloud.created) == 1
|
||||
|
||||
|
||||
def test_waits_for_new_subnet_to_be_ready(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
cloud.subnet_states = ["creating", "created"]
|
||||
|
||||
entry = NetworkingManager(
|
||||
session_factory,
|
||||
cloud,
|
||||
"project-id",
|
||||
availability_zone_id="zone-id",
|
||||
poll_interval=0.001,
|
||||
).getNetworkFromPool(uuid4())
|
||||
|
||||
assert entry.cidr == "10.0.0.0/20"
|
||||
|
||||
|
||||
def test_discards_missing_cloud_network_and_creates_replacement(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
with session_factory.begin() as session:
|
||||
session.add(NetworkPoolEntry(cidr="10.0.0.0/20", cloud_subnet_id="gone"))
|
||||
|
||||
entry = NetworkingManager(session_factory, cloud, "project-id", availability_zone_id="zone-id").getNetworkFromPool(uuid4())
|
||||
|
||||
assert entry.cidr == "10.0.0.0/20"
|
||||
assert entry.cloud_subnet_id == "subnet-1"
|
||||
|
||||
|
||||
def test_passes_vpc_and_availability_zone_to_subnet_create(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
|
||||
NetworkingManager(
|
||||
session_factory,
|
||||
cloud,
|
||||
"project-id",
|
||||
vpc_id="vpc-id",
|
||||
availability_zone_id="zone-id",
|
||||
).getNetworkFromPool(uuid4())
|
||||
|
||||
request = cloud.requests[0]
|
||||
assert request.subnet_address == "10.0.0.0/20"
|
||||
assert request.vpc_id == "vpc-id"
|
||||
assert request.availability_zone_id == "zone-id"
|
||||
assert request.model_dump(exclude_none=True)["availability_zone_id"] == "zone-id"
|
||||
|
||||
|
||||
def test_resolves_availability_zone_name_to_id(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
cloud.zones.append(AvailabilityZone(id="zone-uuid", name="ru.AZ-2"))
|
||||
|
||||
NetworkingManager(
|
||||
session_factory,
|
||||
cloud,
|
||||
"project-id",
|
||||
availability_zone_name="ru.AZ-2",
|
||||
).getNetworkFromPool(uuid4())
|
||||
|
||||
assert cloud.requests[0].availability_zone_id == "zone-uuid"
|
||||
|
||||
|
||||
def test_raises_for_unknown_availability_zone_name(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
cloud.zones.append(AvailabilityZone(id="zone-uuid", name="ru.AZ-2"))
|
||||
|
||||
with pytest.raises(LookupError, match="ru.AZ-9"):
|
||||
NetworkingManager(
|
||||
session_factory,
|
||||
cloud,
|
||||
"project-id",
|
||||
availability_zone_name="ru.AZ-9",
|
||||
).getNetworkFromPool(uuid4())
|
||||
|
||||
|
||||
def test_raises_when_all_pool_cidrs_are_used(session_factory) -> None:
|
||||
cloud = Cloud()
|
||||
with session_factory.begin() as session:
|
||||
for octet in range(0, 256, 16):
|
||||
session.add(
|
||||
NetworkPoolEntry(
|
||||
cidr=f"10.{octet}.0.0/20",
|
||||
cloud_subnet_id=str(octet),
|
||||
game_id=uuid4(),
|
||||
)
|
||||
)
|
||||
|
||||
with pytest.raises(NetworkPoolExhaustedError, match="network pool exhausted"):
|
||||
NetworkingManager(session_factory, cloud, "project-id", availability_zone_id="zone-id").getNetworkFromPool(uuid4())
|
||||
Reference in New Issue
Block a user