Regenerate instance ID on error (#94898)

This commit is contained in:
Erik Montnemery 2023-06-20 11:16:51 +02:00 committed by GitHub
parent 2b1660c0f7
commit 609a573b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 5 deletions

View File

@ -1,6 +1,7 @@
"""Helper to create a unique instance ID.""" """Helper to create a unique instance ID."""
from __future__ import annotations from __future__ import annotations
import logging
import uuid import uuid
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@ -12,17 +13,30 @@ DATA_VERSION = 1
LEGACY_UUID_FILE = ".uuid" LEGACY_UUID_FILE = ".uuid"
_LOGGER = logging.getLogger(__name__)
@singleton.singleton(DATA_KEY) @singleton.singleton(DATA_KEY)
async def async_get(hass: HomeAssistant) -> str: async def async_get(hass: HomeAssistant) -> str:
"""Get unique ID for the hass instance.""" """Get unique ID for the hass instance."""
store = storage.Store[dict[str, str]](hass, DATA_VERSION, DATA_KEY, True) store = storage.Store[dict[str, str]](hass, DATA_VERSION, DATA_KEY, True)
data: dict[str, str] | None = await storage.async_migrator( data: dict[str, str] | None = None
try:
data = await storage.async_migrator(
hass, hass,
hass.config.path(LEGACY_UUID_FILE), hass.config.path(LEGACY_UUID_FILE),
store, store,
) )
except Exception: # pylint: disable=broad-exception-caught
_LOGGER.exception(
(
"Could not read hass instance ID from '%s' or '%s', a new instance ID "
"will be generated"
),
DATA_KEY,
LEGACY_UUID_FILE,
)
if data is not None: if data is not None:
return data["uuid"] return data["uuid"]

View File

@ -1,7 +1,10 @@
"""Tests for instance ID helper.""" """Tests for instance ID helper."""
from json import JSONDecodeError
from typing import Any from typing import Any
from unittest.mock import patch from unittest.mock import patch
import pytest
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import instance_id from homeassistant.helpers import instance_id
@ -14,6 +17,25 @@ async def test_get_id_empty(hass: HomeAssistant, hass_storage: dict[str, Any]) -
assert hass_storage["core.uuid"]["data"]["uuid"] == uuid assert hass_storage["core.uuid"]["data"]["uuid"] == uuid
async def test_get_id_load_fail(
hass: HomeAssistant, hass_storage: dict[str, Any], caplog: pytest.LogCaptureFixture
) -> None:
"""Migrate existing file with error."""
hass_storage["core.uuid"] = None # Invalid, will make store.async_load raise
uuid = await instance_id.async_get(hass)
assert uuid is not None
# Assert it's stored
assert hass_storage["core.uuid"]["data"]["uuid"] == uuid
assert (
"Could not read hass instance ID from 'core.uuid' or '.uuid', a "
"new instance ID will be generated" in caplog.text
)
async def test_get_id_migrate( async def test_get_id_migrate(
hass: HomeAssistant, hass_storage: dict[str, Any] hass: HomeAssistant, hass_storage: dict[str, Any]
) -> None: ) -> None:
@ -30,3 +52,27 @@ async def test_get_id_migrate(
# assert old deleted # assert old deleted
assert len(mock_remove.mock_calls) == 1 assert len(mock_remove.mock_calls) == 1
async def test_get_id_migrate_fail(
hass: HomeAssistant, hass_storage: dict[str, Any], caplog: pytest.LogCaptureFixture
) -> None:
"""Migrate existing file with error."""
with patch(
"homeassistant.util.json.load_json",
side_effect=JSONDecodeError("test_error", "test", 1),
), patch("os.path.isfile", return_value=True), patch("os.remove") as mock_remove:
uuid = await instance_id.async_get(hass)
assert uuid is not None
# Assert it's stored
assert hass_storage["core.uuid"]["data"]["uuid"] == uuid
# assert old not deleted
assert len(mock_remove.mock_calls) == 0
assert (
"Could not read hass instance ID from 'core.uuid' or '.uuid', a "
"new instance ID will be generated" in caplog.text
)