Skip to content
This repository was archived by the owner on Jun 27, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,109 @@
[![License](https://img.shields.io/github/license/netbox-community/netbox-python)](https://img.shields.io/github/license/netbox-community/netbox-python)

Python NetBox API Client

## Installation

To install run `pip install netbox-python`.

Alternatively, you can clone the repo and run `python setup.py install`.

## Usage

To begin, import the NetBox client and instantiate it:

```
from netbox_python import NetBoxClient, Result
nb = NetBoxClient(
base_url="http://127.0.0.1:8000/", token="1dc6fa5bfcef8390dd83a261c36ed8f1551b2d6b"
)
```
The first argument NetBoxClient takes is the NetBox URL. The 'token' argument is from NetBox, see the [Authentication documentation](https://docs.netbox.dev/en/stable/integrations/rest-api/#authentication) in the NetBox docs for more about creating and using API Tokens.

Now using the client you can make calls to the api.

### Basic CRUD APIs

Each of these objects has the standard CRUD endpoints as follows:

```
# 1. List (paginated)
ret = nb.dcim.sites.list(limit=3)

# 2. Filtered List
ret = nb.dcim.sites.list(region_id="43")

# 3. All
ret = nb.dcim.sites.all()

# 4. Get
ret = nb.dcim.sites.get(24)

# 5. Create
ret = nb.dcim.sites.create(name="foo3", slug="foo3")

# 6. Update
ret = nb.dcim.sites.update(26, name="foo2-new", slug="foo2-new-slug")

# 7. Delete
ret = nb.dcim.sites.delete(37)
```

### Bulk APIs

In addition, bulk operations are available on the API's as well:
```
# 8. Bulk Create
data = [
{"name": "foo4", "slug": "foo4"},
{"name": "foo5", "slug": "foo5"},
{"name": "foo6", "slug": "foo6"},
]
ret = nb.dcim.sites.create(data)

# 8. Bulk Update
data = [
{"id": 28, "name": "foo4-new", "slug": "foo4-new"},
{"id": 29, "name": "foo5-new", "slug": "foo5-new"},
]
ret = nb.dcim.sites.update(data)

# 10. Bulk Delete
data = [{"id": 25}, {"id": 27}]
ret = nb.dcim.sites.delete(data)
```
### Special APIs

In addition to the standard API calls above, devices also have a special API for rendering config context:
```
ret = nb.dcim.devices.render_config(107)
```

### Endpoints

The methods on the api's correspond to the NetBox REST API - the best reference to the objects that can be called is by using the [browsable API](https://demo.netbox.dev/api/) on the netbox instance. The root objects that can be called are:

- circuits
- core
- dcim
- extras
- ipam
- plugins
- status
- tenancy
- users
- virtualization
- wireless

circuits would have 'circuit_terminations', 'circuit_types', etc... off of it. Each of the endpoints has 'list', 'get', 'create', 'update' and 'delete' functions.


## Return Object

The return object from the API calls is a dictionary with two values (response and data). **data** is the actual data returned from the call and response contains detailed information on the call, including the HTTP status code returned. Netbox-python is a wrapper around the python [requests](https://github.com/psf/requests) library. Detailed information on the response object can be found in python requests library [documentation](https://requests.readthedocs.io/en/latest/). After making an API call you can check the status code and get the returned data as follows:

```
ret = nb.dcim.sites.all()
print(f"status code: {ret.response.status_code}")
print(ret.data)
```
4 changes: 4 additions & 0 deletions netbox_python/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from netbox_python.api.asn_range import asn_range
from netbox_python.api.circuits import circuits
from netbox_python.api.core import core
from netbox_python.api.dcim import dcim
from netbox_python.api.extras import extras
from netbox_python.api.ip_range import ip_range
from netbox_python.api.ipam import ipam
from netbox_python.api.plugins import plugins
from netbox_python.api.prefix import prefix
from netbox_python.api.tenancy import tenancy
from netbox_python.api.users import users
from netbox_python.api.virtualization import virtualization
from netbox_python.api.vlan_group import vlan_group
from netbox_python.api.wireless import wireless
10 changes: 10 additions & 0 deletions netbox_python/api/asn_range.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from netbox_python.baseapi import AvailableAPIResource


class asn_range:
def __init__(self, client):
self.available_asns = self._available_asns(client)
super().__init__()

class _available_asns(AvailableAPIResource):
path = "ipam/asn-ranges/{id}/available-asns"
6 changes: 5 additions & 1 deletion netbox_python/api/dcim.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from netbox_python.baseapi import APIResource
from netbox_python.baseapi import APIResource, CreateableAPIResource
from netbox_python.rest import Result


class dcim:
Expand Down Expand Up @@ -83,6 +84,9 @@ class _device_types(APIResource):
class _devices(APIResource):
path = "dcim/devices/"

def render_config(self, id: str | int, *args, **kwargs) -> Result:
return self._create(f"{self.path}{id}/render-config/", *args, **kwargs)

class _front_port_templates(APIResource):
path = "dcim/front-port-templates/"

Expand Down
4 changes: 4 additions & 0 deletions netbox_python/api/extras.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from netbox_python.baseapi import APIResource
from netbox_python.rest import Result


class extras:
Expand Down Expand Up @@ -26,6 +27,9 @@ class _config_contexts(APIResource):
class _config_templates(APIResource):
path = "extras/config-templates/"

def render(self, id: str | int, *args, **kwargs) -> Result:
return self._create(f"{self.path}{id}/render/", *args, **kwargs)

class _content_types(APIResource):
path = "extras/content-types/"

Expand Down
10 changes: 10 additions & 0 deletions netbox_python/api/ip_range.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from netbox_python.baseapi import AvailableAPIResource


class ip_range:
def __init__(self, client):
self.available_ips = self._available_ips(client)
super().__init__()

class _available_ips(AvailableAPIResource):
path = "ipam/ip-ranges/{id}/available-ips"
10 changes: 10 additions & 0 deletions netbox_python/api/ipam.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
from netbox_python.api.asn_range import asn_range
from netbox_python.api.ip_range import ip_range
from netbox_python.api.prefix import prefix
from netbox_python.api.vlan_group import vlan_group
from netbox_python.baseapi import APIResource


class ipam:
def __init__(self, client):
self.aggregates = self._aggregates(client)
self.asns = self._asns(client)
self.asn_ranges = self._asn_ranges(client)
self.asn_range = asn_range(client)
self.fhrp_group_assignments = self._fhrp_group_assignments(client)
self.fhrp_groups = self._fhrp_groups(client)
self.ip_addresses = self._ip_addresses(client)
self.ip_ranges = self._ip_ranges(client)
self.ip_range = ip_range(client)
self.l2vpn_terminations = self._l2vpn_terminations(client)
self.l2vpns = self._l2vpns(client)
self.prefixes = self._prefixes(client)
Expand All @@ -28,6 +35,9 @@ class _aggregates(APIResource):
class _asns(APIResource):
path = "ipam/asns/"

class _asn_ranges(APIResource):
path = "ipam/asn-ranges/"

class _fhrp_group_assignments(APIResource):
path = "ipam/fhrp-group-assignments/"

Expand Down
14 changes: 14 additions & 0 deletions netbox_python/api/prefix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from netbox_python.baseapi import AvailableAPIResource


class prefix:
def __init__(self, client):
self.available_ips = self._available_ips(client)
self.available_prefixes = self._available_prefixes(client)
super().__init__()

class _available_ips(AvailableAPIResource):
path = "ipam/prefixes/{id}/available-ips"

class _available_prefixes(AvailableAPIResource):
path = "ipam/prefixes/{id}/available-prefixes"
10 changes: 10 additions & 0 deletions netbox_python/api/vlan_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from netbox_python.baseapi import AvailableAPIResource


class vlan_group:
def __init__(self, client):
self.available_vlans = self._available_vlans(client)
super().__init__()

class _available_vlans(AvailableAPIResource):
path = "ipam/vlan-groups/{id}/available-vlans"
35 changes: 31 additions & 4 deletions netbox_python/baseapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ def __init__(self, client):


class CreateableAPIResource:
def _create(self, path, *args, **kwargs) -> Result:
return self.client.post(path, json=args[0] if args else kwargs)

def create(self, *args, **kwargs) -> Result:
return self.client.post(self.path, json=args[0] if args else kwargs)
return self._create(self.path, *args, **kwargs)


class DeletableAPIResource:
Expand All @@ -33,12 +36,15 @@ def paginate(self, result: Result) -> Result:
yield result
next_token = result.pagination["next"]

def _list(self, path, **kwargs) -> Result:
return self.client.get(path, params=kwargs)

def list(self, **kwargs) -> Result:
return self.client.get(self.path, params=kwargs)
return self._list(self.path, **kwargs)

def all(self, **kwargs):
def _all(self, path, **kwargs):
result = None
for page in self.paginate(self.client.get(self.path, params=kwargs)):
for page in self.paginate(self._list(path, **kwargs)):
if not result:
result = page
else:
Expand All @@ -48,6 +54,9 @@ def all(self, **kwargs):
result.pagination["previous"] = None
return result

def all(self, **kwargs):
return self._all(self.path, **kwargs)


class RetrievableAPIResource:
def get(self, id: str | int) -> Result:
Expand Down Expand Up @@ -86,3 +95,21 @@ class ROAPIResource(
UpdateableAPIResource,
):
pass


class AvailableAPIResource(
baseapi,
CreateableAPIResource,
ListableAPIResource,
):
def create(self, id: str | int, *args, **kwargs) -> Result:
path = self.path.format(id=id)
return self._create(path, *args, **kwargs)

def list(self, id: str | int, **kwargs) -> Result:
path = self.path.format(id=id)
return self._list(path, **kwargs)

def all(self, id: str | int, **kwargs):
path = self.path.format(id=id)
return self._all(path, **kwargs)
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.5
current_version = 0.1.6
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@
test_suite="tests",
tests_require=test_requirements,
url="https://github.com/netbox-community/netbox_python",
version="0.1.5",
version="0.1.6",
zip_safe=False,
)