mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Enhancements for diagnostics platform (#64670)
This commit is contained in:
parent
e6affb8b88
commit
a56bfe012f
@ -15,7 +15,9 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers import integration_platform
|
from homeassistant.helpers import integration_platform
|
||||||
from homeassistant.helpers.device_registry import DeviceEntry, async_get
|
from homeassistant.helpers.device_registry import DeviceEntry, async_get
|
||||||
from homeassistant.helpers.json import ExtendedJSONEncoder
|
from homeassistant.helpers.json import ExtendedJSONEncoder
|
||||||
|
from homeassistant.helpers.system_info import async_get_system_info
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
from homeassistant.loader import DATA_CUSTOM_COMPONENTS, DATA_INTEGRATIONS, Integration
|
||||||
from homeassistant.util.json import (
|
from homeassistant.util.json import (
|
||||||
find_paths_unserializable_data,
|
find_paths_unserializable_data,
|
||||||
format_unserializable_data,
|
format_unserializable_data,
|
||||||
@ -121,17 +123,42 @@ def handle_get(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_json_file_response(
|
async def _async_get_json_file_response(
|
||||||
|
hass: HomeAssistant,
|
||||||
data: dict | list,
|
data: dict | list,
|
||||||
filename: str,
|
filename: str,
|
||||||
|
domain: str,
|
||||||
d_type: DiagnosticsType,
|
d_type: DiagnosticsType,
|
||||||
d_id: str,
|
d_id: str,
|
||||||
sub_type: DiagnosticsSubType | None = None,
|
sub_type: DiagnosticsSubType | None = None,
|
||||||
sub_id: str | None = None,
|
sub_id: str | None = None,
|
||||||
) -> web.Response:
|
) -> web.Response:
|
||||||
"""Return JSON file from dictionary."""
|
"""Return JSON file from dictionary."""
|
||||||
|
hass_sys_info = await async_get_system_info(hass)
|
||||||
|
hass_sys_info["run_as_root"] = hass_sys_info["user"] == "root"
|
||||||
|
del hass_sys_info["user"]
|
||||||
|
|
||||||
|
integration: Integration = hass.data[DATA_INTEGRATIONS][domain]
|
||||||
|
|
||||||
|
custom_components = {}
|
||||||
|
cc_domain: str
|
||||||
|
cc_obj: Integration
|
||||||
|
for cc_domain, cc_obj in hass.data[DATA_CUSTOM_COMPONENTS].items():
|
||||||
|
custom_components[cc_domain] = {
|
||||||
|
"version": cc_obj.manifest["version"],
|
||||||
|
"requirements": cc_obj.manifest["requirements"],
|
||||||
|
}
|
||||||
try:
|
try:
|
||||||
json_data = json.dumps(data, indent=2, cls=ExtendedJSONEncoder)
|
json_data = json.dumps(
|
||||||
|
{
|
||||||
|
"home_assistant": hass_sys_info,
|
||||||
|
"custom_components": custom_components,
|
||||||
|
"integration_manifest": integration.manifest,
|
||||||
|
"data": data,
|
||||||
|
},
|
||||||
|
indent=2,
|
||||||
|
cls=ExtendedJSONEncoder,
|
||||||
|
)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Failed to serialize to JSON: %s/%s%s. Bad data at %s",
|
"Failed to serialize to JSON: %s/%s%s. Bad data at %s",
|
||||||
@ -189,7 +216,9 @@ class DownloadDiagnosticsView(http.HomeAssistantView):
|
|||||||
return web.Response(status=HTTPStatus.NOT_FOUND)
|
return web.Response(status=HTTPStatus.NOT_FOUND)
|
||||||
data = await info[d_type.value](hass, config_entry)
|
data = await info[d_type.value](hass, config_entry)
|
||||||
filename = f"{d_type}-{filename}"
|
filename = f"{d_type}-{filename}"
|
||||||
return _get_json_file_response(data, filename, d_type.value, d_id)
|
return await _async_get_json_file_response(
|
||||||
|
hass, data, filename, config_entry.domain, d_type.value, d_id
|
||||||
|
)
|
||||||
|
|
||||||
# sub_type handling
|
# sub_type handling
|
||||||
try:
|
try:
|
||||||
@ -210,4 +239,6 @@ class DownloadDiagnosticsView(http.HomeAssistantView):
|
|||||||
return web.Response(status=HTTPStatus.NOT_FOUND)
|
return web.Response(status=HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
data = await info[sub_type.value](hass, config_entry, device)
|
data = await info[sub_type.value](hass, config_entry, device)
|
||||||
return _get_json_file_response(data, filename, d_type, d_id, sub_type, sub_id)
|
return await _async_get_json_file_response(
|
||||||
|
hass, data, filename, config_entry.domain, d_type, d_id, sub_type, sub_id
|
||||||
|
)
|
||||||
|
@ -4,7 +4,7 @@ from http import HTTPStatus
|
|||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
|
||||||
async def get_diagnostics_for_config_entry(hass, hass_client, config_entry):
|
async def _get_diagnostics_for_config_entry(hass, hass_client, config_entry):
|
||||||
"""Return the diagnostics config entry for the specified domain."""
|
"""Return the diagnostics config entry for the specified domain."""
|
||||||
assert await async_setup_component(hass, "diagnostics", {})
|
assert await async_setup_component(hass, "diagnostics", {})
|
||||||
|
|
||||||
@ -16,7 +16,13 @@ async def get_diagnostics_for_config_entry(hass, hass_client, config_entry):
|
|||||||
return await response.json()
|
return await response.json()
|
||||||
|
|
||||||
|
|
||||||
async def get_diagnostics_for_device(hass, hass_client, config_entry, device):
|
async def get_diagnostics_for_config_entry(hass, hass_client, config_entry):
|
||||||
|
"""Return the diagnostics config entry for the specified domain."""
|
||||||
|
data = await _get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
return data["data"]
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_diagnostics_for_device(hass, hass_client, config_entry, device):
|
||||||
"""Return the diagnostics for the specified device."""
|
"""Return the diagnostics for the specified device."""
|
||||||
assert await async_setup_component(hass, "diagnostics", {})
|
assert await async_setup_component(hass, "diagnostics", {})
|
||||||
|
|
||||||
@ -26,3 +32,9 @@ async def get_diagnostics_for_device(hass, hass_client, config_entry, device):
|
|||||||
)
|
)
|
||||||
assert response.status == HTTPStatus.OK
|
assert response.status == HTTPStatus.OK
|
||||||
return await response.json()
|
return await response.json()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_diagnostics_for_device(hass, hass_client, config_entry, device):
|
||||||
|
"""Return the diagnostics for the specified device."""
|
||||||
|
data = await _get_diagnostics_for_device(hass, hass_client, config_entry, device)
|
||||||
|
return data["data"]
|
||||||
|
@ -6,9 +6,10 @@ import pytest
|
|||||||
|
|
||||||
from homeassistant.components.websocket_api.const import TYPE_RESULT
|
from homeassistant.components.websocket_api.const import TYPE_RESULT
|
||||||
from homeassistant.helpers.device_registry import async_get
|
from homeassistant.helpers.device_registry import async_get
|
||||||
|
from homeassistant.helpers.system_info import async_get_system_info
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from . import get_diagnostics_for_config_entry, get_diagnostics_for_device
|
from . import _get_diagnostics_for_config_entry, _get_diagnostics_for_device
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, mock_platform
|
from tests.common import MockConfigEntry, mock_platform
|
||||||
|
|
||||||
@ -77,9 +78,22 @@ async def test_download_diagnostics(hass, hass_client):
|
|||||||
"""Test download diagnostics."""
|
"""Test download diagnostics."""
|
||||||
config_entry = MockConfigEntry(domain="fake_integration")
|
config_entry = MockConfigEntry(domain="fake_integration")
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
hass_sys_info = await async_get_system_info(hass)
|
||||||
|
hass_sys_info["run_as_root"] = hass_sys_info["user"] == "root"
|
||||||
|
del hass_sys_info["user"]
|
||||||
|
|
||||||
assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
|
assert await _get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
|
||||||
"config_entry": "info"
|
"home_assistant": hass_sys_info,
|
||||||
|
"custom_components": {},
|
||||||
|
"integration_manifest": {
|
||||||
|
"codeowners": [],
|
||||||
|
"dependencies": [],
|
||||||
|
"domain": "fake_integration",
|
||||||
|
"is_built_in": True,
|
||||||
|
"name": "fake_integration",
|
||||||
|
"requirements": [],
|
||||||
|
},
|
||||||
|
"data": {"config_entry": "info"},
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_reg = async_get(hass)
|
dev_reg = async_get(hass)
|
||||||
@ -87,9 +101,21 @@ async def test_download_diagnostics(hass, hass_client):
|
|||||||
config_entry_id=config_entry.entry_id, identifiers={("test", "test")}
|
config_entry_id=config_entry.entry_id, identifiers={("test", "test")}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert await get_diagnostics_for_device(
|
assert await _get_diagnostics_for_device(
|
||||||
hass, hass_client, config_entry, device
|
hass, hass_client, config_entry, device
|
||||||
) == {"device": "info"}
|
) == {
|
||||||
|
"home_assistant": hass_sys_info,
|
||||||
|
"custom_components": {},
|
||||||
|
"integration_manifest": {
|
||||||
|
"codeowners": [],
|
||||||
|
"dependencies": [],
|
||||||
|
"domain": "fake_integration",
|
||||||
|
"is_built_in": True,
|
||||||
|
"name": "fake_integration",
|
||||||
|
"requirements": [],
|
||||||
|
},
|
||||||
|
"data": {"device": "info"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_failure_scenarios(hass, hass_client):
|
async def test_failure_scenarios(hass, hass_client):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user