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

@ -87,7 +87,7 @@ jobs:
uses: actions/checkout@v3.0.2 uses: actions/checkout@v3.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Write env-file - name: Write env-file
if: needs.init.outputs.requirements == 'true' if: needs.init.outputs.requirements == 'true'
run: | run: |
@ -297,6 +297,12 @@ jobs:
exit 1 exit 1
fi 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 - name: Check the Supervisor code sign
if: needs.init.outputs.publish == 'true' if: needs.init.outputs.publish == 'true'
run: | run: |
@ -369,6 +375,12 @@ jobs:
exit 1 exit 1
fi 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 - name: Restore SSL directory from backup
run: | run: |
test=$(docker exec hassio_cli ha backups restore ${{ steps.backup.outputs.slug }} --folders ssl --no-progress --raw-json | jq -r '.result') 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: else:
addon.state = AddonState.UNKNOWN addon.state = AddonState.UNKNOWN
await addon.remove_data() await addon.unload()
# Cleanup audio settings # Cleanup audio settings
if addon.path_pulse.exists(): if addon.path_pulse.exists():

View File

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