extract BgpContext dataclass for build_bgp_intel

This commit is contained in:
Andrew Pimenov 2026-08-09 16:06:55 +03:00
parent d88b1bd95a
commit 5f51e70d5e
2 changed files with 58 additions and 48 deletions

View file

@ -108,6 +108,7 @@ import json
import os
import time
from pathlib import Path
from dataclasses import dataclass
from typing import Awaitable, Callable
from netsleuth.models import IxpPresence
@ -177,25 +178,28 @@ async def cached_json(
from netsleuth.models import BgpIntel
def build_bgp_intel(
asn: str,
overview: dict,
neighbours: dict,
prefixes: dict,
updates: dict,
asrank: dict | None,
pdb_net: dict | None,
pdb_ixlan: dict | None,
timeframe_days: int,
) -> BgpIntel:
info = parse_as_overview(overview)
upstreams, peers, downstreams = parse_asn_neighbours(neighbours)
announced, v4, v6 = parse_announced_prefixes(prefixes)
events = parse_bgp_updates(updates)
rank, cone_asns, cone_prefixes = parse_asrank(asrank) if asrank else (None, None, None)
info_type, traffic, _net_id = parse_peeringdb_net(pdb_net) if pdb_net else (None, None, None)
@dataclass
class BgpContext:
asn: str
overview: dict
neighbours: dict
prefixes: dict
updates: dict
asrank: dict | None
pdb_net: dict | None
pdb_ixlan: dict | None
timeframe_days: int
def build_bgp_intel(ctx: BgpContext) -> BgpIntel:
info = parse_as_overview(ctx.overview)
upstreams, peers, downstreams = parse_asn_neighbours(ctx.neighbours)
announced, v4, v6 = parse_announced_prefixes(ctx.prefixes)
events = parse_bgp_updates(ctx.updates)
rank, cone_asns, cone_prefixes = parse_asrank(ctx.asrank) if ctx.asrank else (None, None, None)
info_type, traffic, _net_id = parse_peeringdb_net(ctx.pdb_net) if ctx.pdb_net else (None, None, None)
return BgpIntel(
asn=asn,
asn=ctx.asn,
holder=info["holder"],
registry=info["registry"],
allocated_at=info["allocated_at"],
@ -206,8 +210,8 @@ def build_bgp_intel(
prefix_count_v4=v4,
prefix_count_v6=v6,
flaps=events,
stability=classify_stability(events, timeframe_days),
ixps=parse_peeringdb_netixlan(pdb_ixlan) if pdb_ixlan else [],
stability=classify_stability(events, ctx.timeframe_days),
ixps=parse_peeringdb_netixlan(ctx.pdb_ixlan) if ctx.pdb_ixlan else [],
pdb_info_type=info_type,
pdb_traffic=traffic,
asrank=rank,
@ -284,6 +288,7 @@ async def collect_bgp(
pdb_ixlan = None
intel = build_bgp_intel(
BgpContext(
asn=asn,
overview=overview or {},
neighbours=neighbours or {},
@ -294,6 +299,7 @@ async def collect_bgp(
pdb_ixlan=pdb_ixlan,
timeframe_days=providers.ripestat_timeframe_days,
)
)
raw = {
"ripestat-as-overview": overview,
"ripestat-asn-neighbours": neighbours,

View file

@ -211,11 +211,12 @@ async def test_cached_json_survives_a_corrupt_cache_file(tmp_path: Path):
assert await cached_json(tmp_path, "k", ttl_hours=24, fetch=fetch) == {"value": "fresh"}
from netsleuth.bgp import build_bgp_intel
from netsleuth.bgp import BgpContext, build_bgp_intel
def test_build_bgp_intel_merges_every_source(api_fixture):
intel = build_bgp_intel(
BgpContext(
asn="AS64500",
overview=api_fixture("ripestat_as_overview.json"),
neighbours=api_fixture("ripestat_asn_neighbours.json"),
@ -226,6 +227,7 @@ def test_build_bgp_intel_merges_every_source(api_fixture):
pdb_ixlan=api_fixture("peeringdb_netixlan.json"),
timeframe_days=14,
)
)
assert intel.asn == "AS64500"
assert intel.holder == "EXAMPLE-AS Example Telecom BV"
assert intel.upstreams == ["AS3356", "AS1299"]
@ -241,6 +243,7 @@ def test_build_bgp_intel_merges_every_source(api_fixture):
def test_build_bgp_intel_tolerates_every_optional_source_being_absent(api_fixture):
intel = build_bgp_intel(
BgpContext(
asn="AS64500",
overview=api_fixture("ripestat_as_overview.json"),
neighbours={},
@ -251,6 +254,7 @@ def test_build_bgp_intel_tolerates_every_optional_source_being_absent(api_fixtur
pdb_ixlan=None,
timeframe_days=14,
)
)
assert intel.asn == "AS64500"
assert intel.upstreams == []
assert intel.asrank is None