mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-12-24 12:29:08 +00:00
Report stage with error in jobs (#5784)
* Report stage with error in jobs * Copy doesn't lose track of the successful copies * Add stage to errors in api output test * revert unneessary change to import * Add tests for a bit more coverage of copy_additional_locations
This commit is contained in:
@@ -394,7 +394,11 @@ async def test_api_backup_errors(
|
||||
assert job["child_jobs"][1]["child_jobs"][0]["name"] == "backup_addon_save"
|
||||
assert job["child_jobs"][1]["child_jobs"][0]["reference"] == "local_ssh"
|
||||
assert job["child_jobs"][1]["child_jobs"][0]["errors"] == [
|
||||
{"type": "BackupError", "message": "Can't create backup for local_ssh"}
|
||||
{
|
||||
"type": "BackupError",
|
||||
"message": "Can't create backup for local_ssh",
|
||||
"stage": None,
|
||||
}
|
||||
]
|
||||
assert job["child_jobs"][2]["name"] == "backup_store_folders"
|
||||
assert job["child_jobs"][2]["reference"] == slug
|
||||
@@ -425,11 +429,21 @@ async def test_api_backup_errors(
|
||||
|
||||
assert job["name"] == f"backup_manager_{backup_type}_backup"
|
||||
assert job["done"] is True
|
||||
assert job["errors"] == (
|
||||
err := [{"type": "HomeAssistantBackupError", "message": "Backup error"}]
|
||||
)
|
||||
assert job["errors"] == [
|
||||
{
|
||||
"type": "HomeAssistantBackupError",
|
||||
"message": "Backup error",
|
||||
"stage": "home_assistant",
|
||||
}
|
||||
]
|
||||
assert job["child_jobs"][0]["name"] == "backup_store_homeassistant"
|
||||
assert job["child_jobs"][0]["errors"] == err
|
||||
assert job["child_jobs"][0]["errors"] == [
|
||||
{
|
||||
"type": "HomeAssistantBackupError",
|
||||
"message": "Backup error",
|
||||
"stage": None,
|
||||
}
|
||||
]
|
||||
assert len(job["child_jobs"]) == 1
|
||||
|
||||
|
||||
@@ -625,13 +639,20 @@ async def test_upload_download(
|
||||
|
||||
@pytest.mark.usefixtures("path_extern", "tmp_supervisor_data")
|
||||
@pytest.mark.parametrize(
|
||||
("backup_type", "inputs"), [("full", {}), ("partial", {"folders": ["ssl"]})]
|
||||
("backup_type", "inputs", "locations"),
|
||||
[
|
||||
("full", {}, [None, ".cloud_backup"]),
|
||||
("full", {}, [".cloud_backup", None]),
|
||||
("partial", {"folders": ["ssl"]}, [None, ".cloud_backup"]),
|
||||
("partial", {"folders": ["ssl"]}, [".cloud_backup", None]),
|
||||
],
|
||||
)
|
||||
async def test_backup_to_multiple_locations(
|
||||
api_client: TestClient,
|
||||
coresys: CoreSys,
|
||||
backup_type: str,
|
||||
inputs: dict[str, Any],
|
||||
locations: list[str | None],
|
||||
):
|
||||
"""Test making a backup to multiple locations."""
|
||||
await coresys.core.set_state(CoreState.RUNNING)
|
||||
@@ -639,8 +660,7 @@ async def test_backup_to_multiple_locations(
|
||||
|
||||
resp = await api_client.post(
|
||||
f"/backups/new/{backup_type}",
|
||||
json={"name": "Multiple locations test", "location": [None, ".cloud_backup"]}
|
||||
| inputs,
|
||||
json={"name": "Multiple locations test", "location": locations} | inputs,
|
||||
)
|
||||
assert resp.status == 200
|
||||
result = await resp.json()
|
||||
@@ -658,6 +678,56 @@ async def test_backup_to_multiple_locations(
|
||||
assert coresys.backups.get(slug).location is None
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("path_extern", "tmp_supervisor_data")
|
||||
@pytest.mark.parametrize(
|
||||
("backup_type", "inputs"), [("full", {}), ("partial", {"folders": ["ssl"]})]
|
||||
)
|
||||
async def test_backup_to_multiple_locations_error_on_copy(
|
||||
api_client: TestClient,
|
||||
coresys: CoreSys,
|
||||
backup_type: str,
|
||||
inputs: dict[str, Any],
|
||||
):
|
||||
"""Test making a backup to multiple locations that fails during copy stage."""
|
||||
await coresys.core.set_state(CoreState.RUNNING)
|
||||
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
||||
|
||||
with patch("supervisor.backups.manager.copy", side_effect=OSError):
|
||||
resp = await api_client.post(
|
||||
f"/backups/new/{backup_type}",
|
||||
json={
|
||||
"name": "Multiple locations test",
|
||||
"location": [None, ".cloud_backup"],
|
||||
}
|
||||
| inputs,
|
||||
)
|
||||
assert resp.status == 200
|
||||
result = await resp.json()
|
||||
assert result["result"] == "ok"
|
||||
slug = result["data"]["slug"]
|
||||
|
||||
orig_backup = coresys.config.path_backup / f"{slug}.tar"
|
||||
assert await coresys.run_in_executor(orig_backup.exists)
|
||||
assert coresys.backups.get(slug).all_locations == {
|
||||
None: {"path": orig_backup, "protected": False, "size_bytes": 10240},
|
||||
}
|
||||
assert coresys.backups.get(slug).location is None
|
||||
|
||||
resp = await api_client.get("/jobs/info")
|
||||
assert resp.status == 200
|
||||
result = await resp.json()
|
||||
assert result["data"]["jobs"][0]["name"] == f"backup_manager_{backup_type}_backup"
|
||||
assert result["data"]["jobs"][0]["reference"] == slug
|
||||
assert result["data"]["jobs"][0]["done"] is True
|
||||
assert result["data"]["jobs"][0]["errors"] == [
|
||||
{
|
||||
"type": "BackupError",
|
||||
"message": "Could not copy backup to .cloud_backup due to: ",
|
||||
"stage": "copy_additional_locations",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("backup_type", "inputs"), [("full", {}), ("partial", {"folders": ["ssl"]})]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user