mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 04:20:45 +08:00
Ship gated eye polish, fabric levels, and collection UI refresh.
Topology MCP adds pull/compact/bundle/suggest-hubs with a no-template skill path; API gains fabric level and NE collection policy; web list pages get paging and denser collect/network workflows. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b1aee86701
commit
b81e5869a6
91 changed files with 10395 additions and 1513 deletions
71
tests/test_ne_collection_policy.py
Normal file
71
tests/test_ne_collection_policy.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from netx_api.collection_policy import (
|
||||
DEFAULT_HISTORY_KEEP,
|
||||
_normalize_interval_hours,
|
||||
history_keep_value,
|
||||
next_due_at,
|
||||
policy_to_out,
|
||||
)
|
||||
from netx_api.collection_schemas import CollectionPolicyUpdate
|
||||
from netx_api.models import NeCollectionJob, NeCollectionPolicy
|
||||
|
||||
|
||||
class NeCollectionPolicyDefaultsTests(unittest.TestCase):
|
||||
def test_default_history_keep_is_three(self) -> None:
|
||||
self.assertEqual(DEFAULT_HISTORY_KEEP, 3)
|
||||
row = NeCollectionPolicy(id=1, enabled=False, history_keep=3)
|
||||
self.assertEqual(history_keep_value(row), 3)
|
||||
out = policy_to_out(row)
|
||||
self.assertFalse(out.enabled)
|
||||
self.assertEqual(out.history_keep, 3)
|
||||
|
||||
def test_normalize_interval_hours_from_days(self) -> None:
|
||||
row = NeCollectionPolicy(id=1, interval_hours=0, interval_days=2)
|
||||
self.assertEqual(_normalize_interval_hours(row), 48)
|
||||
|
||||
def test_policy_update_schema_bounds(self) -> None:
|
||||
body = CollectionPolicyUpdate(history_keep=3, interval_hours=24, enabled=False)
|
||||
data = body.model_dump(exclude_unset=True)
|
||||
self.assertEqual(data["history_keep"], 3)
|
||||
self.assertFalse(data["enabled"])
|
||||
|
||||
|
||||
class NeCollectionNextDueTests(unittest.TestCase):
|
||||
def test_next_due_none_when_disabled(self) -> None:
|
||||
db = MagicMock()
|
||||
policy = NeCollectionPolicy(id=1, enabled=False, interval_hours=24)
|
||||
self.assertIsNone(next_due_at(db, policy))
|
||||
|
||||
def test_next_due_now_when_no_prior_schedule(self) -> None:
|
||||
db = MagicMock()
|
||||
db.query.return_value.filter.return_value.order_by.return_value.first.return_value = None
|
||||
policy = NeCollectionPolicy(id=1, enabled=True, interval_hours=24)
|
||||
due = next_due_at(db, policy)
|
||||
self.assertIsNotNone(due)
|
||||
assert due is not None
|
||||
self.assertLessEqual(abs((due - datetime.now()).total_seconds()), 5)
|
||||
|
||||
def test_next_due_from_last_scheduled_done(self) -> None:
|
||||
db = MagicMock()
|
||||
ended = datetime.now() - timedelta(hours=2)
|
||||
last = NeCollectionJob(
|
||||
id="abc",
|
||||
status="done",
|
||||
trigger_mode="schedule",
|
||||
ended_at=ended,
|
||||
)
|
||||
db.query.return_value.filter.return_value.order_by.return_value.first.return_value = last
|
||||
policy = NeCollectionPolicy(id=1, enabled=True, interval_hours=24)
|
||||
due = next_due_at(db, policy)
|
||||
self.assertIsNotNone(due)
|
||||
assert due is not None
|
||||
self.assertEqual(due, ended + timedelta(hours=24))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -977,11 +977,14 @@ class FabricTopologyTests(unittest.TestCase):
|
|||
),
|
||||
)
|
||||
prev = clf.preview_classify(self.db)
|
||||
self.assertGreaterEqual(prev.level_matched, 4)
|
||||
self.assertGreaterEqual(prev.role_matched, 4)
|
||||
applied = clf.apply_classify(self.db)
|
||||
self.assertGreaterEqual(applied.level_updated, 4)
|
||||
self.assertGreaterEqual(applied.role_updated, 4)
|
||||
self.db.refresh(nodes[0])
|
||||
self.assertEqual(nodes[0].role, "core")
|
||||
self.assertEqual(nodes[0].level, 1.0)
|
||||
self.assertEqual(nodes[0].region_folder_id, region.id)
|
||||
|
||||
dry = clf.generate_slices(
|
||||
|
|
@ -1026,6 +1029,11 @@ class FabricTopologyTests(unittest.TestCase):
|
|||
),
|
||||
)
|
||||
self.assertEqual(bulk.updated, 1)
|
||||
self.assertEqual(bulk.level, 3.0)
|
||||
acc = next(n for n in nodes if n.name.startswith("ACC-"))
|
||||
self.db.refresh(acc)
|
||||
self.assertEqual(acc.level, 3.0)
|
||||
self.assertEqual(acc.role, "access")
|
||||
|
||||
def test_project_neighbors_respects_max_nodes(self) -> None:
|
||||
suffix = uuid4().hex[:8]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue