Add homeassistant.reload_all service (#87769)

This commit is contained in:
Franck Nijhof 2023-02-13 12:09:29 +01:00 committed by GitHub
parent 03710e58b5
commit f1daeabff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 108 additions and 0 deletions

View File

@ -15,6 +15,7 @@ from homeassistant.const import (
RESTART_EXIT_CODE,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_RELOAD,
SERVICE_SAVE_PERSISTENT_STATES,
SERVICE_TOGGLE,
SERVICE_TURN_OFF,
@ -40,6 +41,7 @@ SERVICE_RELOAD_CONFIG_ENTRY = "reload_config_entry"
SERVICE_CHECK_CONFIG = "check_config"
SERVICE_UPDATE_ENTITY = "update_entity"
SERVICE_SET_LOCATION = "set_location"
SERVICE_RELOAD_ALL = "reload_all"
SCHEMA_UPDATE_ENTITY = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
SCHEMA_RELOAD_CONFIG_ENTRY = vol.All(
vol.Schema(
@ -275,4 +277,50 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
schema=SCHEMA_RELOAD_CONFIG_ENTRY,
)
async def async_handle_reload_all(call: ha.ServiceCall) -> None:
"""Service handler for calling all integration reload services.
Calls all reload services on all active domains, which triggers the
reload of YAML configurations for the domain that support it.
Additionally, it also calls the `homeasssitant.reload_core_config`
service, as that reloads the core YAML configuration, and the
`frontend.reload_themes` service, as that reloads the themes.
We only do so, if there are no configuration errors.
"""
if errors := await conf_util.async_check_ha_config_file(hass):
_LOGGER.error(
"The system cannot reload because the configuration is not valid: %s",
errors,
)
raise HomeAssistantError(
"Cannot quick reload all YAML configurations because the "
f"configuration is not valid: {errors}"
)
services = hass.services.async_services()
tasks = [
hass.services.async_call(
domain, SERVICE_RELOAD, context=call.context, blocking=True
)
for domain, domain_services in services.items()
if domain != "notify" and SERVICE_RELOAD in domain_services
] + [
hass.services.async_call(
domain, service, context=call.context, blocking=True
)
for domain, service in {
ha.DOMAIN: SERVICE_RELOAD_CORE_CONFIG,
"frontend": "reload_themes",
}.items()
]
await asyncio.gather(*tasks)
async_register_admin_service(
hass, ha.DOMAIN, SERVICE_RELOAD_ALL, async_handle_reload_all
)
return True

View File

@ -12,6 +12,7 @@ import homeassistant.components as comps
from homeassistant.components.homeassistant import (
ATTR_ENTRY_ID,
SERVICE_CHECK_CONFIG,
SERVICE_RELOAD_ALL,
SERVICE_RELOAD_CORE_CONFIG,
SERVICE_SET_LOCATION,
)
@ -572,3 +573,62 @@ async def test_save_persistent_states(hass: HomeAssistant) -> None:
blocking=True,
)
assert mock_save.called
async def test_reload_all(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test reload_all service."""
await async_setup_component(hass, "homeassistant", {})
test1 = async_mock_service(hass, "test1", "reload")
test2 = async_mock_service(hass, "test2", "reload")
no_reload = async_mock_service(hass, "test3", "not_reload")
notify = async_mock_service(hass, "notify", "reload")
core_config = async_mock_service(hass, "homeassistant", "reload_core_config")
themes = async_mock_service(hass, "frontend", "reload_themes")
with patch(
"homeassistant.config.async_check_ha_config_file",
return_value=None,
) as mock_async_check_ha_config_file:
await hass.services.async_call(
"homeassistant",
SERVICE_RELOAD_ALL,
blocking=True,
)
assert mock_async_check_ha_config_file.called
assert len(test1) == 1
assert len(test2) == 1
assert len(no_reload) == 0
assert len(notify) == 0
assert len(core_config) == 1
assert len(themes) == 1
with pytest.raises(
HomeAssistantError,
match=(
"Cannot quick reload all YAML configurations because the configuration is "
"not valid: Oh no, drama!"
),
), patch(
"homeassistant.config.async_check_ha_config_file",
return_value="Oh no, drama!",
) as mock_async_check_ha_config_file:
await hass.services.async_call(
"homeassistant",
SERVICE_RELOAD_ALL,
blocking=True,
)
assert mock_async_check_ha_config_file.called
assert (
"The system cannot reload because the configuration is not valid: Oh no, drama!"
in caplog.text
)
# None have been called again
assert len(test1) == 1
assert len(test2) == 1
assert len(core_config) == 1
assert len(themes) == 1