From 0e1fb0daeb02e2385c636a67a1012896c2100976 Mon Sep 17 00:00:00 2001 From: mib1185 Date: Mon, 20 Jul 2026 19:03:24 +0000 Subject: [PATCH] add diagnostics --- .../components/librenms/diagnostics.py | 42 +++ .../components/librenms/quality_scale.yaml | 2 +- .../librenms/snapshots/test_diagnostics.ambr | 300 ++++++++++++++++++ tests/components/librenms/test_diagnostics.py | 31 ++ 4 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/librenms/diagnostics.py create mode 100644 tests/components/librenms/snapshots/test_diagnostics.ambr create mode 100644 tests/components/librenms/test_diagnostics.py diff --git a/homeassistant/components/librenms/diagnostics.py b/homeassistant/components/librenms/diagnostics.py new file mode 100644 index 000000000000..a1415b939e2d --- /dev/null +++ b/homeassistant/components/librenms/diagnostics.py @@ -0,0 +1,42 @@ +"""Diagnostics support for LibreNMS.""" + +from dataclasses import asdict +from typing import Any + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.const import CONF_API_KEY, CONF_HOST +from homeassistant.core import HomeAssistant + +from .coordinator import LibrenmsConfigEntry + +TO_REDACT_ENTRY = {CONF_API_KEY, CONF_HOST} +TO_REDACT_DATA = { + "authname", + "authpass", + "community", + "cryptopass", + "dependency_parent_hostname", + "display", + "hostname", + "ip", + "lat", + "lng", + "location", + "notes", + "overwrite_ip", + "serial", + "sys_contact", + "sys_name", +} + + +async def async_get_config_entry_diagnostics( + hass: HomeAssistant, entry: LibrenmsConfigEntry +) -> dict[str, Any]: + """Return diagnostics for a config entry.""" + coordinator = entry.runtime_data + + return { + "entry": async_redact_data(entry.as_dict(), TO_REDACT_ENTRY), + "data": async_redact_data(asdict(coordinator.data), TO_REDACT_DATA), + } diff --git a/homeassistant/components/librenms/quality_scale.yaml b/homeassistant/components/librenms/quality_scale.yaml index caed96e9b947..17a61715387e 100644 --- a/homeassistant/components/librenms/quality_scale.yaml +++ b/homeassistant/components/librenms/quality_scale.yaml @@ -45,7 +45,7 @@ rules: # Gold devices: done - diagnostics: todo + diagnostics: done discovery-update-info: status: exempt comment: Service can't be discovered diff --git a/tests/components/librenms/snapshots/test_diagnostics.ambr b/tests/components/librenms/snapshots/test_diagnostics.ambr new file mode 100644 index 000000000000..f18b246621dd --- /dev/null +++ b/tests/components/librenms/snapshots/test_diagnostics.ambr @@ -0,0 +1,300 @@ +# serializer version: 1 +# name: test_entry_diagnostics + dict({ + 'data': dict({ + 'devices': list([ + dict({ + 'agent_uptime': 0, + 'authalgo': None, + 'authlevel': None, + 'authname': None, + 'authpass': None, + 'bgp_local_as': None, + 'community': '**REDACTED**', + 'cryptoalgo': None, + 'cryptopass': None, + 'dependency_parent_hostname': None, + 'dependency_parent_id': None, + 'device_id': 3, + 'disable_notify': True, + 'disabled': False, + 'display': '**REDACTED**', + 'display_template': 'Drucker', + 'features': None, + 'hardware': 'MC2425adw', + 'hostname': '**REDACTED**', + 'icon': 'lexmark.svg', + 'ignore': False, + 'ignore_status': False, + 'inserted': '2023-09-16T11:34:51', + 'ip': '**REDACTED**', + 'last_discovered': '2026-07-13T20:00:07', + 'last_discovered_timetaken': 2.7769849300385, + 'last_ping': '2026-07-13T22:20:03', + 'last_ping_timetaken': 0.812, + 'last_poll_attempted': None, + 'last_polled': '2026-07-13T22:17:46', + 'last_polled_timetaken': 1.7405550479889, + 'lat': None, + 'lng': None, + 'location': '**REDACTED**', + 'location_id': 3, + 'max_depth': 0, + 'mtu_status': True, + 'notes': None, + 'os': 'lexmarkprinter', + 'override_sys_location': False, + 'overwrite_ip': '', + 'poller_group': 0, + 'port': 161, + 'port_association_mode': 1, + 'purpose': '', + 'retries': None, + 'serial': '**REDACTED**', + 'snmp_disable': False, + 'snmp_engine_id': '', + 'snmpver': 'v2c', + 'status': True, + 'status_reason': '', + 'sys_contact': '**REDACTED**', + 'sys_descr': 'Lexmark MC2425adw version CXNZJ.250.038 kernel 6.6.86-yocto-standard All-N-1', + 'sys_name': '**REDACTED**', + 'sys_object_id': '.1.3.6.1.4.1.641.52.71107331', + 'timeout': None, + 'transport': 'udp', + 'type': 'printer', + 'uptime': 15830868, + 'version': 'CXNZJ.250.038', + }), + dict({ + 'agent_uptime': 0, + 'authalgo': None, + 'authlevel': None, + 'authname': None, + 'authpass': None, + 'bgp_local_as': None, + 'community': '**REDACTED**', + 'cryptoalgo': None, + 'cryptopass': None, + 'dependency_parent_hostname': '**REDACTED**', + 'dependency_parent_id': '5', + 'device_id': 13, + 'disable_notify': False, + 'disabled': False, + 'display': '**REDACTED**', + 'display_template': None, + 'features': 'Home Assistant OS 18.1', + 'hardware': 'QEMU Standard PC (i440FX + PIIX, 1996)', + 'hostname': '**REDACTED**', + 'icon': 'linux.svg', + 'ignore': False, + 'ignore_status': False, + 'inserted': '2023-09-23T19:45:29', + 'ip': '**REDACTED**', + 'last_discovered': '2026-07-13T20:00:10', + 'last_discovered_timetaken': 2.8492691516876, + 'last_ping': '2026-07-13T22:20:03', + 'last_ping_timetaken': 0.772, + 'last_poll_attempted': None, + 'last_polled': '2026-07-13T22:17:06', + 'last_polled_timetaken': 1.6433110237122, + 'lat': None, + 'lng': None, + 'location': '**REDACTED**', + 'location_id': 4, + 'max_depth': 2, + 'mtu_status': True, + 'notes': None, + 'os': 'linux', + 'override_sys_location': True, + 'overwrite_ip': '', + 'poller_group': 0, + 'port': 161, + 'port_association_mode': 1, + 'purpose': '', + 'retries': None, + 'serial': None, + 'snmp_disable': False, + 'snmp_engine_id': ''' + 80 00 1F 88 80 E7 73 4D 32 ED 2A 54 6A 00 00 00 + 00 + ''', + 'snmpver': 'v2c', + 'status': True, + 'status_reason': '', + 'sys_contact': '**REDACTED**', + 'sys_descr': 'Linux homeassistant 6.18.37-haos #1 SMP PREEMPT_DYNAMIC Wed Jul 1 07:35:33 UTC 2026 x86_64 (Home Assistant OS 18.1)', + 'sys_name': '**REDACTED**', + 'sys_object_id': '.1.3.6.1.4.1.8072.3.2.10', + 'timeout': None, + 'transport': 'udp', + 'type': 'server', + 'uptime': 72931, + 'version': '6.18.37-haos', + }), + dict({ + 'agent_uptime': 0, + 'authalgo': None, + 'authlevel': None, + 'authname': None, + 'authpass': None, + 'bgp_local_as': None, + 'community': '**REDACTED**', + 'cryptoalgo': None, + 'cryptopass': None, + 'dependency_parent_hostname': '**REDACTED**', + 'dependency_parent_id': '5', + 'device_id': 1, + 'disable_notify': False, + 'disabled': False, + 'display': '**REDACTED**', + 'display_template': 'SophosXG', + 'features': None, + 'hardware': 'SFVH_KV01_SFOS', + 'hostname': '**REDACTED**', + 'icon': 'sophos-xg.png', + 'ignore': False, + 'ignore_status': False, + 'inserted': '2023-09-16T11:29:40', + 'ip': '**REDACTED**', + 'last_discovered': '2026-07-13T20:00:04', + 'last_discovered_timetaken': 2.6829509735107, + 'last_ping': '2026-07-13T22:20:03', + 'last_ping_timetaken': 0.149, + 'last_poll_attempted': None, + 'last_polled': '2026-07-13T22:19:47', + 'last_polled_timetaken': 1.6974771022797, + 'lat': None, + 'lng': None, + 'location': '**REDACTED**', + 'location_id': 1, + 'max_depth': 2, + 'mtu_status': True, + 'notes': None, + 'os': 'sophos-xg', + 'override_sys_location': False, + 'overwrite_ip': '', + 'poller_group': 0, + 'port': 161, + 'port_association_mode': 1, + 'purpose': '', + 'retries': None, + 'serial': '**REDACTED**', + 'snmp_disable': False, + 'snmp_engine_id': '80 00 1F 88 80 BD 17 B9 64 41 DA 99 64', + 'snmpver': 'v2c', + 'status': True, + 'status_reason': '', + 'sys_contact': '**REDACTED**', + 'sys_descr': 'Linux localhost 6.6.116 #1 SMP Fri Feb 27 22:12:13 CST 2026 x86_64', + 'sys_name': '**REDACTED**', + 'sys_object_id': '.1.3.6.1.4.1.2604.5', + 'timeout': None, + 'transport': 'udp', + 'type': 'appliance', + 'uptime': 2592289, + 'version': '22.0.1 MR-1-Build490', + }), + dict({ + 'agent_uptime': 0, + 'authalgo': None, + 'authlevel': None, + 'authname': None, + 'authpass': None, + 'bgp_local_as': None, + 'community': None, + 'cryptoalgo': None, + 'cryptopass': None, + 'dependency_parent_hostname': None, + 'dependency_parent_id': None, + 'device_id': 29, + 'disable_notify': False, + 'disabled': False, + 'display': '**REDACTED**', + 'display_template': None, + 'features': None, + 'hardware': '', + 'hostname': '**REDACTED**', + 'icon': None, + 'ignore': False, + 'ignore_status': False, + 'inserted': '2024-11-13T10:47:15', + 'ip': '**REDACTED**', + 'last_discovered': '2026-07-13T20:00:29', + 'last_discovered_timetaken': 1.0503590106964, + 'last_ping': '2026-07-13T22:20:03', + 'last_ping_timetaken': 95.6, + 'last_poll_attempted': None, + 'last_polled': '2026-07-13T22:18:41', + 'last_polled_timetaken': 1.1394469738007, + 'lat': None, + 'lng': None, + 'location': None, + 'location_id': None, + 'max_depth': 0, + 'mtu_status': True, + 'notes': None, + 'os': 'ping', + 'override_sys_location': False, + 'overwrite_ip': None, + 'poller_group': 0, + 'port': 161, + 'port_association_mode': 1, + 'purpose': None, + 'retries': None, + 'serial': None, + 'snmp_disable': True, + 'snmp_engine_id': None, + 'snmpver': 'v2c', + 'status': True, + 'status_reason': '', + 'sys_contact': None, + 'sys_descr': None, + 'sys_name': '**REDACTED**', + 'sys_object_id': None, + 'timeout': None, + 'transport': 'udp', + 'type': '', + 'uptime': None, + 'version': None, + }), + ]), + 'system': dict({ + 'database_ver': 'MariaDB 10.5.29-MariaDB-ubu2004', + 'db_schema': '2026_06_09_000000_change_vsz_to_big_int_processes_table (390)', + 'local_branch': '', + 'local_date': '2026-06-18T09:10:36+02:00', + 'local_sha': '', + 'local_ver': '26.6.1', + 'netsnmp_ver': '5.9.5.2', + 'php_ver': '8.4.21', + 'python_ver': '3.12.13', + 'rrdtool_ver': '1.9.0', + }), + }), + 'entry': dict({ + 'data': dict({ + 'api_key': '**REDACTED**', + 'host': '**REDACTED**', + 'port': 443, + 'ssl': True, + 'verify_ssl': True, + }), + 'disabled_by': None, + 'discovery_keys': dict({ + }), + 'domain': 'librenms', + 'minor_version': 1, + 'options': dict({ + }), + 'pref_disable_new_entities': False, + 'pref_disable_polling': False, + 'source': 'user', + 'subentries': list([ + ]), + 'title': 'librenms', + 'unique_id': None, + 'version': 1, + }), + }) +# --- diff --git a/tests/components/librenms/test_diagnostics.py b/tests/components/librenms/test_diagnostics.py new file mode 100644 index 000000000000..9439594ae264 --- /dev/null +++ b/tests/components/librenms/test_diagnostics.py @@ -0,0 +1,31 @@ +"""Tests for the LibreNMS diagnostics.""" + +from unittest.mock import Mock + +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_entry_diagnostics( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + snapshot: SnapshotAssertion, + mock_librenms: Mock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test config entry diagnostics.""" + await setup_integration(hass, mock_config_entry) + + result = await get_diagnostics_for_config_entry( + hass, hass_client, mock_config_entry + ) + + assert result == snapshot(exclude=props("created_at", "modified_at", "entry_id"))