mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Don't allow setting backup retention to 0 days or copies (#138771)
* Don't allow setting backup retention to 0 days or copies * Add tests
This commit is contained in:
parent
46c604fcbe
commit
22c634e626
@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
||||
STORE_DELAY_SAVE = 30
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
STORAGE_VERSION_MINOR = 3
|
||||
STORAGE_VERSION_MINOR = 4
|
||||
|
||||
|
||||
class StoredBackupData(TypedDict):
|
||||
@ -60,6 +60,13 @@ class _BackupStore(Store[StoredBackupData]):
|
||||
else:
|
||||
data["config"]["schedule"]["days"] = [state]
|
||||
data["config"]["schedule"]["recurrence"] = "custom_days"
|
||||
if old_minor_version < 4:
|
||||
# Workaround for a bug in frontend which incorrectly set days to 0
|
||||
# instead of to None for unlimited retention.
|
||||
if data["config"]["retention"]["copies"] == 0:
|
||||
data["config"]["retention"]["copies"] = None
|
||||
if data["config"]["retention"]["days"] == 0:
|
||||
data["config"]["retention"]["days"] = None
|
||||
|
||||
# Note: We allow reading data with major version 2.
|
||||
# Reject if major version is higher than 2.
|
||||
|
@ -368,8 +368,10 @@ async def handle_config_info(
|
||||
),
|
||||
vol.Optional("retention"): vol.Schema(
|
||||
{
|
||||
vol.Optional("copies"): vol.Any(int, None),
|
||||
vol.Optional("days"): vol.Any(int, None),
|
||||
# Note: We can't use cv.positive_int because it allows 0 even
|
||||
# though 0 is not positive.
|
||||
vol.Optional("copies"): vol.Any(vol.All(int, vol.Range(min=1)), None),
|
||||
vol.Optional("days"): vol.Any(vol.All(int, vol.Range(min=1)), None),
|
||||
},
|
||||
),
|
||||
vol.Optional("schedule"): vol.Schema(
|
||||
|
@ -39,7 +39,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -84,11 +84,100 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
# name: test_store_migration[store_data1]
|
||||
dict({
|
||||
'data': dict({
|
||||
'backups': list([
|
||||
dict({
|
||||
'backup_id': 'abc123',
|
||||
'failed_agent_ids': list([
|
||||
'test.remote',
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
'config': dict({
|
||||
'agents': dict({
|
||||
}),
|
||||
'create_backup': dict({
|
||||
'agent_ids': list([
|
||||
]),
|
||||
'include_addons': None,
|
||||
'include_all_addons': False,
|
||||
'include_database': True,
|
||||
'include_folders': None,
|
||||
'name': None,
|
||||
'password': None,
|
||||
}),
|
||||
'last_attempted_automatic_backup': None,
|
||||
'last_completed_automatic_backup': None,
|
||||
'retention': dict({
|
||||
'copies': None,
|
||||
'days': None,
|
||||
}),
|
||||
'schedule': dict({
|
||||
'days': list([
|
||||
]),
|
||||
'recurrence': 'never',
|
||||
'state': 'never',
|
||||
'time': None,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
# name: test_store_migration[store_data1].1
|
||||
dict({
|
||||
'data': dict({
|
||||
'backups': list([
|
||||
dict({
|
||||
'backup_id': 'abc123',
|
||||
'failed_agent_ids': list([
|
||||
'test.remote',
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
'config': dict({
|
||||
'agents': dict({
|
||||
}),
|
||||
'create_backup': dict({
|
||||
'agent_ids': list([
|
||||
'test-agent',
|
||||
]),
|
||||
'include_addons': None,
|
||||
'include_all_addons': False,
|
||||
'include_database': True,
|
||||
'include_folders': None,
|
||||
'name': None,
|
||||
'password': None,
|
||||
}),
|
||||
'last_attempted_automatic_backup': None,
|
||||
'last_completed_automatic_backup': None,
|
||||
'retention': dict({
|
||||
'copies': None,
|
||||
'days': None,
|
||||
}),
|
||||
'schedule': dict({
|
||||
'days': list([
|
||||
]),
|
||||
'recurrence': 'never',
|
||||
'state': 'never',
|
||||
'time': None,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
# name: test_store_migration[store_data2]
|
||||
dict({
|
||||
'data': dict({
|
||||
'backups': list([
|
||||
@ -131,11 +220,11 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
# name: test_store_migration[store_data1].1
|
||||
# name: test_store_migration[store_data2].1
|
||||
dict({
|
||||
'data': dict({
|
||||
'backups': list([
|
||||
@ -179,7 +268,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
|
@ -686,7 +686,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -800,7 +800,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -914,7 +914,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1038,7 +1038,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1205,7 +1205,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1319,7 +1319,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1435,7 +1435,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1549,7 +1549,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1667,7 +1667,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1789,7 +1789,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -1903,7 +1903,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -2017,7 +2017,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -2131,7 +2131,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -2245,7 +2245,7 @@
|
||||
}),
|
||||
}),
|
||||
'key': 'backup',
|
||||
'minor_version': 3,
|
||||
'minor_version': 4,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@ -2323,6 +2323,154 @@
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_config_update_errors[command10]
|
||||
dict({
|
||||
'id': 1,
|
||||
'result': dict({
|
||||
'config': dict({
|
||||
'agents': dict({
|
||||
}),
|
||||
'create_backup': dict({
|
||||
'agent_ids': list([
|
||||
]),
|
||||
'include_addons': None,
|
||||
'include_all_addons': False,
|
||||
'include_database': True,
|
||||
'include_folders': None,
|
||||
'name': None,
|
||||
'password': None,
|
||||
}),
|
||||
'last_attempted_automatic_backup': None,
|
||||
'last_completed_automatic_backup': None,
|
||||
'next_automatic_backup': None,
|
||||
'next_automatic_backup_additional': False,
|
||||
'retention': dict({
|
||||
'copies': None,
|
||||
'days': None,
|
||||
}),
|
||||
'schedule': dict({
|
||||
'days': list([
|
||||
]),
|
||||
'recurrence': 'never',
|
||||
'time': None,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'success': True,
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_config_update_errors[command10].1
|
||||
dict({
|
||||
'id': 3,
|
||||
'result': dict({
|
||||
'config': dict({
|
||||
'agents': dict({
|
||||
}),
|
||||
'create_backup': dict({
|
||||
'agent_ids': list([
|
||||
]),
|
||||
'include_addons': None,
|
||||
'include_all_addons': False,
|
||||
'include_database': True,
|
||||
'include_folders': None,
|
||||
'name': None,
|
||||
'password': None,
|
||||
}),
|
||||
'last_attempted_automatic_backup': None,
|
||||
'last_completed_automatic_backup': None,
|
||||
'next_automatic_backup': None,
|
||||
'next_automatic_backup_additional': False,
|
||||
'retention': dict({
|
||||
'copies': None,
|
||||
'days': None,
|
||||
}),
|
||||
'schedule': dict({
|
||||
'days': list([
|
||||
]),
|
||||
'recurrence': 'never',
|
||||
'time': None,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'success': True,
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_config_update_errors[command11]
|
||||
dict({
|
||||
'id': 1,
|
||||
'result': dict({
|
||||
'config': dict({
|
||||
'agents': dict({
|
||||
}),
|
||||
'create_backup': dict({
|
||||
'agent_ids': list([
|
||||
]),
|
||||
'include_addons': None,
|
||||
'include_all_addons': False,
|
||||
'include_database': True,
|
||||
'include_folders': None,
|
||||
'name': None,
|
||||
'password': None,
|
||||
}),
|
||||
'last_attempted_automatic_backup': None,
|
||||
'last_completed_automatic_backup': None,
|
||||
'next_automatic_backup': None,
|
||||
'next_automatic_backup_additional': False,
|
||||
'retention': dict({
|
||||
'copies': None,
|
||||
'days': None,
|
||||
}),
|
||||
'schedule': dict({
|
||||
'days': list([
|
||||
]),
|
||||
'recurrence': 'never',
|
||||
'time': None,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'success': True,
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_config_update_errors[command11].1
|
||||
dict({
|
||||
'id': 3,
|
||||
'result': dict({
|
||||
'config': dict({
|
||||
'agents': dict({
|
||||
}),
|
||||
'create_backup': dict({
|
||||
'agent_ids': list([
|
||||
]),
|
||||
'include_addons': None,
|
||||
'include_all_addons': False,
|
||||
'include_database': True,
|
||||
'include_folders': None,
|
||||
'name': None,
|
||||
'password': None,
|
||||
}),
|
||||
'last_attempted_automatic_backup': None,
|
||||
'last_completed_automatic_backup': None,
|
||||
'next_automatic_backup': None,
|
||||
'next_automatic_backup_additional': False,
|
||||
'retention': dict({
|
||||
'copies': None,
|
||||
'days': None,
|
||||
}),
|
||||
'schedule': dict({
|
||||
'days': list([
|
||||
]),
|
||||
'recurrence': 'never',
|
||||
'time': None,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'success': True,
|
||||
'type': 'result',
|
||||
})
|
||||
# ---
|
||||
# name: test_config_update_errors[command1]
|
||||
dict({
|
||||
'id': 1,
|
||||
|
@ -57,6 +57,38 @@ def mock_delay_save() -> Generator[None]:
|
||||
"key": DOMAIN,
|
||||
"version": 1,
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"backups": [
|
||||
{
|
||||
"backup_id": "abc123",
|
||||
"failed_agent_ids": ["test.remote"],
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"create_backup": {
|
||||
"agent_ids": [],
|
||||
"include_addons": None,
|
||||
"include_all_addons": False,
|
||||
"include_database": True,
|
||||
"include_folders": None,
|
||||
"name": None,
|
||||
"password": None,
|
||||
},
|
||||
"last_attempted_automatic_backup": None,
|
||||
"last_completed_automatic_backup": None,
|
||||
"retention": {
|
||||
"copies": 0,
|
||||
"days": 0,
|
||||
},
|
||||
"schedule": {
|
||||
"state": "never",
|
||||
},
|
||||
},
|
||||
},
|
||||
"key": DOMAIN,
|
||||
"version": 1,
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"backups": [
|
||||
|
@ -1361,6 +1361,14 @@ async def test_config_update(
|
||||
"type": "backup/config/update",
|
||||
"agents": {"test-agent1": {"favorite": True}},
|
||||
},
|
||||
{
|
||||
"type": "backup/config/update",
|
||||
"retention": {"copies": 0},
|
||||
},
|
||||
{
|
||||
"type": "backup/config/update",
|
||||
"retention": {"days": 0},
|
||||
},
|
||||
],
|
||||
)
|
||||
async def test_config_update_errors(
|
||||
@ -2158,7 +2166,7 @@ async def test_config_schedule_logic(
|
||||
{
|
||||
"type": "backup/config/update",
|
||||
"create_backup": {"agent_ids": ["test.test-agent"]},
|
||||
"retention": {"copies": 0, "days": None},
|
||||
"retention": {"copies": 1, "days": None},
|
||||
"schedule": {"recurrence": "daily"},
|
||||
},
|
||||
{
|
||||
@ -2232,7 +2240,7 @@ async def test_config_schedule_logic(
|
||||
{
|
||||
"type": "backup/config/update",
|
||||
"create_backup": {"agent_ids": ["test.test-agent"]},
|
||||
"retention": {"copies": 0, "days": None},
|
||||
"retention": {"copies": 1, "days": None},
|
||||
"schedule": {"recurrence": "daily"},
|
||||
},
|
||||
{
|
||||
@ -2301,7 +2309,7 @@ async def test_config_schedule_logic(
|
||||
{
|
||||
"type": "backup/config/update",
|
||||
"create_backup": {"agent_ids": ["test.test-agent"]},
|
||||
"retention": {"copies": 0, "days": None},
|
||||
"retention": {"copies": 1, "days": None},
|
||||
"schedule": {"recurrence": "daily"},
|
||||
},
|
||||
{
|
||||
@ -3019,7 +3027,7 @@ async def test_config_retention_copies_logic_manual_backup(
|
||||
{
|
||||
"type": "backup/config/update",
|
||||
"create_backup": {"agent_ids": ["test-agent"]},
|
||||
"retention": {"copies": None, "days": 0},
|
||||
"retention": {"copies": None, "days": 1},
|
||||
"schedule": {"recurrence": "never"},
|
||||
}
|
||||
],
|
||||
|
Loading…
x
Reference in New Issue
Block a user