Skip to content

Commit

Permalink
Add render_config, update docs, v0.1.6 (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
arthanson authored Jun 8, 2023
1 parent ca5a9aa commit b265733
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 7 deletions.
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,
)

0 comments on commit b265733

Please sign in to comment.