Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Docker config from Supervisor backup #5605

Merged
merged 3 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 0 additions & 56 deletions supervisor/backups/backup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Representation of a backup file."""

import asyncio
from base64 import b64decode, b64encode
from collections import defaultdict
from collections.abc import AsyncGenerator, Awaitable
from contextlib import asynccontextmanager
Expand All @@ -20,7 +19,6 @@

from awesomeversion import AwesomeVersion, AwesomeVersionCompareException
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from securetar import SecureTarFile, atomic_contents_add, secure_path
import voluptuous as vol
Expand All @@ -38,16 +36,13 @@
ATTR_FOLDERS,
ATTR_HOMEASSISTANT,
ATTR_NAME,
ATTR_PASSWORD,
ATTR_PATH,
ATTR_PROTECTED,
ATTR_REGISTRIES,
ATTR_REPOSITORIES,
ATTR_SIZE,
ATTR_SLUG,
ATTR_SUPERVISOR_VERSION,
ATTR_TYPE,
ATTR_USERNAME,
ATTR_VERSION,
CRYPTO_AES128,
)
Expand Down Expand Up @@ -371,28 +366,6 @@ def _init_password(self, password: str) -> None:
backend=default_backend(),
)

def _encrypt_data(self, data: str) -> str:
"""Make data secure."""
if not self._key or data is None:
return data

encrypt = self._aes.encryptor()
padder = padding.PKCS7(128).padder()

data = padder.update(data.encode()) + padder.finalize()
return b64encode(encrypt.update(data)).decode()

def _decrypt_data(self, data: str) -> str:
"""Make data readable."""
if not self._key or data is None:
return data

decrypt = self._aes.decryptor()
padder = padding.PKCS7(128).unpadder()

data = padder.update(decrypt.update(b64decode(data))) + padder.finalize()
return data.decode()

async def validate_password(self, location: str | None) -> bool:
"""Validate backup password.

Expand Down Expand Up @@ -899,32 +872,3 @@ def restore_repositories(self, replace: bool = False) -> Awaitable[None]:
return self.sys_store.update_repositories(
self.repositories, add_with_errors=True, replace=replace
)

def store_dockerconfig(self):
"""Store the configuration for Docker."""
self.docker = {
ATTR_REGISTRIES: {
registry: {
ATTR_USERNAME: credentials[ATTR_USERNAME],
ATTR_PASSWORD: self._encrypt_data(credentials[ATTR_PASSWORD]),
}
for registry, credentials in self.sys_docker.config.registries.items()
}
}

def restore_dockerconfig(self, replace: bool = False):
"""Restore the configuration for Docker."""
if replace:
self.sys_docker.config.registries.clear()

if ATTR_REGISTRIES in self.docker:
self.sys_docker.config.registries.update(
{
registry: {
ATTR_USERNAME: credentials[ATTR_USERNAME],
ATTR_PASSWORD: self._decrypt_data(credentials[ATTR_PASSWORD]),
}
for registry, credentials in self.docker[ATTR_REGISTRIES].items()
}
)
self.sys_docker.config.save_data()
2 changes: 0 additions & 2 deletions supervisor/backups/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class BackupJobStage(StrEnum):

ADDON_REPOSITORIES = "addon_repositories"
ADDONS = "addons"
DOCKER_CONFIG = "docker_config"
FINISHING_FILE = "finishing_file"
FOLDERS = "folders"
HOME_ASSISTANT = "home_assistant"
Expand All @@ -39,7 +38,6 @@ class RestoreJobStage(StrEnum):
ADDONS = "addons"
AWAIT_ADDON_RESTARTS = "await_addon_restarts"
AWAIT_HOME_ASSISTANT_RESTART = "await_home_assistant_restart"
DOCKER_CONFIG = "docker_config"
FOLDERS = "folders"
HOME_ASSISTANT = "home_assistant"
REMOVE_DELTA_ADDONS = "remove_delta_addons"
6 changes: 0 additions & 6 deletions supervisor/backups/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,6 @@ def _create_backup(

self._change_stage(BackupJobStage.ADDON_REPOSITORIES, backup)
backup.store_repositories()
self._change_stage(BackupJobStage.DOCKER_CONFIG, backup)
backup.store_dockerconfig()

return backup

Expand Down Expand Up @@ -655,10 +653,6 @@ async def _do_restore(
try:
task_hass: asyncio.Task | None = None
async with backup.open(location):
# Restore docker config
self._change_stage(RestoreJobStage.DOCKER_CONFIG, backup)
backup.restore_dockerconfig(replace)

# Process folders
if folder_list:
self._change_stage(RestoreJobStage.FOLDERS, backup)
Expand Down
34 changes: 2 additions & 32 deletions tests/backups/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ async def test_do_backup_full(coresys: CoreSys, backup_mock, install_addon_ssh):

backup_instance.store_homeassistant.assert_called_once()
backup_instance.store_repositories.assert_called_once()
backup_instance.store_dockerconfig.assert_called_once()

backup_instance.store_addons.assert_called_once()
assert install_addon_ssh in backup_instance.store_addons.call_args[0][0]
Expand Down Expand Up @@ -115,7 +114,6 @@ async def test_do_backup_full_uncompressed(

backup_instance.store_homeassistant.assert_called_once()
backup_instance.store_repositories.assert_called_once()
backup_instance.store_dockerconfig.assert_called_once()

backup_instance.store_addons.assert_called_once()
assert install_addon_ssh in backup_instance.store_addons.call_args[0][0]
Expand Down Expand Up @@ -146,7 +144,6 @@ async def test_do_backup_partial_minimal(

backup_instance.store_homeassistant.assert_not_called()
backup_instance.store_repositories.assert_called_once()
backup_instance.store_dockerconfig.assert_called_once()

backup_instance.store_addons.assert_not_called()

Expand Down Expand Up @@ -176,7 +173,6 @@ async def test_do_backup_partial_minimal_uncompressed(

backup_instance.store_homeassistant.assert_not_called()
backup_instance.store_repositories.assert_called_once()
backup_instance.store_dockerconfig.assert_called_once()

backup_instance.store_addons.assert_not_called()

Expand Down Expand Up @@ -208,7 +204,6 @@ async def test_do_backup_partial_maximal(

backup_instance.store_homeassistant.assert_called_once()
backup_instance.store_repositories.assert_called_once()
backup_instance.store_dockerconfig.assert_called_once()

backup_instance.store_addons.assert_called_once()
assert install_addon_ssh in backup_instance.store_addons.call_args[0][0]
Expand Down Expand Up @@ -240,7 +235,6 @@ async def test_do_restore_full(coresys: CoreSys, full_backup_mock, install_addon

backup_instance.restore_homeassistant.assert_called_once()
backup_instance.restore_repositories.assert_called_once()
backup_instance.restore_dockerconfig.assert_called_once()

backup_instance.restore_addons.assert_called_once()
install_addon_ssh.uninstall.assert_not_called()
Expand Down Expand Up @@ -273,7 +267,6 @@ async def test_do_restore_full_different_addon(

backup_instance.restore_homeassistant.assert_called_once()
backup_instance.restore_repositories.assert_called_once()
backup_instance.restore_dockerconfig.assert_called_once()

backup_instance.restore_addons.assert_called_once()
install_addon_ssh.uninstall.assert_called_once()
Expand All @@ -300,7 +293,6 @@ async def test_do_restore_partial_minimal(

backup_instance.restore_homeassistant.assert_not_called()
backup_instance.restore_repositories.assert_not_called()
backup_instance.restore_dockerconfig.assert_called_once()

backup_instance.restore_addons.assert_not_called()

Expand Down Expand Up @@ -329,7 +321,6 @@ async def test_do_restore_partial_maximal(coresys: CoreSys, partial_backup_mock)

backup_instance.restore_homeassistant.assert_called_once()
backup_instance.restore_repositories.assert_called_once()
backup_instance.restore_dockerconfig.assert_called_once()

backup_instance.restore_addons.assert_called_once()

Expand Down Expand Up @@ -431,12 +422,12 @@ async def test_restore_error(

backup_instance = full_backup_mock.return_value
backup_instance.protected = False
backup_instance.restore_dockerconfig.side_effect = BackupError()
backup_instance.restore_homeassistant.side_effect = BackupError()
with pytest.raises(BackupError):
await coresys.backups.do_restore_full(backup_instance)
capture_exception.assert_not_called()

backup_instance.restore_dockerconfig.side_effect = (err := DockerError())
backup_instance.restore_homeassistant.side_effect = (err := DockerError())
with pytest.raises(BackupError):
await coresys.backups.do_restore_full(backup_instance)
capture_exception.assert_called_once_with(err)
Expand Down Expand Up @@ -1129,9 +1120,6 @@ async def test_backup_progress(
_make_backup_message_for_assert(
reference=full_backup.slug, stage="addon_repositories"
),
_make_backup_message_for_assert(
reference=full_backup.slug, stage="docker_config"
),
_make_backup_message_for_assert(
reference=full_backup.slug, stage="home_assistant"
),
Expand Down Expand Up @@ -1173,11 +1161,6 @@ async def test_backup_progress(
reference=partial_backup.slug,
stage="addon_repositories",
),
_make_backup_message_for_assert(
action="partial_backup",
reference=partial_backup.slug,
stage="docker_config",
),
_make_backup_message_for_assert(
action="partial_backup", reference=partial_backup.slug, stage="addons"
),
Expand Down Expand Up @@ -1244,9 +1227,6 @@ async def test_restore_progress(
_make_backup_message_for_assert(
action="full_restore", reference=full_backup.slug, stage=None
),
_make_backup_message_for_assert(
action="full_restore", reference=full_backup.slug, stage="docker_config"
),
_make_backup_message_for_assert(
action="full_restore", reference=full_backup.slug, stage="folders"
),
Expand Down Expand Up @@ -1311,11 +1291,6 @@ async def test_restore_progress(
reference=folders_backup.slug,
stage=None,
),
_make_backup_message_for_assert(
action="partial_restore",
reference=folders_backup.slug,
stage="docker_config",
),
_make_backup_message_for_assert(
action="partial_restore",
reference=folders_backup.slug,
Expand Down Expand Up @@ -1357,11 +1332,6 @@ async def test_restore_progress(
reference=addon_backup.slug,
stage=None,
),
_make_backup_message_for_assert(
action="partial_restore",
reference=addon_backup.slug,
stage="docker_config",
),
_make_backup_message_for_assert(
action="partial_restore",
reference=addon_backup.slug,
Expand Down
Loading