fix(scan): default check_method='ping' for approved devices

Approving a pending device created a Node with check_method=NULL, so
the status scheduler silently skipped it (scheduler.py:64 filters
falsy check_method) and the bubble stayed grey forever.

Default to 'ping' when the device has an IP, in both single and bulk
approve paths. Also persist caller-supplied check_method/check_target
in the single-approve path.

Add regression tests asserting default check_method='ping' after
approval for both endpoints.
This commit is contained in:
Pouzor
2026-05-10 20:33:49 +02:00
parent ec8f1c87f1
commit ebdf6cb55b
2 changed files with 38 additions and 0 deletions
+7
View File
@@ -133,6 +133,9 @@ async def bulk_approve_devices(
status="unknown",
services=device.services or [],
ieee_address=device.ieee_address,
# Default to ping so the status checker actually polls the new node.
# Without this the scheduler skips it (check_method NULL → no check).
check_method="ping" if device.ip else None,
)
db.add(node)
created_nodes.append(node)
@@ -230,6 +233,10 @@ async def approve_device(
status=node_data.status,
services=node_data.services or [],
ieee_address=device.ieee_address,
# Honour caller-supplied check_method, else default to ping when an IP exists
# so the scheduler doesn't silently skip the new node.
check_method=node_data.check_method or ("ping" if node_data.ip else None),
check_target=node_data.check_target,
)
db.add(node)
await db.flush()
+31
View File
@@ -528,6 +528,37 @@ async def test_bulk_approve_approves_devices(client: AsyncClient, headers, two_p
assert pending_res.json() == []
@pytest.mark.asyncio
async def test_bulk_approve_sets_default_check_method(client: AsyncClient, headers, two_pending_devices, db_session):
"""Approved devices with an IP must default to ping; otherwise scheduler skips them."""
from sqlalchemy import select
from app.db.models import Node as NodeModel
ids = [d.id for d in two_pending_devices]
res = await client.post("/api/v1/scan/pending/bulk-approve", json={"device_ids": ids}, headers=headers)
assert res.status_code == 200
nodes = (await db_session.execute(select(NodeModel))).scalars().all()
for n in nodes:
if n.ip:
assert n.check_method == "ping", f"node {n.id} created without check_method"
@pytest.mark.asyncio
async def test_approve_device_sets_default_check_method(client: AsyncClient, headers, pending_device, db_session):
from sqlalchemy import select
from app.db.models import Node as NodeModel
res = await client.post(
f"/api/v1/scan/pending/{pending_device.id}/approve",
json={"label": "h", "type": "generic", "ip": "192.168.1.10", "status": "unknown", "services": []},
headers=headers,
)
assert res.status_code == 200
node = (await db_session.execute(select(NodeModel))).scalars().first()
assert node is not None
assert node.check_method == "ping"
@pytest.mark.asyncio
async def test_bulk_approve_skips_already_approved(client: AsyncClient, headers, two_pending_devices):
ids = [d.id for d in two_pending_devices]