Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Add system health component #20436

Merged
merged 14 commits into from
Jan 30, 2019
48 changes: 48 additions & 0 deletions homeassistant/components/system_health/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""System health component."""
from collections import OrderedDict
from typing import Callable, Dict
from aiohttp.web import Request, Response, json_response

from homeassistant.core import callback
from homeassistant.loader import bind_hass
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
from homeassistant.components.http.view import HomeAssistantView

DEPENDENCIES = ['http']
balloob marked this conversation as resolved.
Show resolved Hide resolved
DOMAIN = 'system_health'


@bind_hass
@callback
def async_register_info(hass: HomeAssistantType, domain: str,
info_callback: Callable[[HomeAssistantType], Dict]):
"""Register an info callback."""
data = hass.data.setdefault(
DOMAIN, OrderedDict()).setdefault('info', OrderedDict())
data[domain] = info_callback


async def async_setup(hass: HomeAssistantType, config: ConfigType):
"""Set up the System Health component."""
hass.http.register_view(InfoView)
return True


class InfoView(HomeAssistantView):
"""HTTP endpoint to offer health info."""

url = "/api/system_health/info"
name = "api:system_health:info"

async def get(self, request: Request) -> Response:
"""Handle GET request."""
hass = request.app['hass'] # type: HomeAssistantType
info_callbacks = hass.data.get(DOMAIN, {}).get('info', {})
data = OrderedDict()
data['homeassistant'] = await hass.components.updater.get_system_info()

for domain, info_callback in info_callbacks.items():
print(domain, info_callback)
balloob marked this conversation as resolved.
Show resolved Hide resolved
data[domain] = info_callback(hass)

return json_response(data)
8 changes: 5 additions & 3 deletions homeassistant/components/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
import async_timeout
import voluptuous as vol

from homeassistant.const import ATTR_FRIENDLY_NAME
from homeassistant.const import __version__ as current_version
from homeassistant.const import (
ATTR_FRIENDLY_NAME, __version__ as current_version)
from homeassistant.loader import bind_hass
from homeassistant.helpers import event
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
Expand Down Expand Up @@ -124,7 +125,8 @@ async def check_new_version(now):
return True


async def get_system_info(hass, include_components):
@bind_hass
async def get_system_info(hass, include_components=False):
"""Return info about the system."""
info_object = {
'arch': platform.machine(),
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
# Track the sun
sun:

# Allow diagnosing system problems
system_health:

# Sensors
sensor:
# Weather prediction
Expand Down
1 change: 1 addition & 0 deletions tests/components/system_health/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for the system health component."""
56 changes: 56 additions & 0 deletions tests/components/system_health/test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Tests for the system health component init."""
from unittest.mock import patch

import pytest

from homeassistant.setup import async_setup_component

from tests.common import mock_coro


@pytest.fixture
def mock_system_info():
"""Mock system info."""
with patch('homeassistant.components.updater.get_system_info',
return_value=mock_coro({'hello': True})):
yield


async def test_info_endpoint_requires_auth(hass, aiohttp_client):
"""Test that the info endpoint requires auth."""
assert await async_setup_component(hass, 'system_health', {})
client = await aiohttp_client(hass.http.app)
resp = await client.get('/api/system_health/info')
assert resp.status == 401


async def test_info_endpoint_return_info(hass, hass_client,
mock_system_info):
"""Test that the info endpoint requires auth."""
assert await async_setup_component(hass, 'system_health', {})
client = await hass_client()

resp = await client.get('/api/system_health/info')
assert resp.status == 200
data = await resp.json()

assert len(data) == 1
data = data['homeassistant']
assert data == {'hello': True}


async def test_info_endpoint_register_callback(hass, hass_client,
mock_system_info):
"""Test that the info endpoint requires auth."""
hass.components.system_health.async_register_info(
'lovelace', lambda hass: {'storage': 'YAML'})
assert await async_setup_component(hass, 'system_health', {})
client = await hass_client()

resp = await client.get('/api/system_health/info')
assert resp.status == 200
data = await resp.json()

assert len(data) == 2
data = data['lovelace']
assert data == {'storage': 'YAML'}