mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Fix hassio delaying startup to fetch container stats (#102775)
This commit is contained in:
parent
6e72499f96
commit
4447336083
@ -34,6 +34,7 @@ from homeassistant.core import (
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
from homeassistant.helpers.debounce import Debouncer
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.event import async_call_later
|
from homeassistant.helpers.event import async_call_later
|
||||||
from homeassistant.helpers.storage import Store
|
from homeassistant.helpers.storage import Store
|
||||||
@ -74,6 +75,7 @@ from .const import (
|
|||||||
DATA_KEY_SUPERVISOR,
|
DATA_KEY_SUPERVISOR,
|
||||||
DATA_KEY_SUPERVISOR_ISSUES,
|
DATA_KEY_SUPERVISOR_ISSUES,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
REQUEST_REFRESH_DELAY,
|
||||||
SUPERVISOR_CONTAINER,
|
SUPERVISOR_CONTAINER,
|
||||||
SupervisorEntityModel,
|
SupervisorEntityModel,
|
||||||
)
|
)
|
||||||
@ -334,7 +336,7 @@ def get_addons_stats(hass):
|
|||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
return hass.data.get(DATA_ADDONS_STATS)
|
return hass.data.get(DATA_ADDONS_STATS) or {}
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -344,7 +346,7 @@ def get_core_stats(hass):
|
|||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
return hass.data.get(DATA_CORE_STATS)
|
return hass.data.get(DATA_CORE_STATS) or {}
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -354,7 +356,7 @@ def get_supervisor_stats(hass):
|
|||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
return hass.data.get(DATA_SUPERVISOR_STATS)
|
return hass.data.get(DATA_SUPERVISOR_STATS) or {}
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -754,6 +756,12 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
_LOGGER,
|
_LOGGER,
|
||||||
name=DOMAIN,
|
name=DOMAIN,
|
||||||
update_interval=HASSIO_UPDATE_INTERVAL,
|
update_interval=HASSIO_UPDATE_INTERVAL,
|
||||||
|
# We don't want an immediate refresh since we want to avoid
|
||||||
|
# fetching the container stats right away and avoid hammering
|
||||||
|
# the Supervisor API on startup
|
||||||
|
request_refresh_debouncer=Debouncer(
|
||||||
|
hass, _LOGGER, cooldown=REQUEST_REFRESH_DELAY, immediate=False
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.hassio: HassIO = hass.data[DOMAIN]
|
self.hassio: HassIO = hass.data[DOMAIN]
|
||||||
self.data = {}
|
self.data = {}
|
||||||
@ -875,9 +883,9 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
DATA_SUPERVISOR_INFO: hassio.get_supervisor_info(),
|
DATA_SUPERVISOR_INFO: hassio.get_supervisor_info(),
|
||||||
DATA_OS_INFO: hassio.get_os_info(),
|
DATA_OS_INFO: hassio.get_os_info(),
|
||||||
}
|
}
|
||||||
if first_update or CONTAINER_STATS in container_updates[CORE_CONTAINER]:
|
if CONTAINER_STATS in container_updates[CORE_CONTAINER]:
|
||||||
updates[DATA_CORE_STATS] = hassio.get_core_stats()
|
updates[DATA_CORE_STATS] = hassio.get_core_stats()
|
||||||
if first_update or CONTAINER_STATS in container_updates[SUPERVISOR_CONTAINER]:
|
if CONTAINER_STATS in container_updates[SUPERVISOR_CONTAINER]:
|
||||||
updates[DATA_SUPERVISOR_STATS] = hassio.get_supervisor_stats()
|
updates[DATA_SUPERVISOR_STATS] = hassio.get_supervisor_stats()
|
||||||
|
|
||||||
results = await asyncio.gather(*updates.values())
|
results = await asyncio.gather(*updates.values())
|
||||||
@ -903,20 +911,28 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
# API calls since otherwise we would fetch stats for all containers
|
# API calls since otherwise we would fetch stats for all containers
|
||||||
# and throw them away.
|
# and throw them away.
|
||||||
#
|
#
|
||||||
for data_key, update_func, enabled_key, wanted_addons in (
|
for data_key, update_func, enabled_key, wanted_addons, needs_first_update in (
|
||||||
(
|
(
|
||||||
DATA_ADDONS_STATS,
|
DATA_ADDONS_STATS,
|
||||||
self._update_addon_stats,
|
self._update_addon_stats,
|
||||||
CONTAINER_STATS,
|
CONTAINER_STATS,
|
||||||
started_addons,
|
started_addons,
|
||||||
|
False,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
DATA_ADDONS_CHANGELOGS,
|
DATA_ADDONS_CHANGELOGS,
|
||||||
self._update_addon_changelog,
|
self._update_addon_changelog,
|
||||||
CONTAINER_CHANGELOG,
|
CONTAINER_CHANGELOG,
|
||||||
all_addons,
|
all_addons,
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
DATA_ADDONS_INFO,
|
||||||
|
self._update_addon_info,
|
||||||
|
CONTAINER_INFO,
|
||||||
|
all_addons,
|
||||||
|
True,
|
||||||
),
|
),
|
||||||
(DATA_ADDONS_INFO, self._update_addon_info, CONTAINER_INFO, all_addons),
|
|
||||||
):
|
):
|
||||||
container_data: dict[str, Any] = data.setdefault(data_key, {})
|
container_data: dict[str, Any] = data.setdefault(data_key, {})
|
||||||
container_data.update(
|
container_data.update(
|
||||||
@ -925,7 +941,8 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
*[
|
*[
|
||||||
update_func(slug)
|
update_func(slug)
|
||||||
for slug in wanted_addons
|
for slug in wanted_addons
|
||||||
if first_update or enabled_key in container_updates[slug]
|
if (first_update and needs_first_update)
|
||||||
|
or enabled_key in container_updates[slug]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -101,6 +101,8 @@ KEY_TO_UPDATE_TYPES: dict[str, set[str]] = {
|
|||||||
ATTR_STATE: {CONTAINER_INFO},
|
ATTR_STATE: {CONTAINER_INFO},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REQUEST_REFRESH_DELAY = 10
|
||||||
|
|
||||||
|
|
||||||
class SupervisorEntityModel(StrEnum):
|
class SupervisorEntityModel(StrEnum):
|
||||||
"""Supervisor entity model."""
|
"""Supervisor entity model."""
|
||||||
|
@ -10,6 +10,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|||||||
from . import DOMAIN, HassioDataUpdateCoordinator
|
from . import DOMAIN, HassioDataUpdateCoordinator
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_SLUG,
|
ATTR_SLUG,
|
||||||
|
CONTAINER_STATS,
|
||||||
CORE_CONTAINER,
|
CORE_CONTAINER,
|
||||||
DATA_KEY_ADDONS,
|
DATA_KEY_ADDONS,
|
||||||
DATA_KEY_CORE,
|
DATA_KEY_CORE,
|
||||||
@ -58,6 +59,8 @@ class HassioAddonEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||||||
self._addon_slug, self.entity_id, update_types
|
self._addon_slug, self.entity_id, update_types
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if CONTAINER_STATS in update_types:
|
||||||
|
await self.coordinator.async_request_refresh()
|
||||||
|
|
||||||
|
|
||||||
class HassioOSEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
class HassioOSEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||||
@ -147,6 +150,8 @@ class HassioSupervisorEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||||||
SUPERVISOR_CONTAINER, self.entity_id, update_types
|
SUPERVISOR_CONTAINER, self.entity_id, update_types
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if CONTAINER_STATS in update_types:
|
||||||
|
await self.coordinator.async_request_refresh()
|
||||||
|
|
||||||
|
|
||||||
class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||||
@ -183,3 +188,5 @@ class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||||||
CORE_CONTAINER, self.entity_id, update_types
|
CORE_CONTAINER, self.entity_id, update_types
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if CONTAINER_STATS in update_types:
|
||||||
|
await self.coordinator.async_request_refresh()
|
||||||
|
@ -17,6 +17,7 @@ from homeassistant.components.hassio import (
|
|||||||
async_get_addon_store_info,
|
async_get_addon_store_info,
|
||||||
hostname_from_addon_slug,
|
hostname_from_addon_slug,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY
|
||||||
from homeassistant.components.hassio.handler import HassioAPIError
|
from homeassistant.components.hassio.handler import HassioAPIError
|
||||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -244,7 +245,7 @@ async def test_setup_api_ping(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0"
|
assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0"
|
||||||
assert hass.components.hassio.is_hassio()
|
assert hass.components.hassio.is_hassio()
|
||||||
|
|
||||||
@ -289,7 +290,7 @@ async def test_setup_api_push_api_data(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||||
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
||||||
assert aioclient_mock.mock_calls[1][2]["watchdog"]
|
assert aioclient_mock.mock_calls[1][2]["watchdog"]
|
||||||
@ -308,7 +309,7 @@ async def test_setup_api_push_api_data_server_host(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||||
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
||||||
assert not aioclient_mock.mock_calls[1][2]["watchdog"]
|
assert not aioclient_mock.mock_calls[1][2]["watchdog"]
|
||||||
@ -325,7 +326,7 @@ async def test_setup_api_push_api_data_default(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||||
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
||||||
refresh_token = aioclient_mock.mock_calls[1][2]["refresh_token"]
|
refresh_token = aioclient_mock.mock_calls[1][2]["refresh_token"]
|
||||||
@ -405,7 +406,7 @@ async def test_setup_api_existing_hassio_user(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||||
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
||||||
assert aioclient_mock.mock_calls[1][2]["refresh_token"] == token.token
|
assert aioclient_mock.mock_calls[1][2]["refresh_token"] == token.token
|
||||||
@ -422,7 +423,7 @@ async def test_setup_core_push_timezone(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert aioclient_mock.mock_calls[2][2]["timezone"] == "testzone"
|
assert aioclient_mock.mock_calls[2][2]["timezone"] == "testzone"
|
||||||
|
|
||||||
with patch("homeassistant.util.dt.set_default_time_zone"):
|
with patch("homeassistant.util.dt.set_default_time_zone"):
|
||||||
@ -442,7 +443,7 @@ async def test_setup_hassio_no_additional_data(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert aioclient_mock.mock_calls[-1][3]["Authorization"] == "Bearer 123456"
|
assert aioclient_mock.mock_calls[-1][3]["Authorization"] == "Bearer 123456"
|
||||||
|
|
||||||
|
|
||||||
@ -524,14 +525,14 @@ async def test_service_calls(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 26
|
assert aioclient_mock.call_count == 24
|
||||||
assert aioclient_mock.mock_calls[-1][2] == "test"
|
assert aioclient_mock.mock_calls[-1][2] == "test"
|
||||||
|
|
||||||
await hass.services.async_call("hassio", "host_shutdown", {})
|
await hass.services.async_call("hassio", "host_shutdown", {})
|
||||||
await hass.services.async_call("hassio", "host_reboot", {})
|
await hass.services.async_call("hassio", "host_reboot", {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 28
|
assert aioclient_mock.call_count == 26
|
||||||
|
|
||||||
await hass.services.async_call("hassio", "backup_full", {})
|
await hass.services.async_call("hassio", "backup_full", {})
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
@ -546,7 +547,7 @@ async def test_service_calls(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 30
|
assert aioclient_mock.call_count == 28
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
"name": "2021-11-13 03:48:00",
|
"name": "2021-11-13 03:48:00",
|
||||||
"homeassistant": True,
|
"homeassistant": True,
|
||||||
@ -571,7 +572,7 @@ async def test_service_calls(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 32
|
assert aioclient_mock.call_count == 30
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
"addons": ["test"],
|
"addons": ["test"],
|
||||||
"folders": ["ssl"],
|
"folders": ["ssl"],
|
||||||
@ -590,7 +591,7 @@ async def test_service_calls(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 33
|
assert aioclient_mock.call_count == 31
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
"name": "backup_name",
|
"name": "backup_name",
|
||||||
"location": "backup_share",
|
"location": "backup_share",
|
||||||
@ -606,7 +607,7 @@ async def test_service_calls(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 34
|
assert aioclient_mock.call_count == 32
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
"name": "2021-11-13 03:48:00",
|
"name": "2021-11-13 03:48:00",
|
||||||
"location": None,
|
"location": None,
|
||||||
@ -624,7 +625,7 @@ async def test_service_calls(
|
|||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 36
|
assert aioclient_mock.call_count == 34
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
"name": "2021-11-13 11:48:00",
|
"name": "2021-11-13 11:48:00",
|
||||||
"location": None,
|
"location": None,
|
||||||
@ -896,6 +897,7 @@ async def test_coordinator_updates(
|
|||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
# Initial refresh without stats
|
||||||
assert refresh_updates_mock.call_count == 1
|
assert refresh_updates_mock.call_count == 1
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
@ -919,10 +921,12 @@ async def test_coordinator_updates(
|
|||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
assert refresh_updates_mock.call_count == 1
|
assert refresh_updates_mock.call_count == 0
|
||||||
|
|
||||||
# There is a 10s cooldown on the debouncer
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10))
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
@ -940,6 +944,88 @@ async def test_coordinator_updates(
|
|||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert refresh_updates_mock.call_count == 1
|
||||||
|
assert "Error on Supervisor API: Unknown" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_coordinator_updates_stats_entities_enabled(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
entity_registry_enabled_by_default: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test coordinator updates with stats entities enabled."""
|
||||||
|
await async_setup_component(hass, "homeassistant", {})
|
||||||
|
with patch.dict(os.environ, MOCK_ENVIRON), patch(
|
||||||
|
"homeassistant.components.hassio.HassIO.refresh_updates"
|
||||||
|
) as refresh_updates_mock:
|
||||||
|
config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
# Initial refresh without stats
|
||||||
|
assert refresh_updates_mock.call_count == 1
|
||||||
|
|
||||||
|
# Refresh with stats once we know which ones are needed
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert refresh_updates_mock.call_count == 2
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.hassio.HassIO.refresh_updates",
|
||||||
|
) as refresh_updates_mock:
|
||||||
|
async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=20))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert refresh_updates_mock.call_count == 0
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.hassio.HassIO.refresh_updates",
|
||||||
|
) as refresh_updates_mock:
|
||||||
|
await hass.services.async_call(
|
||||||
|
"homeassistant",
|
||||||
|
"update_entity",
|
||||||
|
{
|
||||||
|
"entity_id": [
|
||||||
|
"update.home_assistant_core_update",
|
||||||
|
"update.home_assistant_supervisor_update",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert refresh_updates_mock.call_count == 0
|
||||||
|
|
||||||
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.hassio.HassIO.refresh_updates",
|
||||||
|
side_effect=HassioAPIError("Unknown"),
|
||||||
|
) as refresh_updates_mock:
|
||||||
|
await hass.services.async_call(
|
||||||
|
"homeassistant",
|
||||||
|
"update_entity",
|
||||||
|
{
|
||||||
|
"entity_id": [
|
||||||
|
"update.home_assistant_core_update",
|
||||||
|
"update.home_assistant_supervisor_update",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
assert refresh_updates_mock.call_count == 1
|
assert refresh_updates_mock.call_count == 1
|
||||||
assert "Error on Supervisor API: Unknown" in caplog.text
|
assert "Error on Supervisor API: Unknown" in caplog.text
|
||||||
|
|
||||||
@ -973,7 +1059,7 @@ async def test_setup_hardware_integration(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result
|
assert result
|
||||||
assert aioclient_mock.call_count == 22
|
assert aioclient_mock.call_count == 20
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ from homeassistant.components.hassio import (
|
|||||||
HASSIO_UPDATE_INTERVAL,
|
HASSIO_UPDATE_INTERVAL,
|
||||||
HassioAPIError,
|
HassioAPIError,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
@ -245,6 +246,12 @@ async def test_sensor(
|
|||||||
await hass.config_entries.async_reload(config_entry.entry_id)
|
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Verify that the entity have the expected state.
|
# Verify that the entity have the expected state.
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state.state == expected
|
assert state.state == expected
|
||||||
@ -306,6 +313,12 @@ async def test_stats_addon_sensor(
|
|||||||
await hass.config_entries.async_reload(config_entry.entry_id)
|
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Verify that the entity have the expected state.
|
# Verify that the entity have the expected state.
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state.state == expected
|
assert state.state == expected
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
"""The tests for the hassio update entities."""
|
"""The tests for the hassio update entities."""
|
||||||
|
from datetime import timedelta
|
||||||
import os
|
import os
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.hassio import DOMAIN
|
from homeassistant.components.hassio import DOMAIN, HassioAPIError
|
||||||
from homeassistant.components.hassio.handler import HassioAPIError
|
from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
@ -609,8 +611,13 @@ async def test_setting_up_core_update_when_addon_fails(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
|
# There is a REQUEST_REFRESH_DELAYs cooldown on the debouncer
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.now() + timedelta(seconds=REQUEST_REFRESH_DELAY)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Verify that the core update entity does exist
|
# Verify that the core update entity does exist
|
||||||
state = hass.states.get("update.home_assistant_core_update")
|
state = hass.states.get("update.home_assistant_core_update")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
assert "Could not fetch stats for test: add-on is not running" in caplog.text
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user