# py312
# requirements:
# pynetbox==7.9.0
from typing import Optional, TypedDict
import pynetbox
class netbox(TypedDict):
url: str
token: str
DynSelect_site_id = str
def api(auth: netbox):
# pynetbox adds /api itself; the resource URL may already end with it.
return pynetbox.api(
auth["url"].rstrip("/").removesuffix("/api"), token=auth["token"]
)
def keep(**fields):
# The run form sends "" / [] / {} for untouched fields: drop them.
return {k: v for k, v in fields.items() if v not in (None, "", [], {})}
def page(records):
# One page (limit/offset), as NetBox's count plus the raw records.
results = [dict(r) for r in records]
return {"count": len(records), "results": results}
def options(endpoint, key="id", **filters):
return [
{"value": str(getattr(r, key)), "label": r.display}
for r in endpoint.filter(brief=1, limit=1000, offset=0, **filters)
]
# Dropdown of the instance's sites: the first 1000 (NetBox MAX_PAGE_SIZE); set the value by expression beyond that.
def site_id(auth: netbox):
return options(api(auth).dcim.sites)
def main(
auth: netbox,
site_id: Optional[DynSelect_site_id] = None,
vid: Optional[int] = None,
group_id: Optional[int] = None,
q: Optional[str] = None,
limit: Optional[int] = None,
offset: Optional[int] = None,
):
"""
List VLANs
List VLANs, filtered by site, VLAN id, group or search text.
"""
records = api(auth).ipam.vlans.filter(
**keep(site_id=site_id, vid=vid, group_id=group_id, q=q),
# limit=0 means NetBox's MAX_PAGE_SIZE, which also caps an explicit 1000.
limit=50 if limit is None else limit or 1000,
offset=offset or 0,
)
return page(records)
Submitted by hugo989 3 hours ago