Don't blow up when a backup doesn't exist on Synology DSM (#136913)

* don't raise while delte not existing backup

* only raise when error ne 408
pull/136725/head^2
Michael 2025-02-03 23:42:30 +01:00 committed by GitHub
parent 42cab208d0
commit f9cc3361e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 19 deletions

View File

@ -161,15 +161,20 @@ class SynologyDSMBackupAgent(BackupAgent):
:param backup_id: The ID of the backup that was returned in async_list_backups.
"""
try:
await self._file_station.delete_file(
path=self.path, filename=f"{backup_id}.tar"
)
await self._file_station.delete_file(
path=self.path, filename=f"{backup_id}_meta.json"
)
except SynologyDSMAPIErrorException as err:
raise BackupAgentError("Failed to delete the backup") from err
for filename in (f"{backup_id}.tar", f"{backup_id}_meta.json"):
try:
await self._file_station.delete_file(path=self.path, filename=filename)
except SynologyDSMAPIErrorException as err:
err_args: dict = err.args[0]
if int(err_args.get("code", 0)) != 900 or (
(err_details := err_args.get("details")) is not None
and isinstance(err_details, list)
and isinstance(err_details[0], dict)
and int(err_details[0].get("code", 0))
!= 408 # No such file or directory
):
LOGGER.error("Failed to delete backup: %s", err)
raise BackupAgentError("Failed to delete backup") from err
async def async_list_backups(self, **kwargs: Any) -> list[AgentBackup]:
"""List backups."""

View File

@ -673,7 +673,11 @@ async def test_agents_delete_not_existing(
backup_id = "ef34ab12"
setup_dsm_with_filestation.file.delete_file = AsyncMock(
side_effect=SynologyDSMAPIErrorException("api", "404", "not found")
side_effect=SynologyDSMAPIErrorException(
"api",
"900",
[{"code": 408, "path": f"/ha_backup/my_backup_path/{backup_id}.tar"}],
)
)
await client.send_json_auto_id(
@ -685,26 +689,40 @@ async def test_agents_delete_not_existing(
response = await client.receive_json()
assert response["success"]
assert response["result"] == {
"agent_errors": {
"synology_dsm.mocked_syno_dsm_entry": "Failed to delete the backup"
}
}
assert response["result"] == {"agent_errors": {}}
@pytest.mark.parametrize(
("error", "expected_log"),
[
(
SynologyDSMAPIErrorException("api", "100", "Unknown error"),
"{'api': 'api', 'code': '100', 'reason': 'Unknown', 'details': 'Unknown error'}",
),
(
SynologyDSMAPIErrorException("api", "900", [{"code": 407}]),
"{'api': 'api', 'code': '900', 'reason': 'Unknown', 'details': [{'code': 407}]",
),
(
SynologyDSMAPIErrorException("api", "900", [{"code": 417}]),
"{'api': 'api', 'code': '900', 'reason': 'Unknown', 'details': [{'code': 417}]",
),
],
)
async def test_agents_delete_error(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
caplog: pytest.LogCaptureFixture,
setup_dsm_with_filestation: MagicMock,
error: SynologyDSMAPIErrorException,
expected_log: str,
) -> None:
"""Test error while delete backup."""
client = await hass_ws_client(hass)
# error while delete
backup_id = "abcd12ef"
setup_dsm_with_filestation.file.delete_file.side_effect = (
SynologyDSMAPIErrorException("api", "404", "not found")
)
setup_dsm_with_filestation.file.delete_file.side_effect = error
await client.send_json_auto_id(
{
"type": "backup/delete",
@ -716,9 +734,10 @@ async def test_agents_delete_error(
assert response["success"]
assert response["result"] == {
"agent_errors": {
"synology_dsm.mocked_syno_dsm_entry": "Failed to delete the backup"
"synology_dsm.mocked_syno_dsm_entry": "Failed to delete backup"
}
}
assert f"Failed to delete backup: {expected_log}" in caplog.text
mock: AsyncMock = setup_dsm_with_filestation.file.delete_file
assert len(mock.mock_calls) == 1
assert mock.call_args_list[0].kwargs["filename"] == "abcd12ef.tar"