Attach event monitor after addon restore (#3893)

* Attach event monitor after addon restore

* Load after install and listener removal
This commit is contained in:
Mike Degatano 2022-09-23 15:11:36 -04:00 committed by GitHub
parent 951efd6b29
commit 30df8ce5c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 8 deletions

View File

@ -297,6 +297,12 @@ jobs:
exit 1
fi
# Make sure its state is started
test="$(docker exec hassio_cli ha addons info core_ssh --no-progress --raw-json | jq -r '.data.state')"
if [ "$test" != "started" ]; then
exit 1
fi
- name: Check the Supervisor code sign
if: needs.init.outputs.publish == 'true'
run: |
@ -369,6 +375,12 @@ jobs:
exit 1
fi
# Make sure its state is started
test="$(docker exec hassio_cli ha addons info core_ssh --no-progress --raw-json | jq -r '.data.state')"
if [ "$test" != "started" ]; then
exit 1
fi
- name: Restore SSL directory from backup
run: |
test=$(docker exec hassio_cli ha backups restore ${{ steps.backup.outputs.slug }} --folders ssl --no-progress --raw-json | jq -r '.result')

View File

@ -203,7 +203,7 @@ class AddonManager(CoreSysAttributes):
else:
addon.state = AddonState.UNKNOWN
await addon.remove_data()
await addon.unload()
# Cleanup audio settings
if addon.path_pulse.exists():

View File

@ -18,6 +18,7 @@ from securetar import atomic_contents_add, secure_path
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..bus import EventListener
from ..const import (
ATTR_ACCESS_TOKEN,
ATTR_AUDIO_INPUT,
@ -115,6 +116,7 @@ class Addon(AddonModel):
self._manual_stop: bool = (
self.sys_hardware.helper.last_boot == self.sys_config.last_boot
)
self._listeners: list[EventListener] = []
@Job(
name=f"addon_{slug}_restart_after_problem",
@ -197,12 +199,16 @@ class Addon(AddonModel):
async def load(self) -> None:
"""Async initialize of object."""
self._listeners.append(
self.sys_bus.register_event(
BusEvent.DOCKER_CONTAINER_STATE_CHANGE, self.container_state_changed
)
)
self._listeners.append(
self.sys_bus.register_event(
BusEvent.DOCKER_CONTAINER_STATE_CHANGE, self.watchdog_container
)
)
with suppress(DockerError):
await self.instance.attach(version=self.version)
@ -504,6 +510,11 @@ class Addon(AddonModel):
return options_schema.pwned
@property
def loaded(self) -> bool:
"""Is add-on loaded."""
return bool(self._listeners)
def save_persist(self) -> None:
"""Save data of add-on."""
self.sys_addons.data.save_data()
@ -572,8 +583,11 @@ class Addon(AddonModel):
raise AddonConfigurationError()
async def remove_data(self) -> None:
"""Remove add-on data."""
async def unload(self) -> None:
"""Unload add-on and remove data."""
for listener in self._listeners:
self.sys_bus.remove_listener(listener)
if not self.path_data.is_dir():
return
@ -931,6 +945,10 @@ class Addon(AddonModel):
)
raise AddonsError() from err
# Is add-on loaded
if not self.loaded:
await self.load()
# Run add-on
if data[ATTR_STATE] == AddonState.STARTED:
return await self.start()

View File

@ -279,3 +279,28 @@ async def test_install_update_fails_if_out_of_date(
await coresys.addons.install(TEST_ADDON_SLUG)
with pytest.raises(AddonsJobError):
await install_addon_ssh.update()
async def test_listeners_removed_on_uninstall(
coresys: CoreSys, install_addon_ssh: Addon
) -> None:
"""Test addon listeners are removed on uninstall."""
with patch.object(DockerAddon, "attach"):
await install_addon_ssh.load()
assert install_addon_ssh.loaded is True
# pylint: disable=protected-access
listeners = install_addon_ssh._listeners
for listener in listeners:
assert (
listener in coresys.bus._listeners[BusEvent.DOCKER_CONTAINER_STATE_CHANGE]
)
with patch.object(Addon, "persist", new=PropertyMock(return_value=MagicMock())):
await coresys.addons.uninstall(TEST_ADDON_SLUG)
for listener in listeners:
assert (
listener
not in coresys.bus._listeners[BusEvent.DOCKER_CONTAINER_STATE_CHANGE]
)