mirror of
https://github.com/Electric-Special/ha-core.git
synced 2026-03-21 05:06:13 +01:00
Add diagnostics to portainer (#153126)
Co-authored-by: Shay Levy <levyshay1@gmail.com> Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
55
homeassistant/components/portainer/diagnostics.py
Normal file
55
homeassistant/components/portainer/diagnostics.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""Diagnostics for the Portainer integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import CONF_API_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import PortainerConfigEntry
|
||||
from .coordinator import PortainerCoordinator
|
||||
|
||||
TO_REDACT = [CONF_API_TOKEN]
|
||||
|
||||
|
||||
def _serialize_coordinator(coordinator: PortainerCoordinator) -> dict[str, Any]:
|
||||
"""Serialize coordinator data into a JSON-safe structure."""
|
||||
|
||||
serialized_endpoints: list[dict[str, Any]] = []
|
||||
for endpoint_id, endpoint_data in coordinator.data.items():
|
||||
serialized_endpoints.append(
|
||||
{
|
||||
"id": endpoint_id,
|
||||
"name": endpoint_data.name,
|
||||
"endpoint": {
|
||||
"status": endpoint_data.endpoint.status,
|
||||
"url": endpoint_data.endpoint.url,
|
||||
"public_url": endpoint_data.endpoint.public_url,
|
||||
},
|
||||
"containers": [
|
||||
{
|
||||
"id": container.id,
|
||||
"names": list(container.names or []),
|
||||
"image": container.image,
|
||||
"state": container.state,
|
||||
"status": container.status,
|
||||
}
|
||||
for container in endpoint_data.containers.values()
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
return {"endpoints": serialized_endpoints}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, config_entry: PortainerConfigEntry
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a Portainer config entry."""
|
||||
|
||||
return {
|
||||
"config_entry": async_redact_data(config_entry.as_dict(), TO_REDACT),
|
||||
"coordinator": _serialize_coordinator(config_entry.runtime_data),
|
||||
}
|
||||
@@ -44,7 +44,7 @@ rules:
|
||||
test-coverage: done
|
||||
# Gold
|
||||
devices: done
|
||||
diagnostics: todo
|
||||
diagnostics: done
|
||||
discovery-update-info:
|
||||
status: exempt
|
||||
comment: |
|
||||
|
||||
88
tests/components/portainer/snapshots/test_diagnostics.ambr
Normal file
88
tests/components/portainer/snapshots/test_diagnostics.ambr
Normal file
@@ -0,0 +1,88 @@
|
||||
# serializer version: 1
|
||||
# name: test_get_config_entry_diagnostics
|
||||
dict({
|
||||
'config_entry': dict({
|
||||
'data': dict({
|
||||
'api_token': '**REDACTED**',
|
||||
'url': 'https://127.0.0.1:9000/',
|
||||
'verify_ssl': True,
|
||||
}),
|
||||
'disabled_by': None,
|
||||
'discovery_keys': dict({
|
||||
}),
|
||||
'domain': 'portainer',
|
||||
'entry_id': 'portainer_test_entry_123',
|
||||
'minor_version': 1,
|
||||
'options': dict({
|
||||
}),
|
||||
'pref_disable_new_entities': False,
|
||||
'pref_disable_polling': False,
|
||||
'source': 'user',
|
||||
'subentries': list([
|
||||
]),
|
||||
'title': 'Portainer test',
|
||||
'unique_id': None,
|
||||
'version': 2,
|
||||
}),
|
||||
'coordinator': dict({
|
||||
'endpoints': list([
|
||||
dict({
|
||||
'containers': list([
|
||||
dict({
|
||||
'id': 'aa86eacfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
|
||||
'image': 'docker.io/library/ubuntu:latest',
|
||||
'names': list([
|
||||
'/funny_chatelet',
|
||||
]),
|
||||
'state': 'running',
|
||||
'status': 'Up 4 days',
|
||||
}),
|
||||
dict({
|
||||
'id': 'bb97facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
|
||||
'image': 'docker.io/library/nginx:latest',
|
||||
'names': list([
|
||||
'/serene_banach',
|
||||
]),
|
||||
'state': 'running',
|
||||
'status': 'Up 2 days',
|
||||
}),
|
||||
dict({
|
||||
'id': 'cc08facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
|
||||
'image': 'docker.io/library/postgres:15',
|
||||
'names': list([
|
||||
'/stoic_turing',
|
||||
]),
|
||||
'state': 'running',
|
||||
'status': 'Up 1 day',
|
||||
}),
|
||||
dict({
|
||||
'id': 'dd19facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
|
||||
'image': 'docker.io/library/redis:7',
|
||||
'names': list([
|
||||
'/focused_einstein',
|
||||
]),
|
||||
'state': 'running',
|
||||
'status': 'Up 12 hours',
|
||||
}),
|
||||
dict({
|
||||
'id': 'ee20facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
|
||||
'image': 'docker.io/library/python:3.13-slim',
|
||||
'names': list([
|
||||
'/practical_morse',
|
||||
]),
|
||||
'state': 'running',
|
||||
'status': 'Up 6 hours',
|
||||
}),
|
||||
]),
|
||||
'endpoint': dict({
|
||||
'public_url': 'docker.mydomain.tld:2375',
|
||||
'status': 1,
|
||||
'url': 'docker.mydomain.tld:2375',
|
||||
}),
|
||||
'id': 1,
|
||||
'name': 'my-environment',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
32
tests/components/portainer/test_diagnostics.py
Normal file
32
tests/components/portainer/test_diagnostics.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""Test the Portainer component diagnostics."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from syrupy.filters import props
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
async def test_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_portainer_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
hass_client: ClientSessionGenerator,
|
||||
) -> None:
|
||||
"""Test if get_config_entry_diagnostics returns the correct data."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
diagnostics_entry = await get_diagnostics_for_config_entry(
|
||||
hass, hass_client, mock_config_entry
|
||||
)
|
||||
assert diagnostics_entry == snapshot(
|
||||
exclude=props("created_at", "modified_at"),
|
||||
)
|
||||
Reference in New Issue
Block a user