Add TTL parser, expires_at on create, extend_ttl and expire/reap APIs, activity-core integration doc, repo classification, registry refresh, HTTP parity, and 69 tests.
151 lines
No EOL
4.8 KiB
Python
151 lines
No EOL
4.8 KiB
Python
"""HTTP API v0 stub tests."""
|
|
|
|
from unittest.mock import patch
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from sandboxer.api.app import app
|
|
from sandboxer.models import ActorType, Consumer, SandboxState, SandboxStatus, SnapshotRecord
|
|
|
|
|
|
def test_list_sandboxes_empty() -> None:
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.list.return_value = []
|
|
client = TestClient(app)
|
|
assert client.get("/v1/sandboxes").json() == []
|
|
|
|
|
|
def test_get_sandbox_not_found() -> None:
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.get.return_value = None
|
|
client = TestClient(app)
|
|
assert client.get("/v1/sandboxes/missing").status_code == 404
|
|
|
|
|
|
def test_create_sandbox() -> None:
|
|
from datetime import UTC, datetime
|
|
|
|
status = SandboxStatus(
|
|
sandbox_id="abc12345",
|
|
profile_id="profile.compose-e2e",
|
|
extension_id="ext.compose-ssh",
|
|
state=SandboxState.READY,
|
|
consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"),
|
|
created_at=datetime.now(UTC),
|
|
updated_at=datetime.now(UTC),
|
|
)
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.create.return_value = status
|
|
client = TestClient(app)
|
|
resp = client.post(
|
|
"/v1/sandboxes",
|
|
json={
|
|
"profile": "profile.compose-e2e",
|
|
"inputs": {"repo": "/tmp/x"},
|
|
"consumer": {"actor": "adm", "project": "sand-boxer"},
|
|
},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["sandbox_id"] == "abc12345"
|
|
|
|
|
|
def test_snapshot_sandbox() -> None:
|
|
from datetime import UTC, datetime
|
|
|
|
record = SnapshotRecord(
|
|
snapshot_id="snap12345678",
|
|
sandbox_id="abc12345",
|
|
profile_id="profile.compose-checkpoint",
|
|
extension_id="ext.compose-ssh",
|
|
host="coulombcore",
|
|
created_at=datetime.now(UTC),
|
|
)
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.snapshot.return_value = record
|
|
client = TestClient(app)
|
|
resp = client.post("/v1/sandboxes/abc12345/snapshot")
|
|
assert resp.status_code == 200
|
|
assert resp.json()["snapshot_id"] == "snap12345678"
|
|
|
|
|
|
def test_restore_snapshot() -> None:
|
|
from datetime import UTC, datetime
|
|
|
|
status = SandboxStatus(
|
|
sandbox_id="restored1",
|
|
profile_id="profile.compose-checkpoint",
|
|
extension_id="ext.compose-ssh",
|
|
state=SandboxState.READY,
|
|
consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"),
|
|
created_at=datetime.now(UTC),
|
|
updated_at=datetime.now(UTC),
|
|
)
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.restore.return_value = status
|
|
client = TestClient(app)
|
|
resp = client.post(
|
|
"/v1/snapshots/snap12345678/restore",
|
|
json={"consumer": {"actor": "adm", "project": "sand-boxer"}},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["sandbox_id"] == "restored1"
|
|
|
|
|
|
def test_recreate_sandbox() -> None:
|
|
from datetime import UTC, datetime
|
|
|
|
status = SandboxStatus(
|
|
sandbox_id="new12345",
|
|
profile_id="profile.compose-e2e",
|
|
extension_id="ext.compose-ssh",
|
|
state=SandboxState.READY,
|
|
consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"),
|
|
created_at=datetime.now(UTC),
|
|
updated_at=datetime.now(UTC),
|
|
)
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.recreate.return_value = status
|
|
client = TestClient(app)
|
|
resp = client.post("/v1/sandboxes/abc12345/recreate")
|
|
assert resp.status_code == 200
|
|
assert resp.json()["sandbox_id"] == "new12345"
|
|
|
|
|
|
def test_extend_ttl() -> None:
|
|
from datetime import UTC, datetime
|
|
|
|
now = datetime.now(UTC)
|
|
status = SandboxStatus(
|
|
sandbox_id="abc12345",
|
|
profile_id="profile.compose-e2e",
|
|
extension_id="ext.compose-ssh",
|
|
state=SandboxState.READY,
|
|
consumer=Consumer(actor=ActorType.ADM, project="sand-boxer"),
|
|
ttl="2h",
|
|
expires_at=now,
|
|
created_at=now,
|
|
updated_at=now,
|
|
ready_at=now,
|
|
)
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.extend_ttl.return_value = status
|
|
client = TestClient(app)
|
|
resp = client.patch(
|
|
"/v1/sandboxes/abc12345/ttl",
|
|
json={"duration": "2h"},
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["ttl"] == "2h"
|
|
|
|
|
|
def test_expire_sandboxes() -> None:
|
|
from sandboxer.models import ExpireActionResult
|
|
|
|
with patch("sandboxer.api.app._manager") as mgr:
|
|
mgr.expire.return_value = [
|
|
ExpireActionResult(sandbox_id="x", reason="ttl", action="dry-run")
|
|
]
|
|
client = TestClient(app)
|
|
resp = client.post("/v1/sandboxes/expire")
|
|
assert resp.status_code == 200
|
|
assert resp.json()[0]["action"] == "dry-run" |