mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-15 13:16:29 +00:00
Bump securetar from 2024.11.0 to 2025.1.3 (#5553)
* Bump securetar from 2024.11.0 to 2025.1.3 Bumps [securetar](https://github.com/pvizeli/securetar) from 2024.11.0 to 2025.1.3. - [Release notes](https://github.com/pvizeli/securetar/releases) - [Commits](https://github.com/pvizeli/securetar/compare/2024.11.0...2025.1.3) --- updated-dependencies: - dependency-name: securetar dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Use file_filter and add test for addon backup_exclude --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
This commit is contained in:
parent
52d5df6778
commit
463f196472
@ -20,7 +20,7 @@ pulsectl==24.12.0
|
||||
pyudev==0.24.3
|
||||
PyYAML==6.0.2
|
||||
requests==2.32.3
|
||||
securetar==2024.11.0
|
||||
securetar==2025.1.3
|
||||
sentry-sdk==2.20.0
|
||||
setuptools==75.8.0
|
||||
voluptuous==0.15.2
|
||||
|
@ -6,6 +6,7 @@ from contextlib import suppress
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
import errno
|
||||
from functools import partial
|
||||
from ipaddress import IPv4Address
|
||||
import logging
|
||||
from pathlib import Path, PurePath
|
||||
@ -1207,6 +1208,25 @@ class Addon(AddonModel):
|
||||
await self._backup_command(self.backup_post)
|
||||
return None
|
||||
|
||||
def _is_excluded_by_filter(
|
||||
self, origin_path: Path, arcname: str, item_arcpath: PurePath
|
||||
) -> bool:
|
||||
"""Filter out files from backup based on filters provided by addon developer.
|
||||
|
||||
This tests the dev provided filters against the full path of the file as
|
||||
Supervisor sees them using match. This is done for legacy reasons, testing
|
||||
against the relative path makes more sense and may be changed in the future.
|
||||
"""
|
||||
full_path = origin_path / item_arcpath.relative_to(arcname)
|
||||
|
||||
for exclude in self.backup_exclude:
|
||||
if not full_path.match(exclude):
|
||||
continue
|
||||
_LOGGER.debug("Ignoring %s because of %s", full_path, exclude)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@Job(
|
||||
name="addon_backup",
|
||||
limit=JobExecutionLimit.GROUP_ONCE,
|
||||
@ -1266,7 +1286,9 @@ class Addon(AddonModel):
|
||||
atomic_contents_add(
|
||||
backup,
|
||||
self.path_data,
|
||||
excludes=self.backup_exclude,
|
||||
file_filter=partial(
|
||||
self._is_excluded_by_filter, self.path_data, "data"
|
||||
),
|
||||
arcname="data",
|
||||
)
|
||||
|
||||
@ -1275,7 +1297,9 @@ class Addon(AddonModel):
|
||||
atomic_contents_add(
|
||||
backup,
|
||||
self.path_config,
|
||||
excludes=self.backup_exclude,
|
||||
file_filter=partial(
|
||||
self._is_excluded_by_filter, self.path_config, "config"
|
||||
),
|
||||
arcname="config",
|
||||
)
|
||||
|
||||
|
@ -11,7 +11,7 @@ from functools import cached_property
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from pathlib import Path, PurePath
|
||||
import tarfile
|
||||
from tarfile import TarFile
|
||||
from tempfile import TemporaryDirectory
|
||||
@ -640,6 +640,22 @@ class Backup(JobGroup):
|
||||
# Take backup
|
||||
_LOGGER.info("Backing up folder %s", name)
|
||||
|
||||
def is_excluded_by_filter(item_arcpath: PurePath) -> bool:
|
||||
"""Filter out bind mounts in folders being backed up."""
|
||||
full_path = origin_dir / item_arcpath.relative_to(".")
|
||||
|
||||
for bound in self.sys_mounts.bound_mounts:
|
||||
if full_path != bound.bind_mount.local_where:
|
||||
continue
|
||||
_LOGGER.debug(
|
||||
"Ignoring %s because of %s",
|
||||
full_path,
|
||||
bound.bind_mount.local_where.as_posix(),
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
with self._outer_secure_tarfile.create_inner_tar(
|
||||
f"./{tar_name}",
|
||||
gzip=self.compressed,
|
||||
@ -648,11 +664,7 @@ class Backup(JobGroup):
|
||||
atomic_contents_add(
|
||||
tar_file,
|
||||
origin_dir,
|
||||
excludes=[
|
||||
bound.bind_mount.local_where.as_posix()
|
||||
for bound in self.sys_mounts.bound_mounts
|
||||
if bound.bind_mount.local_where
|
||||
],
|
||||
file_filter=is_excluded_by_filter,
|
||||
arcname=".",
|
||||
)
|
||||
|
||||
|
@ -416,11 +416,23 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
|
||||
if exclude_database:
|
||||
excludes += HOMEASSISTANT_BACKUP_EXCLUDE_DATABASE
|
||||
|
||||
def is_excluded_by_filter(path: PurePath) -> bool:
|
||||
"""Filter to filter excludes."""
|
||||
for exclude in excludes:
|
||||
if not path.match(exclude):
|
||||
continue
|
||||
_LOGGER.debug(
|
||||
"Ignoring %s because of %s", path, exclude
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# Backup data
|
||||
atomic_contents_add(
|
||||
backup,
|
||||
self.sys_config.path_homeassistant,
|
||||
excludes=excludes,
|
||||
file_filter=is_excluded_by_filter,
|
||||
arcname="data",
|
||||
)
|
||||
|
||||
|
@ -2013,3 +2013,29 @@ async def test_backup_remove_one_location_of_multiple(coresys: CoreSys):
|
||||
assert not location_2.exists()
|
||||
assert coresys.backups.get("7fed74c8")
|
||||
assert backup.all_locations == {None: location_1}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("tmp_supervisor_data")
|
||||
async def test_addon_backup_excludes(coresys: CoreSys, install_addon_example: Addon):
|
||||
"""Test backup excludes option for addons."""
|
||||
coresys.core.state = CoreState.RUNNING
|
||||
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
||||
|
||||
install_addon_example.path_data.mkdir(parents=True)
|
||||
(test1 := install_addon_example.path_data / "test1").touch()
|
||||
(test_dir := install_addon_example.path_data / "test_dir").mkdir()
|
||||
(test2 := test_dir / "test2").touch()
|
||||
(test3 := test_dir / "test3").touch()
|
||||
|
||||
install_addon_example.data["backup_exclude"] = ["test1", "*/test2"]
|
||||
backup = await coresys.backups.do_backup_partial(addons=["local_example"])
|
||||
test1.unlink()
|
||||
test2.unlink()
|
||||
test3.unlink()
|
||||
test_dir.rmdir()
|
||||
|
||||
await coresys.backups.do_restore_partial(backup, addons=["local_example"])
|
||||
assert not test1.exists()
|
||||
assert not test2.exists()
|
||||
assert test_dir.is_dir()
|
||||
assert test3.exists()
|
||||
|
Loading…
x
Reference in New Issue
Block a user