mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-10 10:46:29 +00:00
Attach event monitor after addon restore (#3893)
* Attach event monitor after addon restore * Load after install and listener removal
This commit is contained in:
parent
951efd6b29
commit
30df8ce5c7
14
.github/workflows/builder.yml
vendored
14
.github/workflows/builder.yml
vendored
@ -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')
|
||||||
|
@ -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():
|
||||||
|
@ -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()
|
||||||
|
@ -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]
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user