Handle generic agent exceptions when getting and deleting backups (#138145)

* Handle generic agent exceptions when getting backups

* Update hassio test

* Update delete_backup
This commit is contained in:
Abílio Costa 2025-02-10 00:31:55 +00:00 committed by GitHub
parent 2f12187498
commit c2bb376c43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 226 additions and 31 deletions

View File

@ -560,8 +560,15 @@ class BackupManager:
return_exceptions=True, return_exceptions=True,
) )
for idx, result in enumerate(list_backups_results): for idx, result in enumerate(list_backups_results):
agent_id = agent_ids[idx]
if isinstance(result, BackupAgentError): if isinstance(result, BackupAgentError):
agent_errors[agent_ids[idx]] = result agent_errors[agent_id] = result
continue
if isinstance(result, Exception):
agent_errors[agent_id] = result
LOGGER.error(
"Unexpected error for %s: %s", agent_id, result, exc_info=result
)
continue continue
if isinstance(result, BaseException): if isinstance(result, BaseException):
raise result # unexpected error raise result # unexpected error
@ -588,7 +595,7 @@ class BackupManager:
name=agent_backup.name, name=agent_backup.name,
with_automatic_settings=with_automatic_settings, with_automatic_settings=with_automatic_settings,
) )
backups[backup_id].agents[agent_ids[idx]] = AgentBackupStatus( backups[backup_id].agents[agent_id] = AgentBackupStatus(
protected=agent_backup.protected, protected=agent_backup.protected,
size=agent_backup.size, size=agent_backup.size,
) )
@ -611,8 +618,15 @@ class BackupManager:
return_exceptions=True, return_exceptions=True,
) )
for idx, result in enumerate(get_backup_results): for idx, result in enumerate(get_backup_results):
agent_id = agent_ids[idx]
if isinstance(result, BackupAgentError): if isinstance(result, BackupAgentError):
agent_errors[agent_ids[idx]] = result agent_errors[agent_id] = result
continue
if isinstance(result, Exception):
agent_errors[agent_id] = result
LOGGER.error(
"Unexpected error for %s: %s", agent_id, result, exc_info=result
)
continue continue
if isinstance(result, BaseException): if isinstance(result, BaseException):
raise result # unexpected error raise result # unexpected error
@ -640,7 +654,7 @@ class BackupManager:
name=result.name, name=result.name,
with_automatic_settings=with_automatic_settings, with_automatic_settings=with_automatic_settings,
) )
backup.agents[agent_ids[idx]] = AgentBackupStatus( backup.agents[agent_id] = AgentBackupStatus(
protected=result.protected, protected=result.protected,
size=result.size, size=result.size,
) )
@ -676,8 +690,15 @@ class BackupManager:
return_exceptions=True, return_exceptions=True,
) )
for idx, result in enumerate(delete_backup_results): for idx, result in enumerate(delete_backup_results):
agent_id = agent_ids[idx]
if isinstance(result, BackupAgentError): if isinstance(result, BackupAgentError):
agent_errors[agent_ids[idx]] = result agent_errors[agent_id] = result
continue
if isinstance(result, Exception):
agent_errors[agent_id] = result
LOGGER.error(
"Unexpected error for %s: %s", agent_id, result, exc_info=result
)
continue continue
if isinstance(result, BaseException): if isinstance(result, BaseException):
raise result # unexpected error raise result # unexpected error

View File

@ -3697,12 +3697,13 @@
# --- # ---
# name: test_delete_with_errors[side_effect1-storage_data0] # name: test_delete_with_errors[side_effect1-storage_data0]
dict({ dict({
'error': dict({
'code': 'home_assistant_error',
'message': 'Boom!',
}),
'id': 1, 'id': 1,
'success': False, 'result': dict({
'agent_errors': dict({
'domain.test': 'Boom!',
}),
}),
'success': True,
'type': 'result', 'type': 'result',
}) })
# --- # ---
@ -3757,12 +3758,13 @@
# --- # ---
# name: test_delete_with_errors[side_effect1-storage_data1] # name: test_delete_with_errors[side_effect1-storage_data1]
dict({ dict({
'error': dict({
'code': 'home_assistant_error',
'message': 'Boom!',
}),
'id': 1, 'id': 1,
'success': False, 'result': dict({
'agent_errors': dict({
'domain.test': 'Boom!',
}),
}),
'success': True,
'type': 'result', 'type': 'result',
}) })
# --- # ---
@ -4019,12 +4021,89 @@
# --- # ---
# name: test_details_with_errors[side_effect0] # name: test_details_with_errors[side_effect0]
dict({ dict({
'error': dict({
'code': 'home_assistant_error',
'message': 'Boom!',
}),
'id': 1, 'id': 1,
'success': False, 'result': dict({
'agent_errors': dict({
'domain.test': 'Oops',
}),
'backup': dict({
'addons': list([
dict({
'name': 'Test',
'slug': 'test',
'version': '1.0.0',
}),
]),
'agents': dict({
'backup.local': dict({
'protected': False,
'size': 0,
}),
}),
'backup_id': 'abc123',
'database_included': True,
'date': '1970-01-01T00:00:00.000Z',
'extra_metadata': dict({
'instance_id': 'our_uuid',
'with_automatic_settings': True,
}),
'failed_agent_ids': list([
]),
'folders': list([
'media',
'share',
]),
'homeassistant_included': True,
'homeassistant_version': '2024.12.0',
'name': 'Test',
'with_automatic_settings': True,
}),
}),
'success': True,
'type': 'result',
})
# ---
# name: test_details_with_errors[side_effect1]
dict({
'id': 1,
'result': dict({
'agent_errors': dict({
'domain.test': 'Boom!',
}),
'backup': dict({
'addons': list([
dict({
'name': 'Test',
'slug': 'test',
'version': '1.0.0',
}),
]),
'agents': dict({
'backup.local': dict({
'protected': False,
'size': 0,
}),
}),
'backup_id': 'abc123',
'database_included': True,
'date': '1970-01-01T00:00:00.000Z',
'extra_metadata': dict({
'instance_id': 'our_uuid',
'with_automatic_settings': True,
}),
'failed_agent_ids': list([
]),
'folders': list([
'media',
'share',
]),
'homeassistant_included': True,
'homeassistant_version': '2024.12.0',
'name': 'Test',
'with_automatic_settings': True,
}),
}),
'success': True,
'type': 'result', 'type': 'result',
}) })
# --- # ---
@ -4542,12 +4621,105 @@
# --- # ---
# name: test_info_with_errors[side_effect0] # name: test_info_with_errors[side_effect0]
dict({ dict({
'error': dict({
'code': 'home_assistant_error',
'message': 'Boom!',
}),
'id': 1, 'id': 1,
'success': False, 'result': dict({
'agent_errors': dict({
'domain.test': 'Oops',
}),
'backups': list([
dict({
'addons': list([
dict({
'name': 'Test',
'slug': 'test',
'version': '1.0.0',
}),
]),
'agents': dict({
'backup.local': dict({
'protected': False,
'size': 0,
}),
}),
'backup_id': 'abc123',
'database_included': True,
'date': '1970-01-01T00:00:00.000Z',
'extra_metadata': dict({
'instance_id': 'our_uuid',
'with_automatic_settings': True,
}),
'failed_agent_ids': list([
]),
'folders': list([
'media',
'share',
]),
'homeassistant_included': True,
'homeassistant_version': '2024.12.0',
'name': 'Test',
'with_automatic_settings': True,
}),
]),
'last_attempted_automatic_backup': None,
'last_completed_automatic_backup': None,
'last_non_idle_event': None,
'next_automatic_backup': None,
'next_automatic_backup_additional': False,
'state': 'idle',
}),
'success': True,
'type': 'result',
})
# ---
# name: test_info_with_errors[side_effect1]
dict({
'id': 1,
'result': dict({
'agent_errors': dict({
'domain.test': 'Boom!',
}),
'backups': list([
dict({
'addons': list([
dict({
'name': 'Test',
'slug': 'test',
'version': '1.0.0',
}),
]),
'agents': dict({
'backup.local': dict({
'protected': False,
'size': 0,
}),
}),
'backup_id': 'abc123',
'database_included': True,
'date': '1970-01-01T00:00:00.000Z',
'extra_metadata': dict({
'instance_id': 'our_uuid',
'with_automatic_settings': True,
}),
'failed_agent_ids': list([
]),
'folders': list([
'media',
'share',
]),
'homeassistant_included': True,
'homeassistant_version': '2024.12.0',
'name': 'Test',
'with_automatic_settings': True,
}),
]),
'last_attempted_automatic_backup': None,
'last_completed_automatic_backup': None,
'last_non_idle_event': None,
'next_automatic_backup': None,
'next_automatic_backup_additional': False,
'state': 'idle',
}),
'success': True,
'type': 'result', 'type': 'result',
}) })
# --- # ---

View File

@ -148,7 +148,8 @@ async def test_info(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"side_effect", [HomeAssistantError("Boom!"), BackupAgentUnreachableError] "side_effect",
[Exception("Oops"), HomeAssistantError("Boom!"), BackupAgentUnreachableError],
) )
async def test_info_with_errors( async def test_info_with_errors(
hass: HomeAssistant, hass: HomeAssistant,
@ -209,7 +210,8 @@ async def test_details(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"side_effect", [HomeAssistantError("Boom!"), BackupAgentUnreachableError] "side_effect",
[Exception("Oops"), HomeAssistantError("Boom!"), BackupAgentUnreachableError],
) )
async def test_details_with_errors( async def test_details_with_errors(
hass: HomeAssistant, hass: HomeAssistant,

View File

@ -661,8 +661,8 @@ async def test_agent_get_backup(
( (
SupervisorBadRequestError("blah"), SupervisorBadRequestError("blah"),
{ {
"success": False, "success": True,
"error": {"code": "unknown_error", "message": "Unknown error"}, "result": {"agent_errors": {"hassio.local": "blah"}, "backup": None},
}, },
), ),
( (
@ -733,8 +733,8 @@ async def test_agent_delete_backup(
( (
SupervisorBadRequestError("blah"), SupervisorBadRequestError("blah"),
{ {
"success": False, "success": True,
"error": {"code": "unknown_error", "message": "Unknown error"}, "result": {"agent_errors": {"hassio.local": "blah"}},
}, },
), ),
( (