Skip to content

Commit 4c04f36

Browse files
authored
Use full match in homeassistant backup excludes (#5597)
1 parent 7f39538 commit 4c04f36

File tree

2 files changed

+84
-10
lines changed

2 files changed

+84
-10
lines changed

supervisor/homeassistant/module.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,15 @@
6060

6161

6262
HOMEASSISTANT_BACKUP_EXCLUDE = [
63+
"**/__pycache__/*",
64+
"**/.DS_Store",
6365
"*.db-shm",
6466
"*.corrupt.*",
65-
"__pycache__/*",
66-
"*.log",
6767
"*.log.*",
68+
"*.log",
6869
"OZW_Log.txt",
70+
"backups/*.tar",
71+
"tmp_backups/*.tar",
6972
"tts/*",
7073
]
7174
HOMEASSISTANT_BACKUP_EXCLUDE_DATABASE = [
@@ -419,7 +422,7 @@ def _write_tarfile():
419422
def is_excluded_by_filter(path: PurePath) -> bool:
420423
"""Filter to filter excludes."""
421424
for exclude in excludes:
422-
if not path.match(exclude):
425+
if not path.full_match(f"data/{exclude}"):
423426
continue
424427
_LOGGER.debug(
425428
"Ignoring %s because of %s", path, exclude

tests/homeassistant/test_module.py

+78-7
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,34 @@
22

33
import asyncio
44
import errno
5-
from pathlib import Path
5+
import logging
6+
from pathlib import Path, PurePath
67
from unittest.mock import AsyncMock, patch
78

8-
from pytest import LogCaptureFixture, raises
9+
import pytest
910

11+
from supervisor.backups.backup import Backup
12+
from supervisor.backups.const import BackupType
1013
from supervisor.const import CoreState
1114
from supervisor.coresys import CoreSys
1215
from supervisor.docker.interface import DockerInterface
1316
from supervisor.exceptions import (
1417
HomeAssistantBackupError,
1518
HomeAssistantWSConnectionError,
1619
)
20+
from supervisor.homeassistant.module import HomeAssistant
1721
from supervisor.homeassistant.secrets import HomeAssistantSecrets
1822
from supervisor.homeassistant.websocket import HomeAssistantWebSocket
23+
from supervisor.utils.dt import utcnow
1924

2025

2126
async def test_load(
2227
coresys: CoreSys, tmp_supervisor_data: Path, ha_ws_client: AsyncMock
2328
):
2429
"""Test homeassistant module load."""
25-
with open(tmp_supervisor_data / "homeassistant" / "secrets.yaml", "w") as secrets:
30+
with open(
31+
tmp_supervisor_data / "homeassistant" / "secrets.yaml", "w", encoding="utf-8"
32+
) as secrets:
2633
secrets.write("hello: world\n")
2734

2835
# Unwrap read_secrets to prevent throttling between tests
@@ -32,7 +39,7 @@ async def test_load(
3239
patch.object(
3340
HomeAssistantSecrets,
3441
"_read_secrets",
35-
new=HomeAssistantSecrets._read_secrets.__wrapped__,
42+
new=HomeAssistantSecrets._read_secrets.__wrapped__, # pylint: disable=protected-access,no-member
3643
),
3744
):
3845
await coresys.homeassistant.load()
@@ -59,7 +66,7 @@ async def test_get_users_none(coresys: CoreSys, ha_ws_client: AsyncMock):
5966
)
6067

6168

62-
def test_write_pulse_error(coresys: CoreSys, caplog: LogCaptureFixture):
69+
def test_write_pulse_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):
6370
"""Test errors writing pulse config."""
6471
with patch(
6572
"supervisor.homeassistant.module.Path.write_text",
@@ -87,15 +94,15 @@ async def test_begin_backup_ws_error(coresys: CoreSys):
8794
)
8895
with (
8996
patch.object(HomeAssistantWebSocket, "_can_send", return_value=True),
90-
raises(
97+
pytest.raises(
9198
HomeAssistantBackupError,
9299
match="Preparing backup of Home Assistant Core failed. Check HA Core logs.",
93100
),
94101
):
95102
await coresys.homeassistant.begin_backup()
96103

97104

98-
async def test_end_backup_ws_error(coresys: CoreSys, caplog: LogCaptureFixture):
105+
async def test_end_backup_ws_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):
99106
"""Test WS error when ending backup."""
100107
# pylint: disable-next=protected-access
101108
coresys.homeassistant.websocket._client.async_send_command.side_effect = (
@@ -108,3 +115,67 @@ async def test_end_backup_ws_error(coresys: CoreSys, caplog: LogCaptureFixture):
108115
"Error resuming normal operations after backup of Home Assistant Core. Check HA Core logs."
109116
in caplog.text
110117
)
118+
119+
120+
@pytest.mark.parametrize(
121+
("filename", "exclude_db", "expect_excluded", "subfolder"),
122+
[
123+
("home-assistant.log", False, True, None),
124+
("home-assistant.log.1", False, True, None),
125+
("home-assistant.log.fault", False, True, None),
126+
("home-assistant.log", False, False, "subfolder"),
127+
("OZW_Log.txt", False, True, None),
128+
("OZW_Log.txt", False, False, "subfolder"),
129+
("home-assistant_v2.db-shm", False, True, None),
130+
("home-assistant_v2.db-shm", False, False, "subfolder"),
131+
("home-assistant_v2.db", False, False, None),
132+
("home-assistant_v2.db", True, True, None),
133+
("home-assistant_v2.db", True, False, "subfolder"),
134+
("home-assistant_v2.db-wal", False, False, None),
135+
("home-assistant_v2.db-wal", True, True, None),
136+
("home-assistant_v2.db-wal", True, False, "subfolder"),
137+
("test.tar", False, True, "backups"),
138+
("test.tar", False, False, "subfolder/backups"),
139+
("test.tar", False, True, "tmp_backups"),
140+
("test.tar", False, False, "subfolder/tmp_backups"),
141+
("test", False, True, "tts"),
142+
("test", False, False, "subfolder/tts"),
143+
("test.cpython-312.pyc", False, True, "__pycache__"),
144+
("test.cpython-312.pyc", False, True, "subfolder/__pycache__"),
145+
(".DS_Store", False, True, None),
146+
(".DS_Store", False, True, "subfolder"),
147+
],
148+
)
149+
@pytest.mark.usefixtures("tmp_supervisor_data")
150+
async def test_backup_excludes(
151+
coresys: CoreSys,
152+
caplog: pytest.LogCaptureFixture,
153+
filename: str,
154+
exclude_db: bool,
155+
expect_excluded: bool,
156+
subfolder: str | None,
157+
):
158+
"""Test excludes in backup."""
159+
parent = coresys.config.path_homeassistant
160+
if subfolder:
161+
test_path = PurePath(subfolder, filename)
162+
parent = coresys.config.path_homeassistant / subfolder
163+
parent.mkdir(parents=True)
164+
else:
165+
test_path = PurePath(filename)
166+
167+
(parent / filename).touch()
168+
169+
backup = Backup(coresys, coresys.config.path_backup / "test.tar", "test", None)
170+
backup.new("test", utcnow().isoformat(), BackupType.PARTIAL)
171+
async with backup.create():
172+
with (
173+
patch.object(HomeAssistant, "begin_backup"),
174+
patch.object(HomeAssistant, "end_backup"),
175+
caplog.at_level(logging.DEBUG, logger="supervisor.homeassistant.module"),
176+
):
177+
await backup.store_homeassistant(exclude_database=exclude_db)
178+
179+
assert (
180+
f"Ignoring data/{test_path.as_posix()} because of " in caplog.text
181+
) is expect_excluded

0 commit comments

Comments
 (0)