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 | def api(auth: netbox): |
17 | # pynetbox adds /api itself; the resource URL may already end with it. |
18 | return pynetbox.api( |
19 | auth["url"].rstrip("/").removesuffix("/api"), token=auth["token"] |
20 | ) |
21 |
|
22 |
|
23 | def keep(**fields): |
24 | # The run form sends "" / [] / {} for untouched fields: drop them so a PATCH never blanks a value. |
25 | return {k: v for k, v in fields.items() if v not in (None, "", [], {})} |
26 |
|
27 |
|
28 | def main( |
29 | auth: netbox, |
30 | interface_id: int, |
31 | enabled: Optional[Literal["keep", "true", "false"]] = None, |
32 | description: Optional[str] = None, |
33 | label: Optional[str] = None, |
34 | mtu: Optional[int] = None, |
35 | mode: Optional[Literal["access", "tagged", "tagged-all", "q-in-q"]] = None, |
36 | untagged_vlan_id: Optional[int] = None, |
37 | tagged_vlan_ids: Optional[List[int]] = None, |
38 | custom_fields: Optional[dict] = None, |
39 | ): |
40 | """ |
41 | Update Interface |
42 | Patch an interface: enable/disable it, change its description, MTU or 802.1Q mode and VLANs. Only the fields you set change. |
43 | """ |
44 | body = keep( |
45 | enabled=None if enabled in (None, "", "keep") else enabled == "true", |
46 | description=description, |
47 | label=label, |
48 | mtu=mtu, |
49 | mode=mode, |
50 | untagged_vlan=untagged_vlan_id, |
51 | tagged_vlans=tagged_vlan_ids, |
52 | custom_fields=custom_fields, |
53 | ) |
54 | # A list body on the collection endpoint is NetBox's PATCH of only these fields. |
55 | return dict(api(auth).dcim.interfaces.update([{"id": interface_id, **body}])[0]) |
56 | |