mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-17 22:26:30 +00:00
Use full match in homeassistant backup excludes (#5597)
This commit is contained in:
parent
7f39538231
commit
4c04f364a3
@ -60,12 +60,15 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
HOMEASSISTANT_BACKUP_EXCLUDE = [
|
HOMEASSISTANT_BACKUP_EXCLUDE = [
|
||||||
|
"**/__pycache__/*",
|
||||||
|
"**/.DS_Store",
|
||||||
"*.db-shm",
|
"*.db-shm",
|
||||||
"*.corrupt.*",
|
"*.corrupt.*",
|
||||||
"__pycache__/*",
|
|
||||||
"*.log",
|
|
||||||
"*.log.*",
|
"*.log.*",
|
||||||
|
"*.log",
|
||||||
"OZW_Log.txt",
|
"OZW_Log.txt",
|
||||||
|
"backups/*.tar",
|
||||||
|
"tmp_backups/*.tar",
|
||||||
"tts/*",
|
"tts/*",
|
||||||
]
|
]
|
||||||
HOMEASSISTANT_BACKUP_EXCLUDE_DATABASE = [
|
HOMEASSISTANT_BACKUP_EXCLUDE_DATABASE = [
|
||||||
@ -419,7 +422,7 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
|
|||||||
def is_excluded_by_filter(path: PurePath) -> bool:
|
def is_excluded_by_filter(path: PurePath) -> bool:
|
||||||
"""Filter to filter excludes."""
|
"""Filter to filter excludes."""
|
||||||
for exclude in excludes:
|
for exclude in excludes:
|
||||||
if not path.match(exclude):
|
if not path.full_match(f"data/{exclude}"):
|
||||||
continue
|
continue
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Ignoring %s because of %s", path, exclude
|
"Ignoring %s because of %s", path, exclude
|
||||||
|
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import errno
|
import errno
|
||||||
from pathlib import Path
|
import logging
|
||||||
|
from pathlib import Path, PurePath
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from pytest import LogCaptureFixture, raises
|
import pytest
|
||||||
|
|
||||||
|
from supervisor.backups.backup import Backup
|
||||||
|
from supervisor.backups.const import BackupType
|
||||||
from supervisor.const import CoreState
|
from supervisor.const import CoreState
|
||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.docker.interface import DockerInterface
|
from supervisor.docker.interface import DockerInterface
|
||||||
@ -14,15 +17,19 @@ from supervisor.exceptions import (
|
|||||||
HomeAssistantBackupError,
|
HomeAssistantBackupError,
|
||||||
HomeAssistantWSConnectionError,
|
HomeAssistantWSConnectionError,
|
||||||
)
|
)
|
||||||
|
from supervisor.homeassistant.module import HomeAssistant
|
||||||
from supervisor.homeassistant.secrets import HomeAssistantSecrets
|
from supervisor.homeassistant.secrets import HomeAssistantSecrets
|
||||||
from supervisor.homeassistant.websocket import HomeAssistantWebSocket
|
from supervisor.homeassistant.websocket import HomeAssistantWebSocket
|
||||||
|
from supervisor.utils.dt import utcnow
|
||||||
|
|
||||||
|
|
||||||
async def test_load(
|
async def test_load(
|
||||||
coresys: CoreSys, tmp_supervisor_data: Path, ha_ws_client: AsyncMock
|
coresys: CoreSys, tmp_supervisor_data: Path, ha_ws_client: AsyncMock
|
||||||
):
|
):
|
||||||
"""Test homeassistant module load."""
|
"""Test homeassistant module load."""
|
||||||
with open(tmp_supervisor_data / "homeassistant" / "secrets.yaml", "w") as secrets:
|
with open(
|
||||||
|
tmp_supervisor_data / "homeassistant" / "secrets.yaml", "w", encoding="utf-8"
|
||||||
|
) as secrets:
|
||||||
secrets.write("hello: world\n")
|
secrets.write("hello: world\n")
|
||||||
|
|
||||||
# Unwrap read_secrets to prevent throttling between tests
|
# Unwrap read_secrets to prevent throttling between tests
|
||||||
@ -32,7 +39,7 @@ async def test_load(
|
|||||||
patch.object(
|
patch.object(
|
||||||
HomeAssistantSecrets,
|
HomeAssistantSecrets,
|
||||||
"_read_secrets",
|
"_read_secrets",
|
||||||
new=HomeAssistantSecrets._read_secrets.__wrapped__,
|
new=HomeAssistantSecrets._read_secrets.__wrapped__, # pylint: disable=protected-access,no-member
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
await coresys.homeassistant.load()
|
await coresys.homeassistant.load()
|
||||||
@ -59,7 +66,7 @@ async def test_get_users_none(coresys: CoreSys, ha_ws_client: AsyncMock):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_write_pulse_error(coresys: CoreSys, caplog: LogCaptureFixture):
|
def test_write_pulse_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):
|
||||||
"""Test errors writing pulse config."""
|
"""Test errors writing pulse config."""
|
||||||
with patch(
|
with patch(
|
||||||
"supervisor.homeassistant.module.Path.write_text",
|
"supervisor.homeassistant.module.Path.write_text",
|
||||||
@ -87,7 +94,7 @@ async def test_begin_backup_ws_error(coresys: CoreSys):
|
|||||||
)
|
)
|
||||||
with (
|
with (
|
||||||
patch.object(HomeAssistantWebSocket, "_can_send", return_value=True),
|
patch.object(HomeAssistantWebSocket, "_can_send", return_value=True),
|
||||||
raises(
|
pytest.raises(
|
||||||
HomeAssistantBackupError,
|
HomeAssistantBackupError,
|
||||||
match="Preparing backup of Home Assistant Core failed. Check HA Core logs.",
|
match="Preparing backup of Home Assistant Core failed. Check HA Core logs.",
|
||||||
),
|
),
|
||||||
@ -95,7 +102,7 @@ async def test_begin_backup_ws_error(coresys: CoreSys):
|
|||||||
await coresys.homeassistant.begin_backup()
|
await coresys.homeassistant.begin_backup()
|
||||||
|
|
||||||
|
|
||||||
async def test_end_backup_ws_error(coresys: CoreSys, caplog: LogCaptureFixture):
|
async def test_end_backup_ws_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):
|
||||||
"""Test WS error when ending backup."""
|
"""Test WS error when ending backup."""
|
||||||
# pylint: disable-next=protected-access
|
# pylint: disable-next=protected-access
|
||||||
coresys.homeassistant.websocket._client.async_send_command.side_effect = (
|
coresys.homeassistant.websocket._client.async_send_command.side_effect = (
|
||||||
@ -108,3 +115,67 @@ async def test_end_backup_ws_error(coresys: CoreSys, caplog: LogCaptureFixture):
|
|||||||
"Error resuming normal operations after backup of Home Assistant Core. Check HA Core logs."
|
"Error resuming normal operations after backup of Home Assistant Core. Check HA Core logs."
|
||||||
in caplog.text
|
in caplog.text
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("filename", "exclude_db", "expect_excluded", "subfolder"),
|
||||||
|
[
|
||||||
|
("home-assistant.log", False, True, None),
|
||||||
|
("home-assistant.log.1", False, True, None),
|
||||||
|
("home-assistant.log.fault", False, True, None),
|
||||||
|
("home-assistant.log", False, False, "subfolder"),
|
||||||
|
("OZW_Log.txt", False, True, None),
|
||||||
|
("OZW_Log.txt", False, False, "subfolder"),
|
||||||
|
("home-assistant_v2.db-shm", False, True, None),
|
||||||
|
("home-assistant_v2.db-shm", False, False, "subfolder"),
|
||||||
|
("home-assistant_v2.db", False, False, None),
|
||||||
|
("home-assistant_v2.db", True, True, None),
|
||||||
|
("home-assistant_v2.db", True, False, "subfolder"),
|
||||||
|
("home-assistant_v2.db-wal", False, False, None),
|
||||||
|
("home-assistant_v2.db-wal", True, True, None),
|
||||||
|
("home-assistant_v2.db-wal", True, False, "subfolder"),
|
||||||
|
("test.tar", False, True, "backups"),
|
||||||
|
("test.tar", False, False, "subfolder/backups"),
|
||||||
|
("test.tar", False, True, "tmp_backups"),
|
||||||
|
("test.tar", False, False, "subfolder/tmp_backups"),
|
||||||
|
("test", False, True, "tts"),
|
||||||
|
("test", False, False, "subfolder/tts"),
|
||||||
|
("test.cpython-312.pyc", False, True, "__pycache__"),
|
||||||
|
("test.cpython-312.pyc", False, True, "subfolder/__pycache__"),
|
||||||
|
(".DS_Store", False, True, None),
|
||||||
|
(".DS_Store", False, True, "subfolder"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.usefixtures("tmp_supervisor_data")
|
||||||
|
async def test_backup_excludes(
|
||||||
|
coresys: CoreSys,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
filename: str,
|
||||||
|
exclude_db: bool,
|
||||||
|
expect_excluded: bool,
|
||||||
|
subfolder: str | None,
|
||||||
|
):
|
||||||
|
"""Test excludes in backup."""
|
||||||
|
parent = coresys.config.path_homeassistant
|
||||||
|
if subfolder:
|
||||||
|
test_path = PurePath(subfolder, filename)
|
||||||
|
parent = coresys.config.path_homeassistant / subfolder
|
||||||
|
parent.mkdir(parents=True)
|
||||||
|
else:
|
||||||
|
test_path = PurePath(filename)
|
||||||
|
|
||||||
|
(parent / filename).touch()
|
||||||
|
|
||||||
|
backup = Backup(coresys, coresys.config.path_backup / "test.tar", "test", None)
|
||||||
|
backup.new("test", utcnow().isoformat(), BackupType.PARTIAL)
|
||||||
|
async with backup.create():
|
||||||
|
with (
|
||||||
|
patch.object(HomeAssistant, "begin_backup"),
|
||||||
|
patch.object(HomeAssistant, "end_backup"),
|
||||||
|
caplog.at_level(logging.DEBUG, logger="supervisor.homeassistant.module"),
|
||||||
|
):
|
||||||
|
await backup.store_homeassistant(exclude_database=exclude_db)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
f"Ignoring data/{test_path.as_posix()} because of " in caplog.text
|
||||||
|
) is expect_excluded
|
||||||
|
Loading…
x
Reference in New Issue
Block a user