feat: per-service status checks with offline colouring
Adds optional live status checking per service (not just per node), requested as a follow-up to issue #196. Backend: - New check_service / check_services: HTTP(S) GET for web services, TCP connect otherwise; UDP and port-less non-web services stay 'unknown'. - New scheduler job 'service_checks', independent interval (default 300s), added/removed live via set_service_checks_enabled. - Settings gain service_check_enabled + service_check_interval (>=30s), persisted to scan_config.json. New WS message type 'service_status'. Frontend: - Live per-service status overlay in canvasStore (not persisted, so it never round-trips through canvas save), fed by the WS message. - DetailPanel + canvas node service rows: offline service turns red (#f85149), otherwise keeps its category colour. - SettingsModal: toggle + interval input (default 300s / 5 min). Off by default — no behaviour change until enabled. ha-relevant: yes
This commit is contained in:
@@ -31,9 +31,36 @@ describe('canvasStore', () => {
|
||||
past: [],
|
||||
future: [],
|
||||
clipboard: { nodes: [], edges: [] },
|
||||
serviceStatuses: {},
|
||||
})
|
||||
})
|
||||
|
||||
it('setServiceStatuses stores live status keyed by node/port/protocol', () => {
|
||||
const { setServiceStatuses } = useCanvasStore.getState()
|
||||
setServiceStatuses('node-1', [
|
||||
{ port: 80, protocol: 'tcp', status: 'offline' },
|
||||
{ port: 443, protocol: 'tcp', status: 'online' },
|
||||
])
|
||||
const { serviceStatuses } = useCanvasStore.getState()
|
||||
expect(serviceStatuses['node-1:80/tcp']).toBe('offline')
|
||||
expect(serviceStatuses['node-1:443/tcp']).toBe('online')
|
||||
})
|
||||
|
||||
it('setServiceStatuses merges without dropping other nodes', () => {
|
||||
const { setServiceStatuses } = useCanvasStore.getState()
|
||||
setServiceStatuses('node-1', [{ port: 80, protocol: 'tcp', status: 'online' }])
|
||||
setServiceStatuses('node-2', [{ port: 22, protocol: 'tcp', status: 'offline' }])
|
||||
const { serviceStatuses } = useCanvasStore.getState()
|
||||
expect(serviceStatuses['node-1:80/tcp']).toBe('online')
|
||||
expect(serviceStatuses['node-2:22/tcp']).toBe('offline')
|
||||
})
|
||||
|
||||
it('does not mark canvas unsaved on a service status update', () => {
|
||||
useCanvasStore.setState({ hasUnsavedChanges: false })
|
||||
useCanvasStore.getState().setServiceStatuses('n', [{ port: 80, protocol: 'tcp', status: 'offline' }])
|
||||
expect(useCanvasStore.getState().hasUnsavedChanges).toBe(false)
|
||||
})
|
||||
|
||||
it('setEditingTextId sets and clears editing text id', () => {
|
||||
const { setEditingTextId } = useCanvasStore.getState()
|
||||
setEditingTextId('t1')
|
||||
|
||||
Reference in New Issue
Block a user