mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-09 10:16:29 +00:00
addons/info returns info on all addons (#3762)
* Change to legacy routing approach * Revert launch.json changes
This commit is contained in:
parent
2b4f46f6b3
commit
4f8f28b9f6
@ -356,6 +356,9 @@ class Addon(AddonModel):
|
|||||||
@property
|
@property
|
||||||
def ingress_panel(self) -> Optional[bool]:
|
def ingress_panel(self) -> Optional[bool]:
|
||||||
"""Return True if the add-on access support ingress."""
|
"""Return True if the add-on access support ingress."""
|
||||||
|
if not self.with_ingress:
|
||||||
|
return None
|
||||||
|
|
||||||
return self.persist[ATTR_INGRESS_PANEL]
|
return self.persist[ATTR_INGRESS_PANEL]
|
||||||
|
|
||||||
@ingress_panel.setter
|
@ingress_panel.setter
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
"""Init file for Supervisor RESTful API."""
|
"""Init file for Supervisor RESTful API."""
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
||||||
|
from supervisor.api.utils import api_process
|
||||||
|
from supervisor.exceptions import APIAddonNotInstalled
|
||||||
|
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
from .addons import APIAddons
|
from .addons import APIAddons
|
||||||
from .audio import APIAudio
|
from .audio import APIAudio
|
||||||
@ -383,7 +386,6 @@ class RestAPI(CoreSysAttributes):
|
|||||||
self.webapp.add_routes(
|
self.webapp.add_routes(
|
||||||
[
|
[
|
||||||
web.get("/addons", api_addons.list),
|
web.get("/addons", api_addons.list),
|
||||||
web.get("/addons/{addon}/info", api_addons.info),
|
|
||||||
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
|
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
|
||||||
web.post("/addons/{addon}/start", api_addons.start),
|
web.post("/addons/{addon}/start", api_addons.start),
|
||||||
web.post("/addons/{addon}/stop", api_addons.stop),
|
web.post("/addons/{addon}/stop", api_addons.stop),
|
||||||
@ -401,6 +403,20 @@ class RestAPI(CoreSysAttributes):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Legacy routing to support requests for not installed addons
|
||||||
|
api_store = APIStore()
|
||||||
|
api_store.coresys = self.coresys
|
||||||
|
|
||||||
|
@api_process
|
||||||
|
async def addons_addon_info(request: web.Request) -> dict[str, Any]:
|
||||||
|
"""Route to store if info requested for not installed addon."""
|
||||||
|
try:
|
||||||
|
return await api_addons.info(request)
|
||||||
|
except APIAddonNotInstalled:
|
||||||
|
return await api_store.addons_addon_info(request)
|
||||||
|
|
||||||
|
self.webapp.add_routes([web.get("/addons/{addon}/info", addons_addon_info)])
|
||||||
|
|
||||||
def _register_ingress(self) -> None:
|
def _register_ingress(self) -> None:
|
||||||
"""Register Ingress functions."""
|
"""Register Ingress functions."""
|
||||||
api_ingress = APIIngress()
|
api_ingress = APIIngress()
|
||||||
|
@ -96,7 +96,13 @@ from ..const import (
|
|||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..docker.stats import DockerStats
|
from ..docker.stats import DockerStats
|
||||||
from ..exceptions import APIError, APIForbidden, PwnedError, PwnedSecret
|
from ..exceptions import (
|
||||||
|
APIAddonNotInstalled,
|
||||||
|
APIError,
|
||||||
|
APIForbidden,
|
||||||
|
PwnedError,
|
||||||
|
PwnedSecret,
|
||||||
|
)
|
||||||
from ..validate import docker_ports
|
from ..validate import docker_ports
|
||||||
from .const import ATTR_SIGNED, CONTENT_TYPE_BINARY
|
from .const import ATTR_SIGNED, CONTENT_TYPE_BINARY
|
||||||
from .utils import api_process, api_process_raw, api_validate, json_loads
|
from .utils import api_process, api_process_raw, api_validate, json_loads
|
||||||
@ -140,7 +146,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
if not addon:
|
if not addon:
|
||||||
raise APIError(f"Addon {addon_slug} does not exist")
|
raise APIError(f"Addon {addon_slug} does not exist")
|
||||||
if not isinstance(addon, Addon) or not addon.is_installed:
|
if not isinstance(addon, Addon) or not addon.is_installed:
|
||||||
raise APIError("Addon is not installed")
|
raise APIAddonNotInstalled("Addon is not installed")
|
||||||
|
|
||||||
return addon
|
return addon
|
||||||
|
|
||||||
@ -177,7 +183,6 @@ class APIAddons(CoreSysAttributes):
|
|||||||
"""Reload all add-on data from store."""
|
"""Reload all add-on data from store."""
|
||||||
await asyncio.shield(self.sys_store.reload())
|
await asyncio.shield(self.sys_store.reload())
|
||||||
|
|
||||||
@api_process
|
|
||||||
async def info(self, request: web.Request) -> dict[str, Any]:
|
async def info(self, request: web.Request) -> dict[str, Any]:
|
||||||
"""Return add-on information."""
|
"""Return add-on information."""
|
||||||
addon: AnyAddon = self._extract_addon(request)
|
addon: AnyAddon = self._extract_addon(request)
|
||||||
|
@ -263,6 +263,10 @@ class APIForbidden(APIError):
|
|||||||
"""API forbidden error."""
|
"""API forbidden error."""
|
||||||
|
|
||||||
|
|
||||||
|
class APIAddonNotInstalled(APIError):
|
||||||
|
"""Not installed addon requested at addons API."""
|
||||||
|
|
||||||
|
|
||||||
# Service / Discovery
|
# Service / Discovery
|
||||||
|
|
||||||
|
|
||||||
|
36
tests/api/test_addons.py
Normal file
36
tests/api/test_addons.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""Test addons api."""
|
||||||
|
|
||||||
|
from supervisor.addons.addon import Addon
|
||||||
|
from supervisor.const import AddonState
|
||||||
|
from supervisor.coresys import CoreSys
|
||||||
|
from supervisor.store.repository import Repository
|
||||||
|
|
||||||
|
from ..const import TEST_ADDON_SLUG
|
||||||
|
|
||||||
|
|
||||||
|
async def test_addons_info(api_client, coresys: CoreSys, install_addon_ssh: Addon):
|
||||||
|
"""Test getting addon info."""
|
||||||
|
install_addon_ssh.state = AddonState.STOPPED
|
||||||
|
install_addon_ssh.ingress_panel = True
|
||||||
|
install_addon_ssh.protected = True
|
||||||
|
install_addon_ssh.watchdog = False
|
||||||
|
|
||||||
|
resp = await api_client.get(f"/addons/{TEST_ADDON_SLUG}/info")
|
||||||
|
result = await resp.json()
|
||||||
|
assert result["data"]["version_latest"] == "9.2.1"
|
||||||
|
assert result["data"]["version"] == "9.2.1"
|
||||||
|
assert result["data"]["state"] == "stopped"
|
||||||
|
assert result["data"]["ingress_panel"] is True
|
||||||
|
assert result["data"]["protected"] is True
|
||||||
|
assert result["data"]["watchdog"] is False
|
||||||
|
|
||||||
|
|
||||||
|
# DEPRECATED - Remove with legacy routing logic on 1/2023
|
||||||
|
async def test_addons_info_not_installed(
|
||||||
|
api_client, coresys: CoreSys, repository: Repository
|
||||||
|
):
|
||||||
|
"""Test getting addon info for not installed addon."""
|
||||||
|
resp = await api_client.get(f"/addons/{TEST_ADDON_SLUG}/info")
|
||||||
|
result = await resp.json()
|
||||||
|
assert result["data"]["version_latest"] == "9.2.1"
|
||||||
|
assert result["data"]["version"] is None
|
Loading…
x
Reference in New Issue
Block a user