Skip to content

Commit be8578a

Browse files
committed
Add system health to Portainer
1 parent c1c62e6 commit be8578a

3 files changed

Lines changed: 108 additions & 0 deletions

File tree

homeassistant/components/portainer/strings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,5 +236,10 @@
236236
},
237237
"name": "Prune unused images"
238238
}
239+
},
240+
"system_health": {
241+
"info": {
242+
"can_reach_server": "Reach Portainer server"
243+
}
239244
}
240245
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Provide info to system health."""
2+
3+
from typing import Any
4+
5+
from homeassistant.components import system_health
6+
from homeassistant.const import CONF_URL
7+
from homeassistant.core import HomeAssistant, callback
8+
9+
from .const import DOMAIN
10+
11+
12+
@callback
13+
def async_register(
14+
hass: HomeAssistant, register: system_health.SystemHealthRegistration
15+
) -> None:
16+
"""Register system health callbacks."""
17+
register.async_register_info(system_health_info)
18+
19+
20+
async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
21+
"""Get info for the info page."""
22+
config_entry = hass.config_entries.async_entries(DOMAIN)[0]
23+
24+
return {
25+
"can_reach_server": system_health.async_check_can_reach_url(
26+
hass, f"{config_entry.data[CONF_URL].rstrip('/')}/api/system/status"
27+
),
28+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""Test Portainer system health."""
2+
3+
import asyncio
4+
5+
from aiohttp import ClientError
6+
7+
from homeassistant.components.portainer.const import DOMAIN
8+
from homeassistant.config_entries import ConfigEntryState
9+
from homeassistant.core import HomeAssistant
10+
from homeassistant.setup import async_setup_component
11+
12+
from .conftest import MOCK_TEST_CONFIG, TEST_ENTRY, TEST_INSTANCE_ID
13+
14+
from tests.common import MockConfigEntry, get_system_health_info
15+
from tests.test_util.aiohttp import AiohttpClientMocker
16+
17+
MOCK_HEALTH_URL = "https://127.0.0.1:9000/api/system/status"
18+
19+
20+
async def test_system_health(
21+
hass: HomeAssistant,
22+
aioclient_mock: AiohttpClientMocker,
23+
) -> None:
24+
"""Test system health when server is reachable."""
25+
aioclient_mock.get(MOCK_HEALTH_URL, text="ok")
26+
27+
hass.config.components.add(DOMAIN)
28+
assert await async_setup_component(hass, "system_health", {})
29+
await hass.async_block_till_done()
30+
31+
entry = MockConfigEntry(
32+
domain=DOMAIN,
33+
data=MOCK_TEST_CONFIG,
34+
unique_id=TEST_INSTANCE_ID,
35+
entry_id=TEST_ENTRY,
36+
state=ConfigEntryState.LOADED,
37+
)
38+
entry.add_to_hass(hass)
39+
40+
info = await get_system_health_info(hass, DOMAIN)
41+
42+
for key, val in info.items():
43+
if asyncio.iscoroutine(val):
44+
info[key] = await val
45+
46+
assert info["can_reach_server"] == "ok"
47+
48+
49+
async def test_system_health_failed_connect(
50+
hass: HomeAssistant,
51+
aioclient_mock: AiohttpClientMocker,
52+
) -> None:
53+
"""Test system health when server is unreachable."""
54+
aioclient_mock.get(MOCK_HEALTH_URL, exc=ClientError)
55+
56+
hass.config.components.add(DOMAIN)
57+
assert await async_setup_component(hass, "system_health", {})
58+
await hass.async_block_till_done()
59+
60+
entry = MockConfigEntry(
61+
domain=DOMAIN,
62+
data=MOCK_TEST_CONFIG,
63+
unique_id=TEST_INSTANCE_ID,
64+
entry_id=TEST_ENTRY,
65+
state=ConfigEntryState.LOADED,
66+
)
67+
entry.add_to_hass(hass)
68+
69+
info = await get_system_health_info(hass, DOMAIN)
70+
71+
for key, val in info.items():
72+
if asyncio.iscoroutine(val):
73+
info[key] = await val
74+
75+
assert info["can_reach_server"] == {"error": "unreachable", "type": "failed"}

0 commit comments

Comments
 (0)