feat(cloud): add edge host enrollment

This commit is contained in:
2026-07-13 13:54:16 +08:00
parent cd56facbbf
commit e61dcca801
40 changed files with 2302 additions and 48 deletions
+143 -1
View File
@@ -14,7 +14,14 @@ from cloud.database import CloudDatabase
from cloud.db_models import TaskAttemptRow
from cloud.plugins import PluginManifest
from cloud.pool import PooledDevice
from cloud.repository import CloudRepository, LeasedAssignment, TaskAttemptRecord
from cloud.repository import (
CloudRepository,
DeviceEnrollmentConflictError,
EnrollmentTokenConflictError,
HostEnrollmentConflictError,
LeasedAssignment,
TaskAttemptRecord,
)
from cloud.scheduler import ScheduledTask, TaskConstraints
@@ -53,6 +60,13 @@ def test_cloud_repository_exposes_crud_and_atomic_lease_operations() -> None:
members = get_protocol_members(CloudRepository)
assert {
"enroll_host",
"authenticate_enrolled_host",
"revoke_enrolled_host",
"is_enrollment_managed_host",
"enroll_device",
"get_device_enrollment",
"list_device_enrollments",
"upsert_host",
"replace_host_devices",
"list_hosts",
@@ -76,6 +90,134 @@ def test_repository_transfer_records_are_immutable() -> None:
assert LeasedAssignment.__dataclass_params__.frozen is True
def test_host_enrollment_is_idempotent_and_token_is_one_time(
database_url: str,
) -> None:
database = CloudDatabase(database_url)
repository = database.repository
enrolled_at = datetime(2026, 7, 13, 4, 0, tzinfo=UTC)
host_id = _unique_id("managed-host")
agent_instance_id = _unique_id("agent-instance")
credential_digest = _unique_id("credential-digest")
enrollment_digest = _unique_id("enrollment-digest")
try:
created = repository.enroll_host(
host_id=host_id,
agent_instance_id=agent_instance_id,
credential_digest=credential_digest,
enrollment_token_digest=enrollment_digest,
display_name="Edge Mac",
enrolled_at=enrolled_at,
)
assert created.host_id == host_id
assert created.agent_instance_id == agent_instance_id
assert created.display_name == "Edge Mac"
assert created.enrolled_at == enrolled_at
assert repository.is_enrollment_managed_host(host_id) is True
assert repository.authenticate_enrolled_host(credential_digest) == host_id
retried = repository.enroll_host(
host_id=_unique_id("ignored-host"),
agent_instance_id=agent_instance_id,
credential_digest=credential_digest,
enrollment_token_digest=enrollment_digest,
display_name="Renamed Edge Mac",
enrolled_at=enrolled_at + timedelta(minutes=1),
)
assert retried == created
with pytest.raises(HostEnrollmentConflictError):
repository.enroll_host(
host_id=_unique_id("host"),
agent_instance_id=agent_instance_id,
credential_digest=_unique_id("different-credential"),
enrollment_token_digest=enrollment_digest,
display_name=None,
enrolled_at=enrolled_at,
)
with pytest.raises(EnrollmentTokenConflictError):
repository.enroll_host(
host_id=_unique_id("host"),
agent_instance_id=_unique_id("different-instance"),
credential_digest=_unique_id("credential"),
enrollment_token_digest=enrollment_digest,
display_name=None,
enrolled_at=enrolled_at,
)
assert repository.revoke_enrolled_host(
host_id,
revoked_at=enrolled_at + timedelta(hours=1),
)
assert repository.authenticate_enrolled_host(credential_digest) is None
assert repository.get_host(host_id) is not None
finally:
database.close()
def test_device_enrollment_is_host_scoped_and_idempotent(
database_url: str,
) -> None:
database = CloudDatabase(database_url)
repository = database.repository
enrolled_at = datetime(2026, 7, 13, 5, 0, tzinfo=UTC)
host_a = _unique_id("host-a")
host_b = _unique_id("host-b")
local_device_id = _unique_id("local-device")
try:
device_a = repository.enroll_device(
device_id=_unique_id("cloud-device"),
host_id=host_a,
local_device_id=local_device_id,
driver_type="wda",
name="iPhone",
capability_tags=["ios"],
enrolled_at=enrolled_at,
)
retried = repository.enroll_device(
device_id=_unique_id("ignored-device"),
host_id=host_a,
local_device_id=local_device_id,
driver_type="wda",
name="Renamed iPhone",
capability_tags=["ios", "physical"],
enrolled_at=enrolled_at + timedelta(minutes=1),
)
assert retried.device_id == device_a.device_id
assert retried.name == "Renamed iPhone"
assert retried.capability_tags == ["ios", "physical"]
assert repository.get_device_enrollment(device_a.device_id) == retried
assert repository.list_device_enrollments(host_a) == [retried]
device_b = repository.enroll_device(
device_id=_unique_id("cloud-device"),
host_id=host_b,
local_device_id=local_device_id,
driver_type="wda",
name="Moved iPhone",
capability_tags=[],
enrolled_at=enrolled_at,
)
assert device_b.device_id != device_a.device_id
assert device_b.host_id == host_b
with pytest.raises(DeviceEnrollmentConflictError):
repository.enroll_device(
device_id=_unique_id("device"),
host_id=host_a,
local_device_id=local_device_id,
driver_type="android",
name=None,
capability_tags=[],
enrolled_at=enrolled_at,
)
finally:
database.close()
def test_repository_crud_contract(database_url: str) -> None:
database = CloudDatabase(database_url)
repository = database.repository