mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-11 03:06:33 +00:00
Cleanup API / old rebranding (#3623)
* Cleanup API / old rebranding * cleanup p2 * next round * better comments * cleanup import * support only installed add-ons * legacy migration * test fixes * add old env back * revert for Core * fix issues with old core * fix * using installed short cat * revert * extend legacy * cleanup * fix path * Fix missing * add stop * readd old token * Add minimal * extend attributes * Add repo back * add more repo info * Make it working * Bump frontend to e7848262 (#3680) * Add icon Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
This commit is contained in:
parent
acfa686bb6
commit
e92d8695c7
@ -1 +1 @@
|
|||||||
Subproject commit 4ad49ef07f65431d047094dda7eb6359fe4d8809
|
Subproject commit e7848262ea94af35a5333ce704385da511701240
|
@ -84,8 +84,6 @@ RE_WATCHDOG = re.compile(
|
|||||||
r":\/\/\[HOST\]:(?:\[PORT:)?(?P<t_port>\d+)\]?(?P<s_suffix>.*)$"
|
r":\/\/\[HOST\]:(?:\[PORT:)?(?P<t_port>\d+)\]?(?P<s_suffix>.*)$"
|
||||||
)
|
)
|
||||||
|
|
||||||
RE_OLD_AUDIO = re.compile(r"\d+,\d+")
|
|
||||||
|
|
||||||
WATCHDOG_TIMEOUT = aiohttp.ClientTimeout(total=10)
|
WATCHDOG_TIMEOUT = aiohttp.ClientTimeout(total=10)
|
||||||
|
|
||||||
_OPTIONS_MERGER: Final = Merger(
|
_OPTIONS_MERGER: Final = Merger(
|
||||||
@ -367,13 +365,7 @@ class Addon(AddonModel):
|
|||||||
"""Return a pulse profile for output or None."""
|
"""Return a pulse profile for output or None."""
|
||||||
if not self.with_audio:
|
if not self.with_audio:
|
||||||
return None
|
return None
|
||||||
|
return self.persist.get(ATTR_AUDIO_OUTPUT)
|
||||||
# Fallback with old audio settings
|
|
||||||
# Remove after 210
|
|
||||||
output_data = self.persist.get(ATTR_AUDIO_OUTPUT)
|
|
||||||
if output_data and RE_OLD_AUDIO.fullmatch(output_data):
|
|
||||||
return None
|
|
||||||
return output_data
|
|
||||||
|
|
||||||
@audio_output.setter
|
@audio_output.setter
|
||||||
def audio_output(self, value: Optional[str]):
|
def audio_output(self, value: Optional[str]):
|
||||||
@ -386,12 +378,7 @@ class Addon(AddonModel):
|
|||||||
if not self.with_audio:
|
if not self.with_audio:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Fallback with old audio settings
|
return self.persist.get(ATTR_AUDIO_INPUT)
|
||||||
# Remove after 210
|
|
||||||
input_data = self.persist.get(ATTR_AUDIO_INPUT)
|
|
||||||
if input_data and RE_OLD_AUDIO.fullmatch(input_data):
|
|
||||||
return None
|
|
||||||
return input_data
|
|
||||||
|
|
||||||
@audio_input.setter
|
@audio_input.setter
|
||||||
def audio_input(self, value: Optional[str]) -> None:
|
def audio_input(self, value: Optional[str]) -> None:
|
||||||
|
@ -240,7 +240,7 @@ class RestAPI(CoreSysAttributes):
|
|||||||
[web.get("/available_updates", api_root.available_updates)]
|
[web.get("/available_updates", api_root.available_updates)]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Remove 2023
|
# Remove: 2023
|
||||||
self.webapp.add_routes(
|
self.webapp.add_routes(
|
||||||
[web.get("/supervisor/available_updates", api_root.available_updates)]
|
[web.get("/supervisor/available_updates", api_root.available_updates)]
|
||||||
)
|
)
|
||||||
@ -323,17 +323,22 @@ class RestAPI(CoreSysAttributes):
|
|||||||
web.post("/core/start", api_hass.start),
|
web.post("/core/start", api_hass.start),
|
||||||
web.post("/core/check", api_hass.check),
|
web.post("/core/check", api_hass.check),
|
||||||
web.post("/core/rebuild", api_hass.rebuild),
|
web.post("/core/rebuild", api_hass.rebuild),
|
||||||
# Remove with old Supervisor fallback
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Reroute from legacy
|
||||||
|
self.webapp.add_routes(
|
||||||
|
[
|
||||||
web.get("/homeassistant/info", api_hass.info),
|
web.get("/homeassistant/info", api_hass.info),
|
||||||
web.get("/homeassistant/logs", api_hass.logs),
|
web.get("/homeassistant/logs", api_hass.logs),
|
||||||
web.get("/homeassistant/stats", api_hass.stats),
|
web.get("/homeassistant/stats", api_hass.stats),
|
||||||
web.post("/homeassistant/options", api_hass.options),
|
web.post("/homeassistant/options", api_hass.options),
|
||||||
web.post("/homeassistant/update", api_hass.update),
|
|
||||||
web.post("/homeassistant/restart", api_hass.restart),
|
web.post("/homeassistant/restart", api_hass.restart),
|
||||||
web.post("/homeassistant/stop", api_hass.stop),
|
web.post("/homeassistant/stop", api_hass.stop),
|
||||||
web.post("/homeassistant/start", api_hass.start),
|
web.post("/homeassistant/start", api_hass.start),
|
||||||
web.post("/homeassistant/check", api_hass.check),
|
web.post("/homeassistant/update", api_hass.update),
|
||||||
web.post("/homeassistant/rebuild", api_hass.rebuild),
|
web.post("/homeassistant/rebuild", api_hass.rebuild),
|
||||||
|
web.post("/homeassistant/check", api_hass.check),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -350,7 +355,12 @@ class RestAPI(CoreSysAttributes):
|
|||||||
web.post("/core/api/{path:.+}", api_proxy.api),
|
web.post("/core/api/{path:.+}", api_proxy.api),
|
||||||
web.get("/core/api/{path:.+}", api_proxy.api),
|
web.get("/core/api/{path:.+}", api_proxy.api),
|
||||||
web.get("/core/api/", api_proxy.api),
|
web.get("/core/api/", api_proxy.api),
|
||||||
# Remove with old Supervisor fallback
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Reroute from legacy
|
||||||
|
self.webapp.add_routes(
|
||||||
|
[
|
||||||
web.get("/homeassistant/api/websocket", api_proxy.websocket),
|
web.get("/homeassistant/api/websocket", api_proxy.websocket),
|
||||||
web.get("/homeassistant/websocket", api_proxy.websocket),
|
web.get("/homeassistant/websocket", api_proxy.websocket),
|
||||||
web.get("/homeassistant/api/stream", api_proxy.stream),
|
web.get("/homeassistant/api/stream", api_proxy.stream),
|
||||||
@ -368,7 +378,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.post("/addons/reload", api_addons.reload),
|
|
||||||
web.get("/addons/{addon}/info", api_addons.info),
|
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),
|
||||||
@ -381,10 +390,6 @@ class RestAPI(CoreSysAttributes):
|
|||||||
web.get("/addons/{addon}/options/config", api_addons.options_config),
|
web.get("/addons/{addon}/options/config", api_addons.options_config),
|
||||||
web.post("/addons/{addon}/rebuild", api_addons.rebuild),
|
web.post("/addons/{addon}/rebuild", api_addons.rebuild),
|
||||||
web.get("/addons/{addon}/logs", api_addons.logs),
|
web.get("/addons/{addon}/logs", api_addons.logs),
|
||||||
web.get("/addons/{addon}/icon", api_addons.icon),
|
|
||||||
web.get("/addons/{addon}/logo", api_addons.logo),
|
|
||||||
web.get("/addons/{addon}/changelog", api_addons.changelog),
|
|
||||||
web.get("/addons/{addon}/documentation", api_addons.documentation),
|
|
||||||
web.post("/addons/{addon}/stdin", api_addons.stdin),
|
web.post("/addons/{addon}/stdin", api_addons.stdin),
|
||||||
web.post("/addons/{addon}/security", api_addons.security),
|
web.post("/addons/{addon}/security", api_addons.security),
|
||||||
web.get("/addons/{addon}/stats", api_addons.stats),
|
web.get("/addons/{addon}/stats", api_addons.stats),
|
||||||
@ -412,21 +417,6 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.add_routes(
|
self.webapp.add_routes(
|
||||||
[
|
[
|
||||||
web.get("/snapshots", api_backups.list),
|
|
||||||
web.post("/snapshots/reload", api_backups.reload),
|
|
||||||
web.post("/snapshots/new/full", api_backups.backup_full),
|
|
||||||
web.post("/snapshots/new/partial", api_backups.backup_partial),
|
|
||||||
web.post("/snapshots/new/upload", api_backups.upload),
|
|
||||||
web.get("/snapshots/{slug}/info", api_backups.info),
|
|
||||||
web.delete("/snapshots/{slug}", api_backups.remove),
|
|
||||||
web.post("/snapshots/{slug}/restore/full", api_backups.restore_full),
|
|
||||||
web.post(
|
|
||||||
"/snapshots/{slug}/restore/partial",
|
|
||||||
api_backups.restore_partial,
|
|
||||||
),
|
|
||||||
web.get("/snapshots/{slug}/download", api_backups.download),
|
|
||||||
web.post("/snapshots/{slug}/remove", api_backups.remove),
|
|
||||||
# June 2021: /snapshots was renamed to /backups
|
|
||||||
web.get("/backups", api_backups.list),
|
web.get("/backups", api_backups.list),
|
||||||
web.post("/backups/reload", api_backups.reload),
|
web.post("/backups/reload", api_backups.reload),
|
||||||
web.post("/backups/new/full", api_backups.backup_full),
|
web.post("/backups/new/full", api_backups.backup_full),
|
||||||
@ -521,6 +511,15 @@ class RestAPI(CoreSysAttributes):
|
|||||||
web.get("/store/addons", api_store.addons_list),
|
web.get("/store/addons", api_store.addons_list),
|
||||||
web.get("/store/addons/{addon}", api_store.addons_addon_info),
|
web.get("/store/addons/{addon}", api_store.addons_addon_info),
|
||||||
web.get("/store/addons/{addon}/{version}", api_store.addons_addon_info),
|
web.get("/store/addons/{addon}/{version}", api_store.addons_addon_info),
|
||||||
|
web.get("/store/addons/{addon}/icon", api_store.addons_addon_icon),
|
||||||
|
web.get("/store/addons/{addon}/logo", api_store.addons_addon_logo),
|
||||||
|
web.get(
|
||||||
|
"/store/addons/{addon}/changelog", api_store.addons_addon_changelog
|
||||||
|
),
|
||||||
|
web.get(
|
||||||
|
"/store/addons/{addon}/documentation",
|
||||||
|
api_store.addons_addon_documentation,
|
||||||
|
),
|
||||||
web.post(
|
web.post(
|
||||||
"/store/addons/{addon}/install", api_store.addons_addon_install
|
"/store/addons/{addon}/install", api_store.addons_addon_install
|
||||||
),
|
),
|
||||||
@ -549,8 +548,16 @@ class RestAPI(CoreSysAttributes):
|
|||||||
# Reroute from legacy
|
# Reroute from legacy
|
||||||
self.webapp.add_routes(
|
self.webapp.add_routes(
|
||||||
[
|
[
|
||||||
|
web.post("/addons/reload", api_store.reload),
|
||||||
web.post("/addons/{addon}/install", api_store.addons_addon_install),
|
web.post("/addons/{addon}/install", api_store.addons_addon_install),
|
||||||
web.post("/addons/{addon}/update", api_store.addons_addon_update),
|
web.post("/addons/{addon}/update", api_store.addons_addon_update),
|
||||||
|
web.get("/addons/{addon}/icon", api_store.addons_addon_icon),
|
||||||
|
web.get("/addons/{addon}/logo", api_store.addons_addon_logo),
|
||||||
|
web.get("/addons/{addon}/changelog", api_store.addons_addon_changelog),
|
||||||
|
web.get(
|
||||||
|
"/addons/{addon}/documentation",
|
||||||
|
api_store.addons_addon_documentation,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ from ..const import (
|
|||||||
ATTR_LOGO,
|
ATTR_LOGO,
|
||||||
ATTR_LONG_DESCRIPTION,
|
ATTR_LONG_DESCRIPTION,
|
||||||
ATTR_MACHINE,
|
ATTR_MACHINE,
|
||||||
ATTR_MAINTAINER,
|
|
||||||
ATTR_MEMORY_LIMIT,
|
ATTR_MEMORY_LIMIT,
|
||||||
ATTR_MEMORY_PERCENT,
|
ATTR_MEMORY_PERCENT,
|
||||||
ATTR_MEMORY_USAGE,
|
ATTR_MEMORY_USAGE,
|
||||||
@ -73,12 +72,10 @@ from ..const import (
|
|||||||
ATTR_PROTECTED,
|
ATTR_PROTECTED,
|
||||||
ATTR_PWNED,
|
ATTR_PWNED,
|
||||||
ATTR_RATING,
|
ATTR_RATING,
|
||||||
ATTR_REPOSITORIES,
|
|
||||||
ATTR_REPOSITORY,
|
ATTR_REPOSITORY,
|
||||||
ATTR_SCHEMA,
|
ATTR_SCHEMA,
|
||||||
ATTR_SERVICES,
|
ATTR_SERVICES,
|
||||||
ATTR_SLUG,
|
ATTR_SLUG,
|
||||||
ATTR_SOURCE,
|
|
||||||
ATTR_STAGE,
|
ATTR_STAGE,
|
||||||
ATTR_STARTUP,
|
ATTR_STARTUP,
|
||||||
ATTR_STATE,
|
ATTR_STATE,
|
||||||
@ -95,18 +92,14 @@ from ..const import (
|
|||||||
ATTR_VIDEO,
|
ATTR_VIDEO,
|
||||||
ATTR_WATCHDOG,
|
ATTR_WATCHDOG,
|
||||||
ATTR_WEBUI,
|
ATTR_WEBUI,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
CONTENT_TYPE_PNG,
|
|
||||||
CONTENT_TYPE_TEXT,
|
|
||||||
REQUEST_FROM,
|
REQUEST_FROM,
|
||||||
AddonBoot,
|
AddonBoot,
|
||||||
AddonState,
|
|
||||||
)
|
)
|
||||||
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 APIError, APIForbidden, PwnedError, PwnedSecret
|
||||||
from ..validate import docker_ports
|
from ..validate import docker_ports
|
||||||
from .const import ATTR_SIGNED
|
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
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -133,7 +126,7 @@ SCHEMA_SECURITY = vol.Schema({vol.Optional(ATTR_PROTECTED): vol.Boolean()})
|
|||||||
class APIAddons(CoreSysAttributes):
|
class APIAddons(CoreSysAttributes):
|
||||||
"""Handle RESTful API for add-on functions."""
|
"""Handle RESTful API for add-on functions."""
|
||||||
|
|
||||||
def _extract_addon(self, request: web.Request) -> AnyAddon:
|
def _extract_addon(self, request: web.Request) -> Addon:
|
||||||
"""Return addon, throw an exception it it doesn't exist."""
|
"""Return addon, throw an exception it it doesn't exist."""
|
||||||
addon_slug: str = request.match_info.get("addon")
|
addon_slug: str = request.match_info.get("addon")
|
||||||
|
|
||||||
@ -147,13 +140,9 @@ class APIAddons(CoreSysAttributes):
|
|||||||
addon = self.sys_addons.get(addon_slug)
|
addon = self.sys_addons.get(addon_slug)
|
||||||
if not addon:
|
if not addon:
|
||||||
raise APIError(f"Addon {addon_slug} does not exist")
|
raise APIError(f"Addon {addon_slug} does not exist")
|
||||||
|
|
||||||
return addon
|
|
||||||
|
|
||||||
def _extract_addon_installed(self, request: web.Request) -> Addon:
|
|
||||||
addon = self._extract_addon(request)
|
|
||||||
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 APIError("Addon is not installed")
|
||||||
|
|
||||||
return addon
|
return addon
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
@ -166,11 +155,9 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_DESCRIPTON: addon.description,
|
ATTR_DESCRIPTON: addon.description,
|
||||||
ATTR_ADVANCED: addon.advanced,
|
ATTR_ADVANCED: addon.advanced,
|
||||||
ATTR_STAGE: addon.stage,
|
ATTR_STAGE: addon.stage,
|
||||||
ATTR_VERSION: addon.version if addon.is_installed else None,
|
ATTR_VERSION: addon.version,
|
||||||
ATTR_VERSION_LATEST: addon.latest_version,
|
ATTR_VERSION_LATEST: addon.latest_version,
|
||||||
ATTR_UPDATE_AVAILABLE: addon.need_update
|
ATTR_UPDATE_AVAILABLE: addon.need_update,
|
||||||
if addon.is_installed
|
|
||||||
else False,
|
|
||||||
ATTR_INSTALLED: addon.is_installed,
|
ATTR_INSTALLED: addon.is_installed,
|
||||||
ATTR_AVAILABLE: addon.available,
|
ATTR_AVAILABLE: addon.available,
|
||||||
ATTR_DETACHED: addon.is_detached,
|
ATTR_DETACHED: addon.is_detached,
|
||||||
@ -181,20 +168,10 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_ICON: addon.with_icon,
|
ATTR_ICON: addon.with_icon,
|
||||||
ATTR_LOGO: addon.with_logo,
|
ATTR_LOGO: addon.with_logo,
|
||||||
}
|
}
|
||||||
for addon in self.sys_addons.all
|
for addon in self.sys_addons.installed
|
||||||
]
|
]
|
||||||
|
|
||||||
data_repositories = [
|
return {ATTR_ADDONS: data_addons}
|
||||||
{
|
|
||||||
ATTR_SLUG: repository.slug,
|
|
||||||
ATTR_NAME: repository.name,
|
|
||||||
ATTR_SOURCE: repository.source,
|
|
||||||
ATTR_URL: repository.url,
|
|
||||||
ATTR_MAINTAINER: repository.maintainer,
|
|
||||||
}
|
|
||||||
for repository in self.sys_store.all
|
|
||||||
]
|
|
||||||
return {ATTR_ADDONS: data_addons, ATTR_REPOSITORIES: data_repositories}
|
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def reload(self, request: web.Request) -> None:
|
async def reload(self, request: web.Request) -> None:
|
||||||
@ -215,11 +192,8 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_LONG_DESCRIPTION: addon.long_description,
|
ATTR_LONG_DESCRIPTION: addon.long_description,
|
||||||
ATTR_ADVANCED: addon.advanced,
|
ATTR_ADVANCED: addon.advanced,
|
||||||
ATTR_STAGE: addon.stage,
|
ATTR_STAGE: addon.stage,
|
||||||
ATTR_AUTO_UPDATE: None,
|
|
||||||
ATTR_REPOSITORY: addon.repository,
|
ATTR_REPOSITORY: addon.repository,
|
||||||
ATTR_VERSION: None,
|
|
||||||
ATTR_VERSION_LATEST: addon.latest_version,
|
ATTR_VERSION_LATEST: addon.latest_version,
|
||||||
ATTR_UPDATE_AVAILABLE: False,
|
|
||||||
ATTR_PROTECTED: addon.protected,
|
ATTR_PROTECTED: addon.protected,
|
||||||
ATTR_RATING: rating_security(addon),
|
ATTR_RATING: rating_security(addon),
|
||||||
ATTR_BOOT: addon.boot,
|
ATTR_BOOT: addon.boot,
|
||||||
@ -229,7 +203,6 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_MACHINE: addon.supported_machine,
|
ATTR_MACHINE: addon.supported_machine,
|
||||||
ATTR_HOMEASSISTANT: addon.homeassistant_version,
|
ATTR_HOMEASSISTANT: addon.homeassistant_version,
|
||||||
ATTR_URL: addon.url,
|
ATTR_URL: addon.url,
|
||||||
ATTR_STATE: AddonState.UNKNOWN,
|
|
||||||
ATTR_DETACHED: addon.is_detached,
|
ATTR_DETACHED: addon.is_detached,
|
||||||
ATTR_AVAILABLE: addon.available,
|
ATTR_AVAILABLE: addon.available,
|
||||||
ATTR_BUILD: addon.need_build,
|
ATTR_BUILD: addon.need_build,
|
||||||
@ -242,13 +215,11 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_PRIVILEGED: addon.privileged,
|
ATTR_PRIVILEGED: addon.privileged,
|
||||||
ATTR_FULL_ACCESS: addon.with_full_access,
|
ATTR_FULL_ACCESS: addon.with_full_access,
|
||||||
ATTR_APPARMOR: addon.apparmor,
|
ATTR_APPARMOR: addon.apparmor,
|
||||||
ATTR_DEVICES: addon.static_devices,
|
|
||||||
ATTR_ICON: addon.with_icon,
|
ATTR_ICON: addon.with_icon,
|
||||||
ATTR_LOGO: addon.with_logo,
|
ATTR_LOGO: addon.with_logo,
|
||||||
ATTR_CHANGELOG: addon.with_changelog,
|
ATTR_CHANGELOG: addon.with_changelog,
|
||||||
ATTR_DOCUMENTATION: addon.with_documentation,
|
ATTR_DOCUMENTATION: addon.with_documentation,
|
||||||
ATTR_STDIN: addon.with_stdin,
|
ATTR_STDIN: addon.with_stdin,
|
||||||
ATTR_WEBUI: None,
|
|
||||||
ATTR_HASSIO_API: addon.access_hassio_api,
|
ATTR_HASSIO_API: addon.access_hassio_api,
|
||||||
ATTR_HASSIO_ROLE: addon.hassio_role,
|
ATTR_HASSIO_ROLE: addon.hassio_role,
|
||||||
ATTR_AUTH_API: addon.access_auth_api,
|
ATTR_AUTH_API: addon.access_auth_api,
|
||||||
@ -262,49 +233,35 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_DOCKER_API: addon.access_docker_api,
|
ATTR_DOCKER_API: addon.access_docker_api,
|
||||||
ATTR_VIDEO: addon.with_video,
|
ATTR_VIDEO: addon.with_video,
|
||||||
ATTR_AUDIO: addon.with_audio,
|
ATTR_AUDIO: addon.with_audio,
|
||||||
ATTR_AUDIO_INPUT: None,
|
|
||||||
ATTR_AUDIO_OUTPUT: None,
|
|
||||||
ATTR_STARTUP: addon.startup,
|
ATTR_STARTUP: addon.startup,
|
||||||
ATTR_SERVICES: _pretty_services(addon),
|
ATTR_SERVICES: _pretty_services(addon),
|
||||||
ATTR_DISCOVERY: addon.discovery,
|
ATTR_DISCOVERY: addon.discovery,
|
||||||
ATTR_IP_ADDRESS: None,
|
|
||||||
ATTR_TRANSLATIONS: addon.translations,
|
ATTR_TRANSLATIONS: addon.translations,
|
||||||
ATTR_INGRESS: addon.with_ingress,
|
ATTR_INGRESS: addon.with_ingress,
|
||||||
ATTR_SIGNED: addon.signed,
|
ATTR_SIGNED: addon.signed,
|
||||||
ATTR_INGRESS_ENTRY: None,
|
ATTR_STATE: addon.state,
|
||||||
ATTR_INGRESS_URL: None,
|
ATTR_WEBUI: addon.webui,
|
||||||
ATTR_INGRESS_PORT: None,
|
ATTR_INGRESS_ENTRY: addon.ingress_entry,
|
||||||
ATTR_INGRESS_PANEL: None,
|
ATTR_INGRESS_URL: addon.ingress_url,
|
||||||
ATTR_WATCHDOG: None,
|
ATTR_INGRESS_PORT: addon.ingress_port,
|
||||||
|
ATTR_INGRESS_PANEL: addon.ingress_panel,
|
||||||
|
ATTR_AUDIO_INPUT: addon.audio_input,
|
||||||
|
ATTR_AUDIO_OUTPUT: addon.audio_output,
|
||||||
|
ATTR_AUTO_UPDATE: addon.auto_update,
|
||||||
|
ATTR_IP_ADDRESS: str(addon.ip_address),
|
||||||
|
ATTR_VERSION: addon.version,
|
||||||
|
ATTR_UPDATE_AVAILABLE: addon.need_update,
|
||||||
|
ATTR_WATCHDOG: addon.watchdog,
|
||||||
|
ATTR_DEVICES: addon.static_devices
|
||||||
|
+ [device.path for device in addon.devices],
|
||||||
}
|
}
|
||||||
|
|
||||||
if isinstance(addon, Addon) and addon.is_installed:
|
|
||||||
data.update(
|
|
||||||
{
|
|
||||||
ATTR_STATE: addon.state,
|
|
||||||
ATTR_WEBUI: addon.webui,
|
|
||||||
ATTR_INGRESS_ENTRY: addon.ingress_entry,
|
|
||||||
ATTR_INGRESS_URL: addon.ingress_url,
|
|
||||||
ATTR_INGRESS_PORT: addon.ingress_port,
|
|
||||||
ATTR_INGRESS_PANEL: addon.ingress_panel,
|
|
||||||
ATTR_AUDIO_INPUT: addon.audio_input,
|
|
||||||
ATTR_AUDIO_OUTPUT: addon.audio_output,
|
|
||||||
ATTR_AUTO_UPDATE: addon.auto_update,
|
|
||||||
ATTR_IP_ADDRESS: str(addon.ip_address),
|
|
||||||
ATTR_VERSION: addon.version,
|
|
||||||
ATTR_UPDATE_AVAILABLE: addon.need_update,
|
|
||||||
ATTR_WATCHDOG: addon.watchdog,
|
|
||||||
ATTR_DEVICES: addon.static_devices
|
|
||||||
+ [device.path for device in addon.devices],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def options(self, request: web.Request) -> None:
|
async def options(self, request: web.Request) -> None:
|
||||||
"""Store user options for add-on."""
|
"""Store user options for add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
|
|
||||||
# Update secrets for validation
|
# Update secrets for validation
|
||||||
await self.sys_homeassistant.secrets.reload()
|
await self.sys_homeassistant.secrets.reload()
|
||||||
@ -339,7 +296,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
async def options_validate(self, request: web.Request) -> None:
|
async def options_validate(self, request: web.Request) -> None:
|
||||||
"""Validate user options for add-on."""
|
"""Validate user options for add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
data = {ATTR_MESSAGE: "", ATTR_VALID: True, ATTR_PWNED: False}
|
data = {ATTR_MESSAGE: "", ATTR_VALID: True, ATTR_PWNED: False}
|
||||||
|
|
||||||
options = await request.json(loads=json_loads) or addon.options
|
options = await request.json(loads=json_loads) or addon.options
|
||||||
@ -381,7 +338,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
slug: str = request.match_info.get("addon")
|
slug: str = request.match_info.get("addon")
|
||||||
if slug != "self":
|
if slug != "self":
|
||||||
raise APIForbidden("This can be only read by the Add-on itself!")
|
raise APIForbidden("This can be only read by the Add-on itself!")
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
|
|
||||||
# Lookup/reload secrets
|
# Lookup/reload secrets
|
||||||
await self.sys_homeassistant.secrets.reload()
|
await self.sys_homeassistant.secrets.reload()
|
||||||
@ -393,7 +350,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
async def security(self, request: web.Request) -> None:
|
async def security(self, request: web.Request) -> None:
|
||||||
"""Store security options for add-on."""
|
"""Store security options for add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
body: dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
|
body: dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
|
||||||
|
|
||||||
if ATTR_PROTECTED in body:
|
if ATTR_PROTECTED in body:
|
||||||
@ -405,7 +362,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
async def stats(self, request: web.Request) -> dict[str, Any]:
|
async def stats(self, request: web.Request) -> dict[str, Any]:
|
||||||
"""Return resource information."""
|
"""Return resource information."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
|
|
||||||
stats: DockerStats = await addon.stats()
|
stats: DockerStats = await addon.stats()
|
||||||
|
|
||||||
@ -423,83 +380,43 @@ class APIAddons(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
def uninstall(self, request: web.Request) -> Awaitable[None]:
|
def uninstall(self, request: web.Request) -> Awaitable[None]:
|
||||||
"""Uninstall add-on."""
|
"""Uninstall add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
return asyncio.shield(addon.uninstall())
|
return asyncio.shield(addon.uninstall())
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def start(self, request: web.Request) -> Awaitable[None]:
|
def start(self, request: web.Request) -> Awaitable[None]:
|
||||||
"""Start add-on."""
|
"""Start add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
return asyncio.shield(addon.start())
|
return asyncio.shield(addon.start())
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def stop(self, request: web.Request) -> Awaitable[None]:
|
def stop(self, request: web.Request) -> Awaitable[None]:
|
||||||
"""Stop add-on."""
|
"""Stop add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
return asyncio.shield(addon.stop())
|
return asyncio.shield(addon.stop())
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def restart(self, request: web.Request) -> Awaitable[None]:
|
def restart(self, request: web.Request) -> Awaitable[None]:
|
||||||
"""Restart add-on."""
|
"""Restart add-on."""
|
||||||
addon: Addon = self._extract_addon_installed(request)
|
addon: Addon = self._extract_addon(request)
|
||||||
return asyncio.shield(addon.restart())
|
return asyncio.shield(addon.restart())
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def rebuild(self, request: web.Request) -> Awaitable[None]:
|
def rebuild(self, request: web.Request) -> Awaitable[None]:
|
||||||
"""Rebuild local build add-on."""
|
"""Rebuild local build add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
return asyncio.shield(addon.rebuild())
|
return asyncio.shield(addon.rebuild())
|
||||||
|
|
||||||
@api_process_raw(CONTENT_TYPE_BINARY)
|
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||||
def logs(self, request: web.Request) -> Awaitable[bytes]:
|
def logs(self, request: web.Request) -> Awaitable[bytes]:
|
||||||
"""Return logs from add-on."""
|
"""Return logs from add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
return addon.logs()
|
return addon.logs()
|
||||||
|
|
||||||
@api_process_raw(CONTENT_TYPE_PNG)
|
|
||||||
async def icon(self, request: web.Request) -> bytes:
|
|
||||||
"""Return icon from add-on."""
|
|
||||||
addon = self._extract_addon(request)
|
|
||||||
if not addon.with_icon:
|
|
||||||
raise APIError(f"No icon found for add-on {addon.slug}!")
|
|
||||||
|
|
||||||
with addon.path_icon.open("rb") as png:
|
|
||||||
return png.read()
|
|
||||||
|
|
||||||
@api_process_raw(CONTENT_TYPE_PNG)
|
|
||||||
async def logo(self, request: web.Request) -> bytes:
|
|
||||||
"""Return logo from add-on."""
|
|
||||||
addon = self._extract_addon(request)
|
|
||||||
if not addon.with_logo:
|
|
||||||
raise APIError(f"No logo found for add-on {addon.slug}!")
|
|
||||||
|
|
||||||
with addon.path_logo.open("rb") as png:
|
|
||||||
return png.read()
|
|
||||||
|
|
||||||
@api_process_raw(CONTENT_TYPE_TEXT)
|
|
||||||
async def changelog(self, request: web.Request) -> str:
|
|
||||||
"""Return changelog from add-on."""
|
|
||||||
addon = self._extract_addon(request)
|
|
||||||
if not addon.with_changelog:
|
|
||||||
raise APIError(f"No changelog found for add-on {addon.slug}!")
|
|
||||||
|
|
||||||
with addon.path_changelog.open("r") as changelog:
|
|
||||||
return changelog.read()
|
|
||||||
|
|
||||||
@api_process_raw(CONTENT_TYPE_TEXT)
|
|
||||||
async def documentation(self, request: web.Request) -> str:
|
|
||||||
"""Return documentation from add-on."""
|
|
||||||
addon = self._extract_addon(request)
|
|
||||||
if not addon.with_documentation:
|
|
||||||
raise APIError(f"No documentation found for add-on {addon.slug}!")
|
|
||||||
|
|
||||||
with addon.path_documentation.open("r") as documentation:
|
|
||||||
return documentation.read()
|
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def stdin(self, request: web.Request) -> None:
|
async def stdin(self, request: web.Request) -> None:
|
||||||
"""Write to stdin of add-on."""
|
"""Write to stdin of add-on."""
|
||||||
addon = self._extract_addon_installed(request)
|
addon = self._extract_addon(request)
|
||||||
if not addon.with_stdin:
|
if not addon.with_stdin:
|
||||||
raise APIError(f"STDIN not supported the {addon.slug} add-on")
|
raise APIError(f"STDIN not supported the {addon.slug} add-on")
|
||||||
|
|
||||||
@ -507,6 +424,6 @@ class APIAddons(CoreSysAttributes):
|
|||||||
await asyncio.shield(addon.write_stdin(data))
|
await asyncio.shield(addon.write_stdin(data))
|
||||||
|
|
||||||
|
|
||||||
def _pretty_services(addon: AnyAddon) -> list[str]:
|
def _pretty_services(addon: Addon) -> list[str]:
|
||||||
"""Return a simplified services role list."""
|
"""Return a simplified services role list."""
|
||||||
return [f"{name}:{access}" for name, access in addon.services_role.items()]
|
return [f"{name}:{access}" for name, access in addon.services_role.items()]
|
||||||
|
@ -29,12 +29,12 @@ from ..const import (
|
|||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_VERSION_LATEST,
|
ATTR_VERSION_LATEST,
|
||||||
ATTR_VOLUME,
|
ATTR_VOLUME,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
from ..host.sound import StreamType
|
from ..host.sound import StreamType
|
||||||
from ..validate import version_tag
|
from ..validate import version_tag
|
||||||
|
from .const import CONTENT_TYPE_BINARY
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
@ -8,15 +8,10 @@ from aiohttp.web_exceptions import HTTPUnauthorized
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from ..addons.addon import Addon
|
from ..addons.addon import Addon
|
||||||
from ..const import (
|
from ..const import ATTR_PASSWORD, ATTR_USERNAME, REQUEST_FROM
|
||||||
ATTR_PASSWORD,
|
|
||||||
ATTR_USERNAME,
|
|
||||||
CONTENT_TYPE_JSON,
|
|
||||||
CONTENT_TYPE_URL,
|
|
||||||
REQUEST_FROM,
|
|
||||||
)
|
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIForbidden
|
from ..exceptions import APIForbidden
|
||||||
|
from .const import CONTENT_TYPE_JSON, CONTENT_TYPE_URL
|
||||||
from .utils import api_process, api_validate
|
from .utils import api_process, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
@ -26,17 +26,18 @@ from ..const import (
|
|||||||
ATTR_SLUG,
|
ATTR_SLUG,
|
||||||
ATTR_TYPE,
|
ATTR_TYPE,
|
||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
CONTENT_TYPE_TAR,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
|
from .const import CONTENT_TYPE_TAR
|
||||||
from .utils import api_process, api_validate
|
from .utils import api_process, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
RE_SLUGIFY_NAME = re.compile(r"[^A-Za-z0-9]+")
|
RE_SLUGIFY_NAME = re.compile(r"[^A-Za-z0-9]+")
|
||||||
|
|
||||||
# Backwards compatible / Remove 2022.08
|
# Backwards compatible
|
||||||
|
# Remove: 2022.08
|
||||||
_ALL_FOLDERS = ALL_FOLDERS + [FOLDER_HOMEASSISTANT]
|
_ALL_FOLDERS = ALL_FOLDERS + [FOLDER_HOMEASSISTANT]
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
"""Const for API."""
|
"""Const for API."""
|
||||||
|
|
||||||
|
CONTENT_TYPE_BINARY = "application/octet-stream"
|
||||||
|
CONTENT_TYPE_JSON = "application/json"
|
||||||
|
CONTENT_TYPE_PNG = "image/png"
|
||||||
|
CONTENT_TYPE_TAR = "application/tar"
|
||||||
|
CONTENT_TYPE_TEXT = "text/plain"
|
||||||
|
CONTENT_TYPE_URL = "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
COOKIE_INGRESS = "ingress_session"
|
||||||
|
|
||||||
|
HEADER_TOKEN_OLD = "X-Hassio-Key"
|
||||||
|
HEADER_TOKEN = "X-Supervisor-Token"
|
||||||
|
|
||||||
ATTR_APPARMOR_VERSION = "apparmor_version"
|
ATTR_APPARMOR_VERSION = "apparmor_version"
|
||||||
ATTR_AGENT_VERSION = "agent_version"
|
ATTR_AGENT_VERSION = "agent_version"
|
||||||
ATTR_AVAILABLE_UPDATES = "available_updates"
|
ATTR_AVAILABLE_UPDATES = "available_updates"
|
||||||
@ -19,4 +31,3 @@ ATTR_SIGNED = "signed"
|
|||||||
ATTR_STARTUP_TIME = "startup_time"
|
ATTR_STARTUP_TIME = "startup_time"
|
||||||
ATTR_UPDATE_TYPE = "update_type"
|
ATTR_UPDATE_TYPE = "update_type"
|
||||||
ATTR_USE_NTP = "use_ntp"
|
ATTR_USE_NTP = "use_ntp"
|
||||||
ATTR_USE_RTC = "use_rtc"
|
|
||||||
|
@ -21,12 +21,11 @@ from ..const import (
|
|||||||
ATTR_UPDATE_AVAILABLE,
|
ATTR_UPDATE_AVAILABLE,
|
||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_VERSION_LATEST,
|
ATTR_VERSION_LATEST,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
from ..validate import dns_server_list, version_tag
|
from ..validate import dns_server_list, version_tag
|
||||||
from .const import ATTR_FALLBACK, ATTR_LLMNR, ATTR_MDNS
|
from .const import ATTR_FALLBACK, ATTR_LLMNR, ATTR_MDNS, CONTENT_TYPE_BINARY
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
@ -29,13 +29,12 @@ from ..const import (
|
|||||||
ATTR_UPDATE_AVAILABLE,
|
ATTR_UPDATE_AVAILABLE,
|
||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_VERSION_LATEST,
|
ATTR_VERSION_LATEST,
|
||||||
ATTR_WAIT_BOOT,
|
|
||||||
ATTR_WATCHDOG,
|
ATTR_WATCHDOG,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
from ..validate import docker_image, network_port, version_tag
|
from ..validate import docker_image, network_port, version_tag
|
||||||
|
from .const import CONTENT_TYPE_BINARY
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -48,7 +47,6 @@ SCHEMA_OPTIONS = vol.Schema(
|
|||||||
vol.Optional(ATTR_PORT): network_port,
|
vol.Optional(ATTR_PORT): network_port,
|
||||||
vol.Optional(ATTR_SSL): vol.Boolean(),
|
vol.Optional(ATTR_SSL): vol.Boolean(),
|
||||||
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
|
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
|
||||||
vol.Optional(ATTR_WAIT_BOOT): vol.All(vol.Coerce(int), vol.Range(min=60)),
|
|
||||||
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(str),
|
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(str),
|
||||||
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(str),
|
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(str),
|
||||||
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(str),
|
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(str),
|
||||||
@ -81,11 +79,8 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||||||
ATTR_PORT: self.sys_homeassistant.api_port,
|
ATTR_PORT: self.sys_homeassistant.api_port,
|
||||||
ATTR_SSL: self.sys_homeassistant.api_ssl,
|
ATTR_SSL: self.sys_homeassistant.api_ssl,
|
||||||
ATTR_WATCHDOG: self.sys_homeassistant.watchdog,
|
ATTR_WATCHDOG: self.sys_homeassistant.watchdog,
|
||||||
ATTR_WAIT_BOOT: self.sys_homeassistant.wait_boot,
|
|
||||||
ATTR_AUDIO_INPUT: self.sys_homeassistant.audio_input,
|
ATTR_AUDIO_INPUT: self.sys_homeassistant.audio_input,
|
||||||
ATTR_AUDIO_OUTPUT: self.sys_homeassistant.audio_output,
|
ATTR_AUDIO_OUTPUT: self.sys_homeassistant.audio_output,
|
||||||
# Remove end of Q3 2020
|
|
||||||
"last_version": self.sys_homeassistant.latest_version,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
@ -108,9 +103,6 @@ class APIHomeAssistant(CoreSysAttributes):
|
|||||||
if ATTR_WATCHDOG in body:
|
if ATTR_WATCHDOG in body:
|
||||||
self.sys_homeassistant.watchdog = body[ATTR_WATCHDOG]
|
self.sys_homeassistant.watchdog = body[ATTR_WATCHDOG]
|
||||||
|
|
||||||
if ATTR_WAIT_BOOT in body:
|
|
||||||
self.sys_homeassistant.wait_boot = body[ATTR_WAIT_BOOT]
|
|
||||||
|
|
||||||
if ATTR_REFRESH_TOKEN in body:
|
if ATTR_REFRESH_TOKEN in body:
|
||||||
self.sys_homeassistant.refresh_token = body[ATTR_REFRESH_TOKEN]
|
self.sys_homeassistant.refresh_token = body[ATTR_REFRESH_TOKEN]
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ from ..const import (
|
|||||||
ATTR_SERVICES,
|
ATTR_SERVICES,
|
||||||
ATTR_STATE,
|
ATTR_STATE,
|
||||||
ATTR_TIMEZONE,
|
ATTR_TIMEZONE,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -36,7 +35,7 @@ from .const import (
|
|||||||
ATTR_LLMNR_HOSTNAME,
|
ATTR_LLMNR_HOSTNAME,
|
||||||
ATTR_STARTUP_TIME,
|
ATTR_STARTUP_TIME,
|
||||||
ATTR_USE_NTP,
|
ATTR_USE_NTP,
|
||||||
ATTR_USE_RTC,
|
CONTENT_TYPE_BINARY,
|
||||||
)
|
)
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
@ -70,7 +69,6 @@ class APIHost(CoreSysAttributes):
|
|||||||
ATTR_DT_UTC: self.sys_host.info.dt_utc,
|
ATTR_DT_UTC: self.sys_host.info.dt_utc,
|
||||||
ATTR_DT_SYNCHRONIZED: self.sys_host.info.dt_synchronized,
|
ATTR_DT_SYNCHRONIZED: self.sys_host.info.dt_synchronized,
|
||||||
ATTR_USE_NTP: self.sys_host.info.use_ntp,
|
ATTR_USE_NTP: self.sys_host.info.use_ntp,
|
||||||
ATTR_USE_RTC: self.sys_host.info.use_rtc,
|
|
||||||
ATTR_STARTUP_TIME: self.sys_host.info.startup_time,
|
ATTR_STARTUP_TIME: self.sys_host.info.startup_time,
|
||||||
ATTR_BOOT_TIMESTAMP: self.sys_host.info.boot_timestamp,
|
ATTR_BOOT_TIMESTAMP: self.sys_host.info.boot_timestamp,
|
||||||
ATTR_BROADCAST_LLMNR: self.sys_host.info.broadcast_llmnr,
|
ATTR_BROADCAST_LLMNR: self.sys_host.info.broadcast_llmnr,
|
||||||
@ -101,11 +99,7 @@ class APIHost(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
def reload(self, request):
|
def reload(self, request):
|
||||||
"""Reload host data."""
|
"""Reload host data."""
|
||||||
return asyncio.shield(
|
return asyncio.shield(self.sys_host.reload())
|
||||||
asyncio.wait(
|
|
||||||
[self.sys_host.reload(), self.sys_resolution.evaluate.evaluate_system()]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def services(self, request):
|
async def services(self, request):
|
||||||
|
@ -22,11 +22,9 @@ from ..const import (
|
|||||||
ATTR_PANELS,
|
ATTR_PANELS,
|
||||||
ATTR_SESSION,
|
ATTR_SESSION,
|
||||||
ATTR_TITLE,
|
ATTR_TITLE,
|
||||||
COOKIE_INGRESS,
|
|
||||||
HEADER_TOKEN,
|
|
||||||
HEADER_TOKEN_OLD,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
from .const import COOKIE_INGRESS, HEADER_TOKEN, HEADER_TOKEN_OLD
|
||||||
from .utils import api_process, api_validate, require_home_assistant
|
from .utils import api_process, api_validate, require_home_assistant
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
@ -77,7 +77,6 @@ ADDONS_ROLE_ACCESS = {
|
|||||||
r"^(?:"
|
r"^(?:"
|
||||||
r"|/.+/info"
|
r"|/.+/info"
|
||||||
r"|/backups.*"
|
r"|/backups.*"
|
||||||
r"|/snapshots.*"
|
|
||||||
r")$"
|
r")$"
|
||||||
),
|
),
|
||||||
ROLE_MANAGER: re.compile(
|
ROLE_MANAGER: re.compile(
|
||||||
|
@ -18,11 +18,11 @@ from ..const import (
|
|||||||
ATTR_UPDATE_AVAILABLE,
|
ATTR_UPDATE_AVAILABLE,
|
||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_VERSION_LATEST,
|
ATTR_VERSION_LATEST,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import APIError
|
from ..exceptions import APIError
|
||||||
from ..validate import version_tag
|
from ..validate import version_tag
|
||||||
|
from .const import CONTENT_TYPE_BINARY
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
|
|
||||||
function loadES5() {
|
function loadES5() {
|
||||||
var el = document.createElement('script');
|
var el = document.createElement('script');
|
||||||
el.src = '/api/hassio/app/frontend_es5/entrypoint.073e9cdc.js';
|
el.src = '/api/hassio/app/frontend_es5/entrypoint.f8f83860.js';
|
||||||
document.body.appendChild(el);
|
document.body.appendChild(el);
|
||||||
}
|
}
|
||||||
if (/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent)) {
|
if (/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent)) {
|
||||||
loadES5();
|
loadES5();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
new Function("import('/api/hassio/app/frontend_latest/entrypoint.e7839dce.js')")();
|
new Function("import('/api/hassio/app/frontend_latest/entrypoint.b6cf778b.js')")();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
loadES5();
|
loadES5();
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_es5/166096ca.js.gz
Normal file
BIN
supervisor/api/panel/frontend_es5/166096ca.js.gz
Normal file
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_es5/5600c9ce.js.gz
Normal file
BIN
supervisor/api/panel/frontend_es5/5600c9ce.js.gz
Normal file
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_es5/a9666ad5.js.gz
Normal file
BIN
supervisor/api/panel/frontend_es5/a9666ad5.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_es5/cb70bdfe.js.gz
Normal file
BIN
supervisor/api/panel/frontend_es5/cb70bdfe.js.gz
Normal file
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
2
supervisor/api/panel/frontend_es5/entrypoint.f8f83860.js
Normal file
2
supervisor/api/panel/frontend_es5/entrypoint.f8f83860.js
Normal file
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_es5/entrypoint.f8f83860.js.gz
Normal file
BIN
supervisor/api/panel/frontend_es5/entrypoint.f8f83860.js.gz
Normal file
Binary file not shown.
Binary file not shown.
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.073e9cdc.js"
|
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.f8f83860.js"
|
||||||
}
|
}
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -55,4 +55,4 @@
|
|||||||
--app-header-border-bottom: 1px solid var(--divider-color);
|
--app-header-border-bottom: 1px solid var(--divider-color);
|
||||||
}
|
}
|
||||||
`}}]}}),i.oi)}}]);
|
`}}]}}),i.oi)}}]);
|
||||||
//# sourceMappingURL=99edc920.js.map
|
//# sourceMappingURL=5d68c82a.js.map
|
BIN
supervisor/api/panel/frontend_latest/5d68c82a.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/5d68c82a.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_latest/77d93d88.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/77d93d88.js.gz
Normal file
Binary file not shown.
1
supervisor/api/panel/frontend_latest/77d93d88.js.map
Normal file
1
supervisor/api/panel/frontend_latest/77d93d88.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_latest/7ae7e4b2.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/7ae7e4b2.js.gz
Normal file
Binary file not shown.
1
supervisor/api/panel/frontend_latest/7ae7e4b2.js.map
Normal file
1
supervisor/api/panel/frontend_latest/7ae7e4b2.js.map
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_latest/a573532b.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/a573532b.js.gz
Normal file
Binary file not shown.
1
supervisor/api/panel/frontend_latest/a573532b.js.map
Normal file
1
supervisor/api/panel/frontend_latest/a573532b.js.map
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -108,4 +108,4 @@
|
|||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
`}}]}}),i.oi)},4450:(e,t,r)=>{r.d(t,{I:()=>i,H:()=>n});const i=(0,r(4516).Z)(((e,t)=>t.some((t=>e.includes(t))))),n=(e,t)=>{if(t.startsWith("# Changelog")&&(t=t.substr(12,t.length)),t.includes(`# ${e.version}`)&&t.includes(`# ${e.version_latest}`)){const r=t.split(`# ${e.version}`)[0];r.includes(`# ${e.version_latest}`)&&(t=r)}return t}}}]);
|
`}}]}}),i.oi)},4450:(e,t,r)=>{r.d(t,{I:()=>i,H:()=>n});const i=(0,r(4516).Z)(((e,t)=>t.some((t=>e.includes(t))))),n=(e,t)=>{if(t.startsWith("# Changelog")&&(t=t.substr(12,t.length)),t.includes(`# ${e.version}`)&&t.includes(`# ${e.version_latest}`)){const r=t.split(`# ${e.version}`)[0];r.includes(`# ${e.version_latest}`)&&(t=r)}return t}}}]);
|
||||||
//# sourceMappingURL=fe3336e8.js.map
|
//# sourceMappingURL=bf6a06c2.js.map
|
BIN
supervisor/api/panel/frontend_latest/bf6a06c2.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/bf6a06c2.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_latest/entrypoint.b6cf778b.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/entrypoint.b6cf778b.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
supervisor/api/panel/frontend_latest/faf8e392.js.gz
Normal file
BIN
supervisor/api/panel/frontend_latest/faf8e392.js.gz
Normal file
Binary file not shown.
1
supervisor/api/panel/frontend_latest/faf8e392.js.map
Normal file
1
supervisor/api/panel/frontend_latest/faf8e392.js.map
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"entrypoint.js": "/api/hassio/app/frontend_latest/entrypoint.e7839dce.js"
|
"entrypoint.js": "/api/hassio/app/frontend_latest/entrypoint.b6cf778b.js"
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -8,7 +8,7 @@ import voluptuous as vol
|
|||||||
from ..addons import AnyAddon
|
from ..addons import AnyAddon
|
||||||
from ..addons.utils import rating_security
|
from ..addons.utils import rating_security
|
||||||
from ..api.const import ATTR_SIGNED
|
from ..api.const import ATTR_SIGNED
|
||||||
from ..api.utils import api_process, api_validate
|
from ..api.utils import api_process, api_process_raw, api_validate
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ADDONS,
|
ATTR_ADDONS,
|
||||||
ATTR_ADVANCED,
|
ATTR_ADVANCED,
|
||||||
@ -53,6 +53,7 @@ from ..exceptions import APIError, APIForbidden
|
|||||||
from ..store.addon import AddonStore
|
from ..store.addon import AddonStore
|
||||||
from ..store.repository import Repository
|
from ..store.repository import Repository
|
||||||
from ..store.validate import validate_repository
|
from ..store.validate import validate_repository
|
||||||
|
from .const import CONTENT_TYPE_PNG, CONTENT_TYPE_TEXT
|
||||||
|
|
||||||
SCHEMA_UPDATE = vol.Schema(
|
SCHEMA_UPDATE = vol.Schema(
|
||||||
{
|
{
|
||||||
@ -206,6 +207,46 @@ class APIStore(CoreSysAttributes):
|
|||||||
addon: AddonStore = self._extract_addon(request)
|
addon: AddonStore = self._extract_addon(request)
|
||||||
return self._generate_addon_information(addon, True)
|
return self._generate_addon_information(addon, True)
|
||||||
|
|
||||||
|
@api_process_raw(CONTENT_TYPE_PNG)
|
||||||
|
async def addons_addon_icon(self, request: web.Request) -> bytes:
|
||||||
|
"""Return icon from add-on."""
|
||||||
|
addon = self._extract_addon(request)
|
||||||
|
if not addon.with_icon:
|
||||||
|
raise APIError(f"No icon found for add-on {addon.slug}!")
|
||||||
|
|
||||||
|
with addon.path_icon.open("rb") as png:
|
||||||
|
return png.read()
|
||||||
|
|
||||||
|
@api_process_raw(CONTENT_TYPE_PNG)
|
||||||
|
async def addons_addon_logo(self, request: web.Request) -> bytes:
|
||||||
|
"""Return logo from add-on."""
|
||||||
|
addon = self._extract_addon(request)
|
||||||
|
if not addon.with_logo:
|
||||||
|
raise APIError(f"No logo found for add-on {addon.slug}!")
|
||||||
|
|
||||||
|
with addon.path_logo.open("rb") as png:
|
||||||
|
return png.read()
|
||||||
|
|
||||||
|
@api_process_raw(CONTENT_TYPE_TEXT)
|
||||||
|
async def addons_addon_changelog(self, request: web.Request) -> str:
|
||||||
|
"""Return changelog from add-on."""
|
||||||
|
addon = self._extract_addon(request)
|
||||||
|
if not addon.with_changelog:
|
||||||
|
raise APIError(f"No changelog found for add-on {addon.slug}!")
|
||||||
|
|
||||||
|
with addon.path_changelog.open("r") as changelog:
|
||||||
|
return changelog.read()
|
||||||
|
|
||||||
|
@api_process_raw(CONTENT_TYPE_TEXT)
|
||||||
|
async def addons_addon_documentation(self, request: web.Request) -> str:
|
||||||
|
"""Return documentation from add-on."""
|
||||||
|
addon = self._extract_addon(request)
|
||||||
|
if not addon.with_documentation:
|
||||||
|
raise APIError(f"No documentation found for add-on {addon.slug}!")
|
||||||
|
|
||||||
|
with addon.path_documentation.open("r") as documentation:
|
||||||
|
return documentation.read()
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def repositories_list(self, request: web.Request) -> list[dict[str, Any]]:
|
async def repositories_list(self, request: web.Request) -> list[dict[str, Any]]:
|
||||||
"""Return all repositories."""
|
"""Return all repositories."""
|
||||||
|
@ -17,14 +17,12 @@ from ..const import (
|
|||||||
ATTR_CPU_PERCENT,
|
ATTR_CPU_PERCENT,
|
||||||
ATTR_DEBUG,
|
ATTR_DEBUG,
|
||||||
ATTR_DEBUG_BLOCK,
|
ATTR_DEBUG_BLOCK,
|
||||||
ATTR_DESCRIPTON,
|
|
||||||
ATTR_DIAGNOSTICS,
|
ATTR_DIAGNOSTICS,
|
||||||
ATTR_FORCE_SECURITY,
|
ATTR_FORCE_SECURITY,
|
||||||
ATTR_HEALTHY,
|
ATTR_HEALTHY,
|
||||||
ATTR_ICON,
|
ATTR_ICON,
|
||||||
ATTR_IP_ADDRESS,
|
ATTR_IP_ADDRESS,
|
||||||
ATTR_LOGGING,
|
ATTR_LOGGING,
|
||||||
ATTR_LOGO,
|
|
||||||
ATTR_MEMORY_LIMIT,
|
ATTR_MEMORY_LIMIT,
|
||||||
ATTR_MEMORY_PERCENT,
|
ATTR_MEMORY_PERCENT,
|
||||||
ATTR_MEMORY_USAGE,
|
ATTR_MEMORY_USAGE,
|
||||||
@ -40,7 +38,6 @@ from ..const import (
|
|||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
ATTR_VERSION_LATEST,
|
ATTR_VERSION_LATEST,
|
||||||
ATTR_WAIT_BOOT,
|
ATTR_WAIT_BOOT,
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
LogLevel,
|
LogLevel,
|
||||||
UpdateChannel,
|
UpdateChannel,
|
||||||
)
|
)
|
||||||
@ -49,6 +46,7 @@ from ..exceptions import APIError
|
|||||||
from ..store.validate import repositories
|
from ..store.validate import repositories
|
||||||
from ..utils.validate import validate_timezone
|
from ..utils.validate import validate_timezone
|
||||||
from ..validate import version_tag, wait_boot
|
from ..validate import version_tag, wait_boot
|
||||||
|
from .const import CONTENT_TYPE_BINARY
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -83,23 +81,6 @@ class APISupervisor(CoreSysAttributes):
|
|||||||
@api_process
|
@api_process
|
||||||
async def info(self, request: web.Request) -> dict[str, Any]:
|
async def info(self, request: web.Request) -> dict[str, Any]:
|
||||||
"""Return host information."""
|
"""Return host information."""
|
||||||
list_addons = []
|
|
||||||
for addon in self.sys_addons.installed:
|
|
||||||
list_addons.append(
|
|
||||||
{
|
|
||||||
ATTR_NAME: addon.name,
|
|
||||||
ATTR_SLUG: addon.slug,
|
|
||||||
ATTR_DESCRIPTON: addon.description,
|
|
||||||
ATTR_STATE: addon.state,
|
|
||||||
ATTR_VERSION: addon.version,
|
|
||||||
ATTR_VERSION_LATEST: addon.latest_version,
|
|
||||||
ATTR_UPDATE_AVAILABLE: addon.need_update,
|
|
||||||
ATTR_REPOSITORY: addon.repository,
|
|
||||||
ATTR_ICON: addon.with_icon,
|
|
||||||
ATTR_LOGO: addon.with_logo,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ATTR_VERSION: self.sys_supervisor.version,
|
ATTR_VERSION: self.sys_supervisor.version,
|
||||||
ATTR_VERSION_LATEST: self.sys_supervisor.latest_version,
|
ATTR_VERSION_LATEST: self.sys_supervisor.latest_version,
|
||||||
@ -115,8 +96,24 @@ class APISupervisor(CoreSysAttributes):
|
|||||||
ATTR_DEBUG: self.sys_config.debug,
|
ATTR_DEBUG: self.sys_config.debug,
|
||||||
ATTR_DEBUG_BLOCK: self.sys_config.debug_block,
|
ATTR_DEBUG_BLOCK: self.sys_config.debug_block,
|
||||||
ATTR_DIAGNOSTICS: self.sys_config.diagnostics,
|
ATTR_DIAGNOSTICS: self.sys_config.diagnostics,
|
||||||
ATTR_ADDONS: list_addons,
|
# Depricated
|
||||||
ATTR_ADDONS_REPOSITORIES: self.sys_store.repository_urls,
|
ATTR_ADDONS: [
|
||||||
|
{
|
||||||
|
ATTR_NAME: addon.name,
|
||||||
|
ATTR_SLUG: addon.slug,
|
||||||
|
ATTR_VERSION: addon.version,
|
||||||
|
ATTR_VERSION_LATEST: addon.latest_version,
|
||||||
|
ATTR_UPDATE_AVAILABLE: addon.need_update,
|
||||||
|
ATTR_STATE: addon.state,
|
||||||
|
ATTR_REPOSITORY: addon.repository,
|
||||||
|
ATTR_ICON: addon.with_icon,
|
||||||
|
}
|
||||||
|
for addon in self.sys_addons.local.values()
|
||||||
|
],
|
||||||
|
ATTR_ADDONS_REPOSITORIES: [
|
||||||
|
{ATTR_NAME: store.name, ATTR_SLUG: store.slug}
|
||||||
|
for store in self.sys_store.all
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
@ -146,18 +143,11 @@ class APISupervisor(CoreSysAttributes):
|
|||||||
if ATTR_LOGGING in body:
|
if ATTR_LOGGING in body:
|
||||||
self.sys_config.logging = body[ATTR_LOGGING]
|
self.sys_config.logging = body[ATTR_LOGGING]
|
||||||
|
|
||||||
# REMOVE: 2021.7
|
|
||||||
if ATTR_CONTENT_TRUST in body:
|
|
||||||
self.sys_security.content_trust = body[ATTR_CONTENT_TRUST]
|
|
||||||
|
|
||||||
# REMOVE: 2021.7
|
|
||||||
if ATTR_FORCE_SECURITY in body:
|
|
||||||
self.sys_security.force = body[ATTR_FORCE_SECURITY]
|
|
||||||
|
|
||||||
# Save changes before processing addons in case of errors
|
# Save changes before processing addons in case of errors
|
||||||
self.sys_updater.save_data()
|
self.sys_updater.save_data()
|
||||||
self.sys_config.save_data()
|
self.sys_config.save_data()
|
||||||
|
|
||||||
|
# Remove: 2022.9
|
||||||
if ATTR_ADDONS_REPOSITORIES in body:
|
if ATTR_ADDONS_REPOSITORIES in body:
|
||||||
await asyncio.shield(
|
await asyncio.shield(
|
||||||
self.sys_store.update_repositories(set(body[ATTR_ADDONS_REPOSITORIES]))
|
self.sys_store.update_repositories(set(body[ATTR_ADDONS_REPOSITORIES]))
|
||||||
|
@ -10,9 +10,6 @@ import voluptuous as vol
|
|||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
CONTENT_TYPE_BINARY,
|
|
||||||
HEADER_TOKEN,
|
|
||||||
HEADER_TOKEN_OLD,
|
|
||||||
JSON_DATA,
|
JSON_DATA,
|
||||||
JSON_MESSAGE,
|
JSON_MESSAGE,
|
||||||
JSON_RESULT,
|
JSON_RESULT,
|
||||||
@ -25,22 +22,20 @@ from ..exceptions import APIError, APIForbidden, DockerAPIError, HassioError
|
|||||||
from ..utils import check_exception_chain, get_message_from_exception_chain
|
from ..utils import check_exception_chain, get_message_from_exception_chain
|
||||||
from ..utils.json import JSONEncoder
|
from ..utils.json import JSONEncoder
|
||||||
from ..utils.log_format import format_message
|
from ..utils.log_format import format_message
|
||||||
|
from .const import CONTENT_TYPE_BINARY, HEADER_TOKEN, HEADER_TOKEN_OLD
|
||||||
|
|
||||||
|
|
||||||
def excract_supervisor_token(request: web.Request) -> Optional[str]:
|
def excract_supervisor_token(request: web.Request) -> Optional[str]:
|
||||||
"""Extract Supervisor token from request."""
|
"""Extract Supervisor token from request."""
|
||||||
supervisor_token = request.headers.get(HEADER_TOKEN)
|
if supervisor_token := request.headers.get(HEADER_TOKEN):
|
||||||
if supervisor_token:
|
|
||||||
return supervisor_token
|
return supervisor_token
|
||||||
|
|
||||||
# Remove with old Supervisor fallback
|
# Old Supervisor fallback
|
||||||
supervisor_token = request.headers.get(HEADER_TOKEN_OLD)
|
if supervisor_token := request.headers.get(HEADER_TOKEN_OLD):
|
||||||
if supervisor_token:
|
|
||||||
return supervisor_token
|
return supervisor_token
|
||||||
|
|
||||||
# API access only
|
# API access only
|
||||||
supervisor_token = request.headers.get(AUTHORIZATION)
|
if supervisor_token := request.headers.get(AUTHORIZATION):
|
||||||
if supervisor_token:
|
|
||||||
return supervisor_token.split(" ")[-1]
|
return supervisor_token.split(" ")[-1]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -68,21 +68,6 @@ JSON_RESULT = "result"
|
|||||||
RESULT_ERROR = "error"
|
RESULT_ERROR = "error"
|
||||||
RESULT_OK = "ok"
|
RESULT_OK = "ok"
|
||||||
|
|
||||||
CONTENT_TYPE_BINARY = "application/octet-stream"
|
|
||||||
CONTENT_TYPE_JSON = "application/json"
|
|
||||||
CONTENT_TYPE_PNG = "image/png"
|
|
||||||
CONTENT_TYPE_TAR = "application/tar"
|
|
||||||
CONTENT_TYPE_TEXT = "text/plain"
|
|
||||||
CONTENT_TYPE_URL = "application/x-www-form-urlencoded"
|
|
||||||
COOKIE_INGRESS = "ingress_session"
|
|
||||||
|
|
||||||
HEADER_TOKEN = "X-Supervisor-Token"
|
|
||||||
HEADER_TOKEN_OLD = "X-Hassio-Key"
|
|
||||||
|
|
||||||
ENV_TIME = "TZ"
|
|
||||||
ENV_TOKEN = "SUPERVISOR_TOKEN"
|
|
||||||
ENV_TOKEN_HASSIO = "HASSIO_TOKEN"
|
|
||||||
|
|
||||||
ENV_HOMEASSISTANT_REPOSITORY = "HOMEASSISTANT_REPOSITORY"
|
ENV_HOMEASSISTANT_REPOSITORY = "HOMEASSISTANT_REPOSITORY"
|
||||||
ENV_SUPERVISOR_DEV = "SUPERVISOR_DEV"
|
ENV_SUPERVISOR_DEV = "SUPERVISOR_DEV"
|
||||||
ENV_SUPERVISOR_MACHINE = "SUPERVISOR_MACHINE"
|
ENV_SUPERVISOR_MACHINE = "SUPERVISOR_MACHINE"
|
||||||
|
@ -97,7 +97,6 @@ DBUS_ATTR_LAST_ERROR = "LastError"
|
|||||||
DBUS_ATTR_LLMNR = "LLMNR"
|
DBUS_ATTR_LLMNR = "LLMNR"
|
||||||
DBUS_ATTR_LLMNR_HOSTNAME = "LLMNRHostname"
|
DBUS_ATTR_LLMNR_HOSTNAME = "LLMNRHostname"
|
||||||
DBUS_ATTR_LOADER_TIMESTAMP_MONOTONIC = "LoaderTimestampMonotonic"
|
DBUS_ATTR_LOADER_TIMESTAMP_MONOTONIC = "LoaderTimestampMonotonic"
|
||||||
DBUS_ATTR_LOCALRTC = "LocalRTC"
|
|
||||||
DBUS_ATTR_MANAGED = "Managed"
|
DBUS_ATTR_MANAGED = "Managed"
|
||||||
DBUS_ATTR_MODE = "Mode"
|
DBUS_ATTR_MODE = "Mode"
|
||||||
DBUS_ATTR_MULTICAST_DNS = "MulticastDNS"
|
DBUS_ATTR_MULTICAST_DNS = "MulticastDNS"
|
||||||
|
@ -7,7 +7,6 @@ from ..exceptions import DBusError, DBusInterfaceError
|
|||||||
from ..utils.dbus import DBus
|
from ..utils.dbus import DBus
|
||||||
from ..utils.dt import utc_from_timestamp
|
from ..utils.dt import utc_from_timestamp
|
||||||
from .const import (
|
from .const import (
|
||||||
DBUS_ATTR_LOCALRTC,
|
|
||||||
DBUS_ATTR_NTP,
|
DBUS_ATTR_NTP,
|
||||||
DBUS_ATTR_NTPSYNCHRONIZED,
|
DBUS_ATTR_NTPSYNCHRONIZED,
|
||||||
DBUS_ATTR_TIMEUSEC,
|
DBUS_ATTR_TIMEUSEC,
|
||||||
@ -37,12 +36,6 @@ class TimeDate(DBusInterface):
|
|||||||
"""Return host timezone."""
|
"""Return host timezone."""
|
||||||
return self.properties[DBUS_ATTR_TIMEZONE]
|
return self.properties[DBUS_ATTR_TIMEZONE]
|
||||||
|
|
||||||
@property
|
|
||||||
@dbus_property
|
|
||||||
def local_rtc(self) -> bool:
|
|
||||||
"""Return if a local RTC exists."""
|
|
||||||
return self.properties[DBUS_ATTR_LOCALRTC]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@dbus_property
|
@dbus_property
|
||||||
def ntp(self) -> bool:
|
def ntp(self) -> bool:
|
||||||
|
@ -17,9 +17,6 @@ from ..addons.build import AddonBuild
|
|||||||
from ..bus import EventListener
|
from ..bus import EventListener
|
||||||
from ..const import (
|
from ..const import (
|
||||||
DOCKER_CPU_RUNTIME_ALLOCATION,
|
DOCKER_CPU_RUNTIME_ALLOCATION,
|
||||||
ENV_TIME,
|
|
||||||
ENV_TOKEN,
|
|
||||||
ENV_TOKEN_HASSIO,
|
|
||||||
MAP_ADDONS,
|
MAP_ADDONS,
|
||||||
MAP_BACKUP,
|
MAP_BACKUP,
|
||||||
MAP_CONFIG,
|
MAP_CONFIG,
|
||||||
@ -46,7 +43,14 @@ from ..hardware.data import Device
|
|||||||
from ..jobs.decorator import Job, JobCondition
|
from ..jobs.decorator import Job, JobCondition
|
||||||
from ..resolution.const import ContextType, IssueType, SuggestionType
|
from ..resolution.const import ContextType, IssueType, SuggestionType
|
||||||
from ..utils import process_lock
|
from ..utils import process_lock
|
||||||
from .const import DBUS_PATH, DBUS_VOLUME, Capabilities
|
from .const import (
|
||||||
|
DBUS_PATH,
|
||||||
|
DBUS_VOLUME,
|
||||||
|
ENV_TIME,
|
||||||
|
ENV_TOKEN,
|
||||||
|
ENV_TOKEN_OLD,
|
||||||
|
Capabilities,
|
||||||
|
)
|
||||||
from .interface import DockerInterface
|
from .interface import DockerInterface
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -128,7 +132,7 @@ class DockerAddon(DockerInterface):
|
|||||||
**addon_env,
|
**addon_env,
|
||||||
ENV_TIME: self.sys_timezone,
|
ENV_TIME: self.sys_timezone,
|
||||||
ENV_TOKEN: self.addon.supervisor_token,
|
ENV_TOKEN: self.addon.supervisor_token,
|
||||||
ENV_TOKEN_HASSIO: self.addon.supervisor_token,
|
ENV_TOKEN_OLD: self.addon.supervisor_token,
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -4,15 +4,10 @@ from typing import Optional
|
|||||||
|
|
||||||
import docker
|
import docker
|
||||||
|
|
||||||
from ..const import (
|
from ..const import DOCKER_CPU_RUNTIME_ALLOCATION, MACHINE_ID
|
||||||
DOCKER_CPU_RUNTIME_ALLOCATION,
|
|
||||||
ENV_SUPERVISOR_MACHINE,
|
|
||||||
ENV_TIME,
|
|
||||||
MACHINE_ID,
|
|
||||||
)
|
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..hardware.const import PolicyGroup
|
from ..hardware.const import PolicyGroup
|
||||||
from .const import Capabilities
|
from .const import ENV_TIME, Capabilities
|
||||||
from .interface import DockerInterface
|
from .interface import DockerInterface
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -101,7 +96,6 @@ class DockerAudio(DockerInterface, CoreSysAttributes):
|
|||||||
device_cgroup_rules=self.cgroups_rules,
|
device_cgroup_rules=self.cgroups_rules,
|
||||||
environment={
|
environment={
|
||||||
ENV_TIME: self.sys_timezone,
|
ENV_TIME: self.sys_timezone,
|
||||||
ENV_SUPERVISOR_MACHINE: self.sys_machine,
|
|
||||||
},
|
},
|
||||||
volumes=self.volumes,
|
volumes=self.volumes,
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
"""HA Cli docker object."""
|
"""HA Cli docker object."""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from ..const import ENV_TIME, ENV_TOKEN
|
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
from .const import ENV_TIME, ENV_TOKEN
|
||||||
from .interface import DockerInterface
|
from .interface import DockerInterface
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
@ -19,3 +19,7 @@ class Capabilities(str, Enum):
|
|||||||
|
|
||||||
DBUS_PATH = "/run/dbus"
|
DBUS_PATH = "/run/dbus"
|
||||||
DBUS_VOLUME = {"bind": DBUS_PATH, "mode": "ro"}
|
DBUS_VOLUME = {"bind": DBUS_PATH, "mode": "ro"}
|
||||||
|
|
||||||
|
ENV_TIME = "TZ"
|
||||||
|
ENV_TOKEN = "SUPERVISOR_TOKEN"
|
||||||
|
ENV_TOKEN_OLD = "HASSIO_TOKEN"
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user