Gateway Relationships¶
Groups gateways by parent_uid to separate cluster members from standalone gateways — see Sessions & Multi-Domain for how domain context flows through these results.
examples/03_gateway_relationships.py
"""Inspect cluster topology: which gateways are cluster members vs. standalone.
Run: uv run examples/03_gateway_relationships.py
"""
import asyncio
import os
# Load environment variables BEFORE importing arodonata modules
from dotenv import load_dotenv
load_dotenv(".env.lib", override=True)
load_dotenv(".env.secrets", override=True)
import time
from collections import defaultdict
from sqlalchemy.ext.asyncio import create_async_engine
from arodonata import ArodonataClient, ArodonataSettings
def _settings_from_env() -> ArodonataSettings:
api_key_vars = os.getenv("API_KEY_VARS", "").split(",")
api_keys = ",".join(os.getenv(var, "") for var in api_key_vars)
return ArodonataSettings(
mgmt_names=os.getenv("MGMT_NAMES", "mgmt1"),
mgmt_servers=os.getenv("MGMT_SERVERS", "10.0.0.1"),
api_keys=api_keys,
)
async def main() -> None:
engine = create_async_engine(os.getenv("DATABASE_URL", "sqlite+aiosqlite:///:memory:"))
client = ArodonataClient(engine=engine, settings=_settings_from_env())
start_time = time.perf_counter()
try:
async with client:
gateways = await client.get_gateways()
members_by_parent = defaultdict(list)
standalone = []
for gw in gateways:
parent_uid = getattr(gw, "parent_uid", None)
if parent_uid:
members_by_parent[parent_uid].append(gw)
else:
standalone.append(gw)
print(f"Standalone gateways: {len(standalone)}")
for gw in standalone[:5]:
print(f" {gw.name} ({gw.type})")
print(f"\nClusters with members: {len(members_by_parent)}")
for parent_uid, members in list(members_by_parent.items())[:5]:
names = ", ".join(m.name for m in members)
print(f" cluster {parent_uid}: {names}")
finally:
await engine.dispose()
duration = time.perf_counter() - start_time
print(f"\nTotal time: {duration:.2f}s")
if __name__ == "__main__":
asyncio.run(main())
Run it: