Skip to content

Commit

Permalink
Merge pull request #48 from digitalocean/napalm-endpoint
Browse files Browse the repository at this point in the history
Fixes #45 - NAPALM Endpoint Support
  • Loading branch information
Zach Moody committed Mar 29, 2018
2 parents 1069258 + 4b2a010 commit 07b71c2
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 3 deletions.
2 changes: 1 addition & 1 deletion pynetbox/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.0
3.3.0
22 changes: 22 additions & 0 deletions pynetbox/dcim.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
limitations under the License.
'''
from pynetbox.lib.response import Record
from pynetbox.lib.endpoint import RODetailEndpoint
from pynetbox.ipam import IpAddresses


Expand Down Expand Up @@ -43,6 +44,27 @@ class Devices(Record):
primary_ip4 = IpAddresses
primary_ip6 = IpAddresses

@property
def napalm(self):
""" Represents the ``napalm`` detail endpoint.
Returns a DetailEndpoint object that is the interface for
viewing response from the napalm endpoint.
:returns: :py:class:`.DetailEndpoint`
:Examples:
>>> device = nb.ipam.devices.get(123)
>>> device.napalm.list(method='get_facts')
{"get_facts": {"interface_list": ["ge-0/0/0"]}}
"""
return RODetailEndpoint(
'napalm',
parent_obj=self,
)


class InterfaceConnections(Record):

Expand Down
23 changes: 21 additions & 2 deletions pynetbox/lib/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'''
from collections import defaultdict

from pynetbox.lib.query import Request
from pynetbox.lib.query import Request, url_param_builder
from pynetbox.lib.response import Record, IPRecord

CACHE = defaultdict(list)
Expand Down Expand Up @@ -327,14 +327,25 @@ def __init__(self, name, parent_obj=None):
version=self.version,
)

def list(self):
def list(self, **kwargs):
"""The view operation for a detail endpoint
Returns the response from NetBox for a detail endpoint.
:args \**kwargs: key/value pairs that get converted into url
parameters when passed to the endpoint.
E.g. ``.list(method='get_facts')`` would be converted to
``.../?method=get_facts``.
:returns: A dictionary or list of dictionaries its retrieved
from NetBox.
"""
if kwargs:
self.request_kwargs['base'] = '{}{}'.format(
self.url,
url_param_builder(kwargs)
)

return Request(**self.request_kwargs).get()

def create(self, data={}):
Expand All @@ -351,3 +362,11 @@ def create(self, data={}):
NetBox.
"""
return Request(**self.request_kwargs).post(data)


class RODetailEndpoint(DetailEndpoint):

def create(self, data={}):
raise NotImplementedError(
'Writes are not supported for this endpoint.'
)
12 changes: 12 additions & 0 deletions pynetbox/lib/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@
import requests


def url_param_builder(param_dict):
'''Builds url parameters
Creates URL paramters (e.g. '.../?xyz=r21&abc=123') from a dict
passed in param_dict
'''
param_list = []
for key, val in param_dict.items():
param_list.append('{}={}'.format(key, val))
return '?{}'.format('&'.join(param_list))


class RequestError(Exception):
"""Basic Request Exception
Expand Down
14 changes: 14 additions & 0 deletions tests/fixtures/dcim/napalm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"get_facts": {
"interface_list": [
"xe-0/0/0"
],
"serial_number": "ABC!@#",
"vendor": "PacketPusher",
"os_version": "1.1",
"hostname": "test-1",
"model": "UnobtaniumX",
"fqdn": "None",
"uptime": 2
}
}
17 changes: 17 additions & 0 deletions tests/test_dcim.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,23 @@ def test_get_recurse(self, mock):
self.ret
))

@patch(
'pynetbox.lib.query.requests.get',
side_effect=[
Response(fixture='dcim/device.json'),
Response(fixture='dcim/napalm.json'),
]
)
def test_get_napalm(self, mock):
test = nb.devices.get(1)
ret = test.napalm.list(method='get_facts')
mock.assert_called_with(
'http://localhost:8000/api/dcim/devices/1/napalm/?method=get_facts',
headers=HEADERS
)
self.assertTrue(ret)
self.assertTrue(ret['get_facts'])


class SiteTestCase(unittest.TestCase, GenericTest):
name = 'sites'
Expand Down
14 changes: 14 additions & 0 deletions tests/test_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import unittest
from collections import OrderedDict

from pynetbox.lib.query import url_param_builder


class TestQuery(unittest.TestCase):

def test_url_param_builder(self):
test_params = OrderedDict([
('abc', '123'),
('xyz', '321'),
])
self.assertEqual(url_param_builder(test_params), '?abc=123&xyz=321')

0 comments on commit 07b71c2

Please sign in to comment.