Skip to main content

Topolograph Python SDK

A Pythonic, object-oriented client for the Topolograph REST API with built-in topology ingestion via SSH.

Features

  • Pythonic API Client: Clean, object-oriented interface to the Topolograph REST API
  • SSH-Based Collection: Collect IGP LSDB data directly from network devices using Nornir
  • CLI Interface: Command-line tool built on top of the SDK
  • PyPI Ready: Installable via pip install topolograph-sdk

Installation

pip install topolograph-sdk

PyPI Package: https://pypi.org/project/topolograph-sdk/

Quick Start

Basic Usage

from topolograph import Topolograph

# Initialize client
topo = Topolograph(
    url="http://localhost:8080",
    token="your-api-token"  # or set TOPOLOGRAPH_TOKEN env var
)

# Get latest graph
graph = topo.graphs.get(latest=True)

# Access graph properties
print(f"Graph Time: {graph.graph_time}")
print(f"Protocol: {graph.protocol}")
print(f"Hosts: {graph.hosts['count']}")

# Get graph status
status = graph.status()
print(f"Status: {status['status']}")

Collecting Topology Data

from topolograph import TopologyCollector

# Create collector with inventory file
collector = TopologyCollector("inventory.yaml")

# Collect LSDB data
result = collector.collect()

# Access results
print(f"Collected from {len(result.host_results)} hosts")
print(f"LSDB text length: {len(result.raw_lsdb_text)}")

# Upload to Topolograph
graph = topo.uploader.upload_raw(
    lsdb_text=result.raw_lsdb_text,
    vendor="FRR",
    protocol="isis"
)

Inventory Format

Create a YAML inventory file with explicit vendor and protocol metadata. A sample inventory file (inventory.yaml.example) is provided in the project root:

---
router1:
  hostname: 172.20.20.2
  username: admin
  password: admin
  vendor: frr
  protocol: isis
  port: 22

router2:
  hostname: 172.20.20.3
  username: admin
  password: admin
  vendor: cisco
  protocol: ospf
  port: 22

Required fields:

  • hostname: IP address or hostname of the device
  • username: SSH username
  • password: SSH password
  • vendor: Device vendor (cisco, juniper, frr, arista, nokia, huawei)
  • protocol: IGP protocol (ospf, isis)
  • port: SSH port (optional, defaults to 22)

Quick start: Copy the example inventory file:

cp inventory.yaml.example inventory.yaml
# Edit inventory.yaml with your device credentials

Working with Graphs

# List all graphs
graphs = topo.graphs.list(protocol="ospf")

# Get specific graph
graph = topo.graphs.get_by_time("2024-01-15T10:30:00Z")

# Get nodes
nodes = graph.nodes.get()
for node in nodes:
    print(f"Node: {node.name} (ID: {node.id})")

# Find networks
networks = graph.networks.find_by_ip("10.10.10.1")
networks = graph.networks.find_by_node("1.1.1.1")
network = graph.networks.find_by_network("10.10.10.0/24")

Uploading YAML Diagrams

Upload arbitrary network topologies defined in YAML format:

# Define topology in YAML format
yaml_diagram = """
nodes:
  10.10.10.1:
    label: Router1
    location: dc1
  10.10.10.2:
    label: Router2
    location: dc1
edges:
  - src: 10.10.10.1
    dst: 10.10.10.2
    cost: 10
    bw: 1000
"""

# Upload diagram
graph = topo.graphs.upload_diagram(yaml_diagram)
print(f"Diagram uploaded with graph_time: {graph.graph_time}")

Updating Node Attributes

Update node attributes in YAML-based diagrams:

# Get a YAML diagram graph
graph = topo.graphs.get_by_time("18Jan2026_15h53m13s_3_hosts_yaml")

# Get a node
node = graph.nodes.get_by_id(0)
print(f"Current name: {node.name}")

# Update node completely (PUT - replaces all attributes)
updated_node = graph.nodes.update(
    node.id,
    {
        'name': 'new_router_name',
        'location': 'datacenter1',
        'role': 'core_router',
        'vendor': 'cisco'
    }
)

# Partially update node (PATCH - only specified attributes)
updated_node = graph.nodes.patch(
    node.id,
    {'name': 'renamed_router'}
)

# Or use instance methods for convenience
node = graph.nodes.get_by_id(0)
updated_node = node.patch(name='new_name', location='dc2')

Path Computation

# Shortest path between nodes
path = graph.paths.shortest("1.1.1.1", "2.2.2.2")
print(f"Path cost: {path.cost}")
for path_nodes in path.paths:
    print(f"Path: {' -> '.join(path_nodes)}")

# Shortest path between networks/IPs
path = graph.paths.shortest_network("192.168.1.1", "192.168.2.1")

# Backup path (removing specific edges)
path = graph.paths.shortest(
    "1.1.1.1",
    "2.2.2.2",
    removed_edges=[("1.1.1.1", "3.3.3.3")]
)

Events

# Get network events
network_events = graph.events.get_network_events(last_minutes=60)
for event in network_events['network_up_down_events']:
    print(f"Network {event.event_object} is {event.event_status}")

# Get adjacency events
adjacency_events = graph.events.get_adjacency_events(
    start_time="2024-01-15T10:00:00Z",
    end_time="2024-01-15T11:00:00Z"
)

BGP topology

Requires Topolograph >= 2.69.

# List BGP epochs, take the newest
bgp = client.bgp_graphs.get_latest()

# Speakers and sessions
bgp.nodes.list(role="rr")
bgp.sessions.list(bgp_session_type="ebgp")

# Route table (one row per RFC 4271 9.1 path); pass router_id to scope it
# to that router's resolved RIB view
bgp.routes.search(prefix="10.0.0.0/24", community="65000:100")
bgp.routes.search(router_id="1.1.1.1", ribs="loc-rib")
bgp.routes.summary("1.1.1.1")

# Point-in-time state and a two-timestamp diff
bgp.routes.state(at="2026-08-30T10:00:00Z")
bgp.routes.compare("2026-08-30T09:00:00Z", "2026-08-30T10:00:00Z")

# BGP change events, IGP bindings
bgp.events.timeline(last_minutes=15)
bgp.igp_bindings.list()

# VRF inventory for an IGP graph's routers
graph.vrfs(router_id="1.1.1.1")

# Protocol-aware path resolution (static/BGP/IGP/LSP hand-off)
graph.paths.resolve_route("R1", "8.8.8.8", vrf="BLUE")

CLI Usage

The SDK includes a CLI tool accessible via the topo command:

List Graphs

# List all graphs
topo graphs --list

# Get latest graph
topo graphs --latest

# Filter by protocol
topo graphs --list --protocol ospf

# Filter by watcher
topo graphs --list --watcher production-watcher

Collect and Upload Topology

# Collect LSDB from devices
topo ingest inventory.yaml --protocol isis

# Collect and save to file
topo ingest inventory.yaml --output lsdb.txt

# Collect and upload to Topolograph
topo ingest inventory.yaml --upload --url http://localhost:8080

Compute Paths

# Shortest path between nodes
topo path --src 1.1.1.1 --dst 2.2.2.2

# Shortest path between networks
topo path --src 192.168.1.1 --dst 192.168.2.1 --network

# Use specific graph
topo path --src 1.1.1.1 --dst 2.2.2.2 --graph-time "2024-01-15T10:30:00Z"

Upload LSDB Files

# Upload a LSDB file
topo upload --file lsdb.txt --vendor FRR --protocol isis

# Upload with watcher name
topo upload --file lsdb.txt --vendor Cisco --protocol ospf --watcher prod-watcher

Supported Vendors and Protocols

OSPF

  • Cisco: show ip ospf database router, show ip ospf database network, show ip ospf database external
  • Juniper: show ospf database router extensive | no-more, etc.
  • FRR/Quagga: show ip ospf database router, etc.
  • Arista: show ip ospf database router detail, etc.
  • Nokia: show router ospf database router detail, etc.

IS-IS

  • Cisco: show isis database detail
  • Juniper: show isis database extensive
  • FRR: show isis database detail
  • Nokia: show router isis database detail
  • Huawei: display isis lsdb verbose

Authentication

The SDK supports multiple authentication methods (in priority order):

  1. Explicit token parameter:

    topo = Topolograph(url="...", token="your-token")
    
  2. Environment variable:

    export TOPOLOGRAPH_TOKEN="your-token"
    
  3. Basic authentication:

    topo = Topolograph(url="...", username="user", password="pass")
    

Error Handling

The SDK raises custom exceptions for different error scenarios:

from topolograph.exceptions import (
    AuthenticationError,
    NotFoundError,
    ValidationError,
    APIError
)

try:
    graph = topo.graphs.get_by_time("invalid-time")
except NotFoundError:
    print("Graph not found")
except AuthenticationError:
    print("Authentication failed")
except APIError as e:
    print(f"API error: {e}")

Testing

Run integration tests with containerlab:

# Set environment variables
export TOPOLOGRAPH_URL="http://localhost:8080"
export TOPOLOGRAPH_TOKEN="your-token"

# Run tests
pytest tests/test_integration.py -v

Or use the manual test script:

python test_sdk.py

Development

Setup Development Environment

# Clone repository
git clone https://github.com/topolograph/topolograph-sdk.git
cd topolograph-sdk

# Install in development mode
pip install -e ".[dev]"

Project Structure

topolograph-sdk/
├── topolograph/          # SDK package
│   ├── client.py        # Core HTTP client
│   ├── resources/       # Resource objects (Graph, Node, Network, etc.)
│   ├── collector/       # SSH-based topology collection
│   └── upload/          # Upload pipeline
├── cli/                 # CLI interface
├── tests/               # Test suite
└── pyproject.toml       # Package configuration

License

Apache License 2.0 - See LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Support

For issues, questions, or feature requests, please open an issue on GitHub.

Release files for topolograph-sdk 0.1.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for topolograph-sdk 0.1.12
File Size Uploaded
topolograph_sdk-0.1.12.tar.gz 41.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for topolograph-sdk 0.1.12
File Interpreter ABI Platform
topolograph_sdk-0.1.12-py3-none-any.whl Python 3 none any Details

Total release size: 79.4 kB

Release files / topolograph_sdk-0.1.12.tar.gz

Download URL topolograph_sdk-0.1.12.tar.gz
Size 41.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5e5bbf78355cba430f9e3b214ab3f4e233ae82d659f64ae3f7d06d1b88d3a28e
BLAKE2b-256 checksum
How to use checksums
5cbd2d6b92c8e154ecf65f7bd6698c496eb5f5c0d9e66440a2512f02c84a9300
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release files / topolograph_sdk-0.1.12-py3-none-any.whl

Download URL topolograph_sdk-0.1.12-py3-none-any.whl
Size 38.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2a699152e11fe26bb8144b34c30e5454a9aba871ae3c20638df6ac746e1efb7d
BLAKE2b-256 checksum
How to use checksums
acdcf832c4977f8ada4fc27eeaaf7e517ef8044ff1fd452f87b4bae9f1ab2faf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release history Release notifications | RSS feed

0.1.14

2 release files

0.1.13

2 release files

This release

0.1.12 This release

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.8

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page