Fix reload of automation and scripts when blueprint changed (#80322)
parent
d5e26326dc
commit
284893d942
|
@ -276,9 +276,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
|
|
||||||
async def reload_service_handler(service_call: ServiceCall) -> None:
|
async def reload_service_handler(service_call: ServiceCall) -> None:
|
||||||
"""Remove all automations and load new ones from config."""
|
"""Remove all automations and load new ones from config."""
|
||||||
|
await async_get_blueprints(hass).async_reset_cache()
|
||||||
if (conf := await component.async_prepare_reload(skip_reset=True)) is None:
|
if (conf := await component.async_prepare_reload(skip_reset=True)) is None:
|
||||||
return
|
return
|
||||||
async_get_blueprints(hass).async_reset_cache()
|
|
||||||
await _async_process_config(hass, conf, component)
|
await _async_process_config(hass, conf, component)
|
||||||
hass.bus.async_fire(EVENT_AUTOMATION_RELOADED, context=service_call.context)
|
hass.bus.async_fire(EVENT_AUTOMATION_RELOADED, context=service_call.context)
|
||||||
|
|
||||||
|
|
|
@ -202,9 +202,9 @@ class DomainBlueprints:
|
||||||
"""Return the blueprint folder."""
|
"""Return the blueprint folder."""
|
||||||
return pathlib.Path(self.hass.config.path(BLUEPRINT_FOLDER, self.domain))
|
return pathlib.Path(self.hass.config.path(BLUEPRINT_FOLDER, self.domain))
|
||||||
|
|
||||||
@callback
|
async def async_reset_cache(self) -> None:
|
||||||
def async_reset_cache(self) -> None:
|
|
||||||
"""Reset the blueprint cache."""
|
"""Reset the blueprint cache."""
|
||||||
|
async with self._load_lock:
|
||||||
self._blueprints = {}
|
self._blueprints = {}
|
||||||
|
|
||||||
def _load_blueprint(self, blueprint_path) -> Blueprint:
|
def _load_blueprint(self, blueprint_path) -> Blueprint:
|
||||||
|
|
|
@ -176,9 +176,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
|
|
||||||
async def reload_service(service: ServiceCall) -> None:
|
async def reload_service(service: ServiceCall) -> None:
|
||||||
"""Call a service to reload scripts."""
|
"""Call a service to reload scripts."""
|
||||||
|
await async_get_blueprints(hass).async_reset_cache()
|
||||||
if (conf := await component.async_prepare_reload()) is None:
|
if (conf := await component.async_prepare_reload()) is None:
|
||||||
return
|
return
|
||||||
async_get_blueprints(hass).async_reset_cache()
|
|
||||||
await _async_process_config(hass, conf, component)
|
await _async_process_config(hass, conf, component)
|
||||||
|
|
||||||
async def turn_on_service(service: ServiceCall) -> None:
|
async def turn_on_service(service: ServiceCall) -> None:
|
||||||
|
|
|
@ -46,6 +46,7 @@ from homeassistant.helpers.script import (
|
||||||
_async_stop_scripts_at_shutdown,
|
_async_stop_scripts_at_shutdown,
|
||||||
)
|
)
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
from homeassistant.util import yaml
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
|
@ -1002,6 +1003,60 @@ async def test_reload_unchanged_automation(hass, calls, automation_config):
|
||||||
assert len(calls) == 2
|
assert len(calls) == 2
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reload_automation_when_blueprint_changes(hass, calls):
|
||||||
|
"""Test an automation is updated at reload if the blueprint has changed."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.automation.AutomationEntity", wraps=AutomationEntity
|
||||||
|
) as automation_entity_init:
|
||||||
|
config = {
|
||||||
|
automation.DOMAIN: [
|
||||||
|
{
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "test_event_service.yaml",
|
||||||
|
"input": {
|
||||||
|
"trigger_event": "test_event",
|
||||||
|
"service_to_call": "test.automation",
|
||||||
|
"a_number": 5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
assert await async_setup_component(hass, automation.DOMAIN, config)
|
||||||
|
assert automation_entity_init.call_count == 1
|
||||||
|
automation_entity_init.reset_mock()
|
||||||
|
|
||||||
|
hass.bus.async_fire("test_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
# Reload the automations without any change, but with updated blueprint
|
||||||
|
blueprint_path = automation.async_get_blueprints(hass).blueprint_folder
|
||||||
|
blueprint_config = yaml.load_yaml(blueprint_path / "test_event_service.yaml")
|
||||||
|
blueprint_config["action"] = [blueprint_config["action"]]
|
||||||
|
blueprint_config["action"].append(blueprint_config["action"][-1])
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.config.load_yaml_config_file",
|
||||||
|
autospec=True,
|
||||||
|
return_value=config,
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.blueprint.models.yaml.load_yaml",
|
||||||
|
autospec=True,
|
||||||
|
return_value=blueprint_config,
|
||||||
|
):
|
||||||
|
await hass.services.async_call(
|
||||||
|
automation.DOMAIN, SERVICE_RELOAD, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
assert automation_entity_init.call_count == 1
|
||||||
|
automation_entity_init.reset_mock()
|
||||||
|
|
||||||
|
hass.bus.async_fire("test_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 3
|
||||||
|
|
||||||
|
|
||||||
async def test_automation_restore_state(hass):
|
async def test_automation_restore_state(hass):
|
||||||
"""Ensure states are restored on startup."""
|
"""Ensure states are restored on startup."""
|
||||||
time = dt_util.utcnow()
|
time = dt_util.utcnow()
|
||||||
|
|
|
@ -224,7 +224,7 @@ async def test_domain_blueprints_caching(domain_bps):
|
||||||
assert await domain_bps.async_get_blueprint("something") is obj
|
assert await domain_bps.async_get_blueprint("something") is obj
|
||||||
|
|
||||||
obj_2 = object()
|
obj_2 = object()
|
||||||
domain_bps.async_reset_cache()
|
await domain_bps.async_reset_cache()
|
||||||
|
|
||||||
# Now we call this method again.
|
# Now we call this method again.
|
||||||
with patch.object(domain_bps, "_load_blueprint", return_value=obj_2):
|
with patch.object(domain_bps, "_load_blueprint", return_value=obj_2):
|
||||||
|
|
Loading…
Reference in New Issue