Edits history of script submission #23927 for ' List Devices (netbox)'

  • python3
    One script reply has been approved by the moderators
    Ap­pro­ved
    # py312
    # requirements:
    # pynetbox==7.9.0
    
    
    from typing import List, Literal, Optional, TypedDict
    
    import pynetbox
    
    
    class netbox(TypedDict):
        url: str
        token: str
    
    
    DynMultiselect_site = List[str]
    DynMultiselect_role = List[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, by slug: the first 1000 (NetBox MAX_PAGE_SIZE); set the value by expression beyond that.
    def site(auth: netbox):
        return options(api(auth).dcim.sites, "slug")
    
    
    # Dropdown of the instance's device roles, by slug.
    def role(auth: netbox):
        return options(api(auth).dcim.device_roles, "slug")
    
    
    def main(
        auth: netbox,
        site: Optional[DynMultiselect_site] = None,
        role: Optional[DynMultiselect_role] = None,
        status: Optional[
            List[
                Literal[
                    "offline",
                    "active",
                    "planned",
                    "staged",
                    "failed",
                    "inventory",
                    "decommissioning",
                ]
            ]
        ] = None,
        tag: Optional[List[str]] = None,
        name: Optional[str] = None,
        custom_field_filters: Optional[dict] = None,
        q: Optional[str] = None,
        limit: Optional[int] = None,
        offset: Optional[int] = None,
    ):
        """
        List Devices
        List devices filtered by sites, roles, status, tags (slugs), exact name or custom fields ({tier: "edge"} becomes cf_tier=edge). Returns NetBox's count and one page of raw devices, including platform and custom_fields.
        """
        cf = {
            k if k.startswith("cf_") else f"cf_{k}": v
            for k, v in (custom_field_filters or {}).items()
        }
        records = api(auth).dcim.devices.filter(
            **keep(site=site, role=role, status=status, tag=tag, name=name, q=q, **cf),
            # 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