mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-05-09 12:28:38 +00:00

* Notify HA Core when backup is being executed Notify Home Assistant Core using the Websocket API when the Home Assistant config directory is about to get backed up. This makes sure the Core can prepare the SQLite database (if active) so it safe to make a backup. * Only close WebSocket connection on connection errors Let regular WebSocket errors bubble to the caller so they can be handled explicitly. * Add version restriction to backup/start/end WS commands * Restore Home Assistant metadata when Home Assistant is selected
211 lines
7.9 KiB
Python
211 lines
7.9 KiB
Python
"""Test BackupManager class."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
from supervisor.backups.const import BackupType
|
|
from supervisor.backups.manager import BackupManager
|
|
from supervisor.const import FOLDER_HOMEASSISTANT, FOLDER_SHARE, CoreState
|
|
from supervisor.coresys import CoreSys
|
|
|
|
from tests.const import TEST_ADDON_SLUG
|
|
|
|
|
|
async def test_do_backup_full(coresys: CoreSys, backup_mock, install_addon_ssh):
|
|
"""Test creating Backup."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
# backup_mock fixture causes Backup() to be a MagicMock
|
|
backup_instance: MagicMock = await manager.do_backup_full()
|
|
|
|
# Check Backup has been created without password
|
|
assert backup_instance.new.call_args[0][3] == BackupType.FULL
|
|
assert backup_instance.new.call_args[0][4] is None
|
|
|
|
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]
|
|
|
|
backup_instance.store_folders.assert_called_once()
|
|
assert len(backup_instance.store_folders.call_args[0][0]) == 4
|
|
backup_instance.store_homeassistant_config_dir.assert_called_once()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|
|
|
|
|
|
async def test_do_backup_partial_minimal(
|
|
coresys: CoreSys, backup_mock, install_addon_ssh
|
|
):
|
|
"""Test creating minimal partial Backup."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
# backup_mock fixture causes Backup() to be a MagicMock
|
|
backup_instance: MagicMock = await manager.do_backup_partial(homeassistant=False)
|
|
|
|
# Check Backup has been created without password
|
|
assert backup_instance.new.call_args[0][3] == BackupType.PARTIAL
|
|
assert backup_instance.new.call_args[0][4] is None
|
|
|
|
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()
|
|
|
|
backup_instance.store_folders.assert_not_called()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|
|
|
|
|
|
async def test_do_backup_partial_maximal(
|
|
coresys: CoreSys, backup_mock, install_addon_ssh
|
|
):
|
|
"""Test creating maximal partial Backup."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
# backup_mock fixture causes Backup() to be a MagicMock
|
|
backup_instance: MagicMock = await manager.do_backup_partial(
|
|
addons=[TEST_ADDON_SLUG],
|
|
folders=[FOLDER_SHARE, FOLDER_HOMEASSISTANT],
|
|
homeassistant=True,
|
|
)
|
|
|
|
# Check Backup has been created without password
|
|
assert backup_instance.new.call_args[0][3] == BackupType.PARTIAL
|
|
assert backup_instance.new.call_args[0][4] is None
|
|
|
|
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]
|
|
|
|
backup_instance.store_folders.assert_called_once()
|
|
assert len(backup_instance.store_folders.call_args[0][0]) == 1
|
|
backup_instance.store_homeassistant_config_dir.assert_called_once()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|
|
|
|
|
|
async def test_do_restore_full(coresys: CoreSys, full_backup_mock, install_addon_ssh):
|
|
"""Test restoring full Backup."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
coresys.homeassistant.core.start = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.stop = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.update = AsyncMock(return_value=None)
|
|
install_addon_ssh.uninstall = AsyncMock(return_value=None)
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
backup_instance = full_backup_mock.return_value
|
|
await manager.do_restore_full(backup_instance)
|
|
|
|
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()
|
|
|
|
backup_instance.restore_folders.assert_called_once()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|
|
|
|
|
|
async def test_do_restore_full_different_addon(
|
|
coresys: CoreSys, full_backup_mock, install_addon_ssh
|
|
):
|
|
"""Test restoring full Backup with different addons than installed."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
coresys.homeassistant.core.start = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.stop = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.update = AsyncMock(return_value=None)
|
|
install_addon_ssh.uninstall = AsyncMock(return_value=None)
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
backup_instance = full_backup_mock.return_value
|
|
backup_instance.addon_list = ["differentslug"]
|
|
await manager.do_restore_full(backup_instance)
|
|
|
|
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()
|
|
|
|
backup_instance.restore_folders.assert_called_once()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|
|
|
|
|
|
async def test_do_restore_partial_minimal(
|
|
coresys: CoreSys, partial_backup_mock, install_addon_ssh
|
|
):
|
|
"""Test restoring partial Backup minimal."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
coresys.homeassistant.core.start = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.stop = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.update = AsyncMock(return_value=None)
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
backup_instance = partial_backup_mock.return_value
|
|
await manager.do_restore_partial(backup_instance, homeassistant=False)
|
|
|
|
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()
|
|
|
|
backup_instance.restore_folders.assert_not_called()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|
|
|
|
|
|
async def test_do_restore_partial_maximal(coresys: CoreSys, partial_backup_mock):
|
|
"""Test restoring partial Backup minimal."""
|
|
coresys.core.state = CoreState.RUNNING
|
|
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
|
coresys.homeassistant.core.start = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.stop = AsyncMock(return_value=None)
|
|
coresys.homeassistant.core.update = AsyncMock(return_value=None)
|
|
|
|
manager = BackupManager(coresys)
|
|
|
|
backup_instance = partial_backup_mock.return_value
|
|
await manager.do_restore_partial(
|
|
backup_instance,
|
|
addons=[TEST_ADDON_SLUG],
|
|
folders=[FOLDER_SHARE, FOLDER_HOMEASSISTANT],
|
|
homeassistant=True,
|
|
)
|
|
|
|
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()
|
|
|
|
backup_instance.restore_folders.assert_called_once()
|
|
backup_instance.restore_homeassistant_config_dir.assert_called_once()
|
|
|
|
assert coresys.core.state == CoreState.RUNNING
|