From 13767dd3b2671a2fb037932d73a3f20784ff5009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sun, 1 Dec 2024 12:38:12 +0100 Subject: [PATCH] Support reports of action_id that no longer maps to software As an edge case, the software can be deleted while device reboots after update. This caused errors and endless reporting of device. --- goosebit/updater/controller/v1/routes.py | 16 +++++++++++----- tests/updater/controller/v1/test_routes.py | 19 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/goosebit/updater/controller/v1/routes.py b/goosebit/updater/controller/v1/routes.py index 597cb546..2a4881ca 100644 --- a/goosebit/updater/controller/v1/routes.py +++ b/goosebit/updater/controller/v1/routes.py @@ -123,11 +123,15 @@ async def deployment_feedback(_: Request, data: FeedbackSchema, action_id: int, else: # edge case where device update mode got changed while update was running logging.warning( - f"Updating rollout success stats failed, software={reported_software.id}, device={device.uuid}" # noqa: E501 + f"Updating rollout success stats failed, action_id={action_id}, device={device.uuid}" # noqa: E501 ) - await DeviceManager.update_sw_version(device, reported_software.version) - logger.debug(f"Installation successful, software={reported_software.version}, device={device.uuid}") + if reported_software: + await DeviceManager.update_sw_version(device, reported_software.version) + + logger.debug( + f"Installation successful, software={reported_software.version if reported_software else None}, device={device.uuid}" + ) elif data.status.result.finished == FeedbackStatusResultFinished.FAILURE: await DeviceManager.update_device_state(device, UpdateStateEnum.ERROR) @@ -140,10 +144,12 @@ async def deployment_feedback(_: Request, data: FeedbackSchema, action_id: int, else: # edge case where device update mode got changed while update was running logging.warning( - f"Updating rollout failure stats failed, software={reported_software.id}, device={device.uuid}" # noqa: E501 + f"Updating rollout failure stats failed, action_id={action_id.id}, device={device.uuid}" # noqa: E501 ) - logger.debug(f"Installation failed, software={reported_software.version}, device={device.uuid}") + logger.debug( + f"Installation failed, software={reported_software.version if reported_software else None}, device={device.uuid}" + ) else: logging.error(f"Device reported unhandled execution state, state={data.status.execution}, device={device.uuid}") diff --git a/tests/updater/controller/v1/test_routes.py b/tests/updater/controller/v1/test_routes.py index f09eb84a..0c4f7fa1 100644 --- a/tests/updater/controller/v1/test_routes.py +++ b/tests/updater/controller/v1/test_routes.py @@ -146,7 +146,8 @@ async def test_register_device(async_client, test_data): @pytest.mark.asyncio -async def test_rollout_full(async_client, test_data): +@pytest.mark.parametrize("delete_software", [False, True]) +async def test_rollout_full(async_client, test_data, delete_software): device = test_data["device_rollout"] software = test_data["software_release"] rollout = test_data["rollout_default"] @@ -160,16 +161,22 @@ async def test_rollout_full(async_client, test_data): device_api = await _api_device_get(async_client, device.uuid) assert device_api["last_state"] == "Running" + # edge case: remove software during update + if delete_software: + await Software.delete(software) + # report finished installation await _feedback(async_client, device.uuid, software, "success", "closed") device_api = await _api_device_get(async_client, device.uuid) assert device_api["last_state"] == "Finished" - assert device_api["sw_version"] == software.version - await rollout.refresh_from_db() - rollouts = await _api_rollouts_get(async_client) - assert rollouts["rollouts"][0]["success_count"] == 1 - assert rollouts["rollouts"][0]["failure_count"] == 0 + if not delete_software: + assert device_api["sw_version"] == software.version + + await rollout.refresh_from_db() + rollouts = await _api_rollouts_get(async_client) + assert rollouts["rollouts"][0]["success_count"] == 1 + assert rollouts["rollouts"][0]["failure_count"] == 0 @pytest.mark.asyncio