fix(backups): fix orphaned snapshots erroring out

This commit is contained in:
Houkime 2024-05-24 12:30:27 +00:00
parent 5a100ec33a
commit 8e8e76a954
3 changed files with 49 additions and 18 deletions

View File

@ -34,6 +34,24 @@ class BackupConfiguration:
location_id: typing.Optional[str] location_id: typing.Optional[str]
# TODO: Ideally this should not be done in API but making an internal Service requires more work
# than to make an API record about a service
def tombstone_service(service_id: str) -> Service:
return Service(
id=service_id,
display_name=f"{service_id} (Orphaned)",
description="",
svg_icon="",
is_movable=False,
is_required=False,
is_enabled=False,
status=ServiceStatusEnum.OFF,
url=None,
can_be_backed_up=False,
backup_description="",
)
@strawberry.type @strawberry.type
class Backup: class Backup:
@strawberry.field @strawberry.field
@ -55,27 +73,21 @@ class Backup:
result = [] result = []
snapshots = Backups.get_all_snapshots() snapshots = Backups.get_all_snapshots()
for snap in snapshots: for snap in snapshots:
api_service = None
service = get_service_by_id(snap.service_name) service = get_service_by_id(snap.service_name)
if service is None: if service is None:
service = Service( api_service = tombstone_service(snap.service_name)
id=snap.service_name,
display_name=f"{snap.service_name} (Orphaned)",
description="",
svg_icon="",
is_movable=False,
is_required=False,
is_enabled=False,
status=ServiceStatusEnum.OFF,
url=None,
dns_records=None,
can_be_backed_up=False,
backup_description="",
)
else: else:
service = service_to_graphql_service(service) api_service = service_to_graphql_service(service)
if api_service is None:
raise NotImplementedError(
f"Could not construct API Service record for:{snap.service_name}. This should be unreachable and is a bug if you see it."
)
graphql_snap = SnapshotInfo( graphql_snap = SnapshotInfo(
id=snap.id, id=snap.id,
service=service, service=api_service,
created_at=snap.created_at, created_at=snap.created_at,
reason=snap.reason, reason=snap.reason,
) )

View File

@ -208,5 +208,7 @@ def dummy_service(
service.enable() service.enable()
yield service yield service
# cleanup because apparently it matters wrt tasks # Cleanup because apparently it matters wrt tasks
services.services.remove(service) # Some tests may remove it from the list intentionally, this is fine
if service in services.services:
services.services.remove(service)

View File

@ -3,6 +3,8 @@ from tests.test_backup import backups
from tests.common import generate_backup_query from tests.common import generate_backup_query
import selfprivacy_api.services as all_services
from selfprivacy_api.services import get_service_by_id
from selfprivacy_api.graphql.common_types.service import service_to_graphql_service from selfprivacy_api.graphql.common_types.service import service_to_graphql_service
from selfprivacy_api.graphql.common_types.backup import ( from selfprivacy_api.graphql.common_types.backup import (
_AutobackupQuotas, _AutobackupQuotas,
@ -143,6 +145,7 @@ allSnapshots {
id id
service { service {
id id
displayName
} }
createdAt createdAt
reason reason
@ -306,6 +309,20 @@ def test_snapshots_empty(authorized_client, dummy_service, backups):
assert snaps == [] assert snaps == []
def test_snapshots_orphaned_service(authorized_client, dummy_service, backups):
api_backup(authorized_client, dummy_service)
snaps = api_snapshots(authorized_client)
assert len(snaps) == 1
all_services.services.remove(dummy_service)
assert get_service_by_id(dummy_service.get_id()) is None
snaps = api_snapshots(authorized_client)
assert len(snaps) == 1
assert "Orphaned" in snaps[0]["service"]["displayName"]
assert dummy_service.get_id() in snaps[0]["service"]["displayName"]
def test_start_backup(authorized_client, dummy_service, backups): def test_start_backup(authorized_client, dummy_service, backups):
response = api_backup(authorized_client, dummy_service) response = api_backup(authorized_client, dummy_service)
data = get_data(response)["backup"]["startBackup"] data = get_data(response)["backup"]["startBackup"]