Allow compare templates to split one collected metric into filtered sheets.

BGP/ISIS (and any other metric) can share a metric_id with distinct sheet_id + row_filters; drop conflicting bgp state_or_pfx and keep state/pfx_rcd.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-19 01:46:03 +08:00
parent 88b7558a48
commit a65c9fc420
17 changed files with 745 additions and 230 deletions

View file

@ -27,6 +27,55 @@ PORT_OVERRIDE = {
class ParseExpectSetTests(unittest.TestCase):
def test_items_sheet_id_bucket(self):
got = parse_expect_set(
{
"items": [
{"metric_id": "bgp_peer", "sheet_id": "bgp_peer.vpnv4", "key": "1.1.1.1"},
{"metric_id": "bgp_peer", "sheet_id": "bgp_peer.ipv4", "key": "2.2.2.2"},
]
}
)
self.assertEqual(got["bgp_peer.vpnv4"], {"1.1.1.1"})
self.assertEqual(got["bgp_peer.ipv4"], {"2.2.2.2"})
self.assertNotIn("bgp_peer", got)
def test_expect_keys_prefer_sheet_id(self):
expect = parse_expect_set(
{
"items": [
{"metric_id": "bgp_peer", "sheet_id": "bgp_peer.vpnv4", "key": "1.1.1.1"},
{"metric_id": "bgp_peer", "key": "9.9.9.9"},
]
}
)
self.assertEqual(
expect_keys_for_metric(
expect, metric_id="bgp_peer", iface_fields=[], sheet_id="bgp_peer.vpnv4"
),
{"1.1.1.1"},
)
self.assertEqual(
expect_keys_for_metric(expect, metric_id="bgp_peer", iface_fields=[]),
{"9.9.9.9"},
)
def test_override_for_sheet_prefers_sheet_id(self):
from netx_api.biz_migration.evaluate import override_for_sheet
overrides = [
{"metric_id": "bgp_peer", "status_fields": ["state"]},
{"metric_id": "bgp_peer", "sheet_id": "bgp_peer.vpnv4", "status_fields": ["state", "pfx_rcd"]},
]
hit = override_for_sheet(
overrides, sheet_id="bgp_peer.vpnv4", metric_id="bgp_peer"
)
self.assertEqual(hit["status_fields"], ["state", "pfx_rcd"])
legacy = override_for_sheet(
overrides, sheet_id="bgp_peer.ipv4", metric_id="bgp_peer"
)
self.assertEqual(legacy["status_fields"], ["state"])
def test_ports_go_to_interface_brief(self):
got = parse_expect_set({"ports": ["gei-1", "gei-2", ""]})
self.assertEqual(got["interface_brief"], {"gei-1", "gei-2"})

View file

@ -10,6 +10,7 @@ from netx_api.biz_state.compare_rules import (
arp_dynamic_row_filters,
effective_compare_fields,
effective_display_fields,
eval_leaf_filter,
normalize_value,
values_equal,
)
@ -314,6 +315,57 @@ class CompareDiffPagingTests(unittest.TestCase):
class CompareSheetDefaultsTests(unittest.TestCase):
def test_contains_filter_op(self) -> None:
row = {"af": "IPv4,IPv6"}
self.assertTrue(eval_leaf_filter(row, {"field": "af", "op": "contains", "value": "IPv4"}))
self.assertTrue(eval_leaf_filter(row, {"field": "af", "op": "contains", "value": "ipv6"}))
self.assertFalse(eval_leaf_filter(row, {"field": "af", "op": "contains", "value": "vpn"}))
def test_zte_default_splits_bgp_and_isis(self) -> None:
from netx_api.biz_state.compare_service import _default_zte_status_sheets, sheet_key
sheets = _default_zte_status_sheets()
ids = [sheet_key(s) for s in sheets]
self.assertIn("bgp_peer.ipv4", ids)
self.assertIn("bgp_peer.vpnv4", ids)
self.assertIn("bgp_peer.vpnv6", ids)
self.assertIn("isis_adjacency.ipv4", ids)
self.assertIn("isis_adjacency.ipv6", ids)
# Same source metric may appear multiple times
self.assertEqual(sum(1 for s in sheets if s["metric_id"] == "bgp_peer"), 4)
vpnv4 = next(s for s in sheets if sheet_key(s) == "bgp_peer.vpnv4")
self.assertEqual(vpnv4["row_filters"], [{"field": "afi", "op": "eq", "value": "vpnv4"}])
isis4 = next(s for s in sheets if sheet_key(s) == "isis_adjacency.ipv4")
self.assertEqual(isis4["row_filters"][0]["op"], "contains")
def test_normalize_allows_duplicate_metric_with_distinct_sheet_id(self) -> None:
from netx_api.biz_state.compare_service import _normalize_sheet, sheet_key
a = _normalize_sheet(
{
"sheet_id": "bgp_peer.vpnv4",
"title": "BGP VPNv4",
"metric_id": "bgp_peer",
"key_fields": ["afi", "neighbor"],
"compare_fields": ["state"],
"row_filters": [{"field": "afi", "op": "eq", "value": "vpnv4"}],
}
)
b = _normalize_sheet(
{
"sheet_id": "bgp_peer.ipv4",
"title": "BGP IPv4",
"metric_id": "bgp_peer",
"key_fields": ["afi", "neighbor"],
"compare_fields": ["state"],
"row_filters": [{"field": "afi", "op": "eq", "value": "ipv4"}],
}
)
self.assertIsNotNone(a)
self.assertIsNotNone(b)
self.assertEqual(a["metric_id"], b["metric_id"])
self.assertNotEqual(sheet_key(a), sheet_key(b))
def test_arp_default_sheet_has_row_filters(self) -> None:
from netx_api.biz_state.compare_service import _default_sheet_for_metric

View file

@ -145,6 +145,12 @@ class ZteStatusParserTests(unittest.TestCase):
conn = [r for r in rows if r["state"] == "Connect"]
self.assertGreaterEqual(len(est), 3)
self.assertGreaterEqual(len(conn), 3)
self.assertTrue(all("state_or_pfx" not in r for r in rows))
self.assertTrue(all(r["pfx_rcd"].isdigit() for r in est))
self.assertTrue(all(r["pfx_rcd"] == "" for r in conn))
one = next(r for r in rows if r["neighbor"] == "10.206.63.205")
self.assertEqual(one["state"], "Established")
self.assertEqual(one["pfx_rcd"], "642")
ipv4 = _section(self.log, "show bgp ipv4 unicast summary", ("show bgp vpnv6",))
rows2 = normalize_bgp_peer(raw_text=ipv4, command="show bgp ipv4 unicast summary")