0

Update Device

by
Published today

Patch a device: only the fields you set change. custom_fields merges into the existing values; tags (slugs) replace the current tags when set.

Script netbox Verified

The script

Submitted by hugo989 Python3
Verified 5 hours ago
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
DynSelect_role_id = str
18

19

20
def api(auth: netbox):
21
    # pynetbox adds /api itself; the resource URL may already end with it.
22
    return pynetbox.api(
23
        auth["url"].rstrip("/").removesuffix("/api"), token=auth["token"]
24
    )
25

26

27
def keep(**fields):
28
    # The run form sends "" / [] / {} for untouched fields: drop them so a PATCH never blanks a value.
29
    return {k: v for k, v in fields.items() if v not in (None, "", [], {})}
30

31

32
def options(endpoint, key="id", **filters):
33
    return [
34
        {"value": str(getattr(r, key)), "label": r.display}
35
        for r in endpoint.filter(brief=1, limit=1000, offset=0, **filters)
36
    ]
37

38

39
# Dropdown of the instance's sites: the first 1000 (NetBox MAX_PAGE_SIZE); set the value by expression beyond that.
40
def site_id(auth: netbox):
41
    return options(api(auth).dcim.sites)
42

43

44
# Dropdown of the instance's device roles.
45
def role_id(auth: netbox):
46
    return options(api(auth).dcim.device_roles)
47

48

49
def main(
50
    auth: netbox,
51
    device_id: int,
52
    name: Optional[str] = None,
53
    status: Optional[
54
        Literal[
55
            "offline",
56
            "active",
57
            "planned",
58
            "staged",
59
            "failed",
60
            "inventory",
61
            "decommissioning",
62
        ]
63
    ] = None,
64
    site_id: Optional[DynSelect_site_id] = None,
65
    role_id: Optional[DynSelect_role_id] = None,
66
    platform_id: Optional[int] = None,
67
    serial: Optional[str] = None,
68
    description: Optional[str] = None,
69
    tags: Optional[List[str]] = None,
70
    custom_fields: Optional[dict] = None,
71
):
72
    """
73
    Update Device
74
    Patch a device: only the fields you set change. custom_fields merges into the existing values; tags (slugs) replace the current tags when set.
75
    """
76
    body = keep(
77
        name=name,
78
        status=status,
79
        site=int(site_id) if site_id else None,
80
        role=int(role_id) if role_id else None,
81
        platform=platform_id,
82
        serial=serial,
83
        description=description,
84
        tags=[{"slug": s} for s in tags or []],
85
        custom_fields=custom_fields,
86
    )
87
    # A list body on the collection endpoint is NetBox's PATCH of only these fields.
88
    return dict(api(auth).dcim.devices.update([{"id": device_id, **body}])[0])
89