1 | # py312 |
2 | # requirements: |
3 | # pynetbox==7.9.0 |
4 |
|
5 |
|
6 | from typing import List, Literal, Optional, TypedDict |
7 |
|
8 | import pynetbox |
9 |
|
10 |
|
11 | class netbox(TypedDict): |
12 | url: str |
13 | token: str |
14 |
|
15 |
|
16 | DynSelect_site_id = str |
17 |
|
18 |
|
19 | def api(auth: netbox): |
20 | # pynetbox adds /api itself; the resource URL may already end with it. |
21 | return pynetbox.api( |
22 | auth["url"].rstrip("/").removesuffix("/api"), token=auth["token"] |
23 | ) |
24 |
|
25 |
|
26 | def keep(**fields): |
27 | # The run form sends "" / [] / {} for untouched fields: drop them. |
28 | return {k: v for k, v in fields.items() if v not in (None, "", [], {})} |
29 |
|
30 |
|
31 | def page(records): |
32 | # One page (limit/offset), as NetBox's count plus the raw records. |
33 | results = [dict(r) for r in records] |
34 | return {"count": len(records), "results": results} |
35 |
|
36 |
|
37 | def options(endpoint, key="id", **filters): |
38 | return [ |
39 | {"value": str(getattr(r, key)), "label": r.display} |
40 | for r in endpoint.filter(brief=1, limit=1000, offset=0, **filters) |
41 | ] |
42 |
|
43 |
|
44 | # Dropdown of the instance's sites: the first 1000 (NetBox MAX_PAGE_SIZE); set the value by expression beyond that. |
45 | def site_id(auth: netbox): |
46 | return options(api(auth).dcim.sites) |
47 |
|
48 |
|
49 | def main( |
50 | auth: netbox, |
51 | q: Optional[str] = None, |
52 | prefix: Optional[str] = None, |
53 | within: Optional[str] = None, |
54 | site_id: Optional[DynSelect_site_id] = None, |
55 | vrf_id: Optional[int] = None, |
56 | status: Optional[ |
57 | List[Literal["container", "active", "reserved", "deprecated"]] |
58 | ] = None, |
59 | tag: Optional[List[str]] = None, |
60 | limit: Optional[int] = None, |
61 | offset: Optional[int] = None, |
62 | ): |
63 | """ |
64 | List Prefixes |
65 | List prefixes, filtered by prefix, containing prefix (within), site, VRF, status or tag. |
66 | """ |
67 | records = api(auth).ipam.prefixes.filter( |
68 | **keep( |
69 | q=q, |
70 | prefix=prefix, |
71 | within=within, |
72 | site_id=site_id, |
73 | vrf_id=vrf_id, |
74 | status=status, |
75 | tag=tag, |
76 | ), |
77 | # limit=0 means NetBox's MAX_PAGE_SIZE, which also caps an explicit 1000. |
78 | limit=50 if limit is None else limit or 1000, |
79 | offset=offset or 0, |
80 | ) |
81 | return page(records) |
82 | |