def all(self): """Queries the 'ListView' of a given endpoint. Returns all objects from an endpoint. :Returns: List of :py:class:`.Record` objects. :Examples: >>> nb.dcim.devices.all() [test1-a3-oobsw2, test1-a3-oobsw3, test1-a3-oobsw4] >>> """ req = Request( base="{}/".format(self.url), token=self.token, session_key=self.session_key, http_session=self.api.http_session, threading=self.api.threading, ) get_req = req.get() self.api.api_version = req.api_version return response_loader(get_req, self.return_obj, self)
def test_get_manual_pagination(self): test_obj = Request( http_session=Mock(), base="http://localhost:8001/api/dcim/devices", limit=10, offset=20, ) test_obj.http_session.get.return_value.json.return_value = { "count": 4, "next": "http://localhost:8001/api/dcim/devices?limit=10&offset=30", "previous": False, "results": [1, 2, 3, 4], } expected = call( "http://localhost:8001/api/dcim/devices/", params={ "offset": 20, "limit": 10 }, headers={"accept": "application/json;"}, ) test_obj.http_session.get.ok = True generator = test_obj.get() self.assertEqual(len(list(generator)), 4) test_obj.http_session.get.assert_called_with( "http://localhost:8001/api/dcim/devices/", params={ "offset": 20, "limit": 10 }, headers={"accept": "application/json;"}, json=None, )
def get(self, *args, **kwargs): r"""Queries the DetailsView of a given endpoint. :arg int,optional key: id for the item to be retrieved. :arg str,optional \**kwargs: Accepts the same keyword args as filter(). Any search argument the endpoint accepts can be added as a keyword arg. :returns: A single :py:class:`.Record` object or None :raises ValueError: if kwarg search return more than one value. :Examples: Referencing with a kwarg that only returns one value. >>> nb.dcim.devices.get(name='test1-a3-tor1b') test1-a3-tor1b >>> Referencing with an id. >>> nb.dcim.devices.get(1) test1-edge1 >>> """ try: key = args[0] except IndexError: key = None if not key: filter_lookup = self.filter(**kwargs) if filter_lookup: if len(filter_lookup) > 1: raise ValueError( "get() returned more than one result. " "Check that the kwarg(s) passed are valid for this " "endpoint or use filter() or all() instead." ) else: return filter_lookup[0] return None try: req = Request( key=key, base=self.url, token=self.token, session_key=self.session_key, http_session=self.api.http_session, ) except RequestError: return None return response_loader(req.get(), self.return_obj, self)
def getnext(self, *args): try: offset = args[0] except IndexError: offset = 0 req = Request( offset=offset, base=self.url, token=self.token, session_key=self.session_key, http_session=self.api.http_session, ) return response_loader(req.get(), self.return_obj, self)
def trace(self): req = Request( key=str(self.id) + "/trace", base=self.endpoint.url, token=self.api.token, session_key=self.api.session_key, http_session=self.api.http_session, ) uri_to_obj_class_map = { "dcim/cables": Cables, "dcim/front-ports": FrontPorts, "dcim/interfaces": Interfaces, "dcim/rear-ports": RearPorts, } ret = [] for (termination_a_data, cable_data, termination_b_data) in req.get(): this_hop_ret = [] for hop_item_data in (termination_a_data, cable_data, termination_b_data): # if not fully terminated then some items will be None if not hop_item_data: this_hop_ret.append(hop_item_data) continue # TODO: Move this to a more general function. app_endpoint = "/".join( urlsplit(hop_item_data["url"] [len(self.api.base_url):]).path.split("/")[1:3]) return_obj_class = uri_to_obj_class_map.get( app_endpoint, Record, ) this_hop_ret.append( return_obj_class(hop_item_data, self.endpoint.api, self.endpoint)) ret.append(this_hop_ret) return ret
def full_details(self): """Queries the hyperlinked endpoint if 'url' is defined. This method will populate the attributes from the detail endpoint when it's called. Sets the class-level `has_details` attribute when it's called to prevent being called more than once. :returns: True """ if self.url: req = Request( base=self.url, token=self.api.token, session_key=self.api.session_key, http_session=self.api.http_session, ) self._parse_values(next(req.get())) self.has_details = True return True return False
def all(self): """Queries the 'ListView' of a given endpoint. Returns all objects from an endpoint. :Returns: List of :py:class:`.Record` objects. :Examples: >>> nb.dcim.devices.all() [test1-a3-oobsw2, test1-a3-oobsw3, test1-a3-oobsw4] >>> """ req = Request( base="{}/".format(self.url), token=self.token, session_key=self.session_key, ssl_verify=self.ssl_verify, ) return [self._response_loader(i) for i in req.get()]
def list(self, **kwargs): r"""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 retrieved from NetBox. """ req = Request(**self.request_kwargs) resp = req.get(add_params=kwargs) self.api.api_version = req.api_version if self.custom_return: return response_loader(resp, self.custom_return, self.parent_obj.endpoint) return req
def filter(self, *args, **kwargs): r"""Queries the 'ListView' of a given endpoint. Takes named arguments that match the usable filters on a given endpoint. If an argument is passed then it's used as a freeform search argument if the endpoint supports it. :arg str,optional \*args: Freeform search string that's accepted on given endpoint. :arg str,optional \**kwargs: Any search argument the endpoint accepts can be added as a keyword arg. :Returns: A list of :py:class:`.Record` objects. :Examples: To return a list of objects matching a named argument filter. >>> nb.dcim.devices.filter(role='leaf-switch') [test1-a3-tor1b, test1-a3-tor1c, test1-a3-tor1d, test1-a3-tor2a] >>> Using a freeform query along with a named argument. >>> nb.dcim.devices.filter('a3', role='leaf-switch') [test1-a3-tor1b, test1-a3-tor1c, test1-a3-tor1d, test1-a3-tor2a] >>> Chaining multiple named arguments. >>> nb.dcim.devices.filter(role='leaf-switch', status=True) [test1-leaf2] >>> Passing a list as a named argument adds multiple filters of the same value. >>> nb.dcim.devices.filter(role=['leaf-switch', 'spine-switch']) [test1-a3-spine1, test1-a3-spine2, test1-a3-leaf1] >>> """ if args: kwargs.update({"q": args[0]}) if not kwargs: raise ValueError( "filter must be passed kwargs. Perhaps use all() instead." ) if any(i in RESERVED_KWARGS for i in kwargs): raise ValueError( "A reserved {} kwarg was passed. Please remove it " "try again.".format(RESERVED_KWARGS) ) req = Request( filters=kwargs, base=self.url, token=self.token, session_key=self.session_key, ssl_verify=self.ssl_verify, http_session=self.api.http_session, threading=self.api.threading, ) ret = [self._response_loader(i) for i in req.get()] return ret
def test_pagination(self): test_obj = Request(http_session=Mock(), base="http://localhost:8001/api/dcim/devices/", limit=2, external_proxy=False) test_obj.http_session.get.return_value.json.return_value = { "count": 6, "next": "http://localhost:8001/api/dcim/devices/?limit=2&offset=2", "previous": None, "results": [ { 'id': 87861, 'url': 'https://localhost:8001/api/dcim/devices/87861/', 'name': 'test87861' }, { 'id': 87862, 'url': 'https://localhost:8001/api/dcim/devices/87862/', 'name': 'test87862' }, ], } test = test_obj.get() req = next(test) test_obj.http_session.get.assert_called_with( "http://localhost:8001/api/dcim/devices/", headers={"accept": "application/json;"}, params={"limit": 2}, json=None, ) self.assertEqual( req, { 'id': 87861, 'url': 'https://localhost:8001/api/dcim/devices/87861/', 'name': 'test87861' }) req = next(test) self.assertEqual( req, { 'id': 87862, 'url': 'https://localhost:8001/api/dcim/devices/87862/', 'name': 'test87862' }) test_obj.http_session.get.return_value.json.return_value = { "count": 2, "next": "http://localhost:8001/api/dcim/devices/?limit=2&offset=4", "previous": "http://localhost:8001/api/dcim/devices/?limit=2", "results": [ { 'id': 87863, 'url': 'https://localhost:8001/api/dcim/devices/87863/', 'name': 'test87863' }, { 'id': 87864, 'url': 'https://localhost:8001/api/dcim/devices/87864/', 'name': 'test87864' }, ], } req = next(test) test_obj.http_session.get.assert_called_with( "http://localhost:8001/api/dcim/devices/", headers={"accept": "application/json;"}, params={ "limit": 2, "offset": 2 }, json=None, ) self.assertEqual( req, { 'id': 87863, 'url': 'https://localhost:8001/api/dcim/devices/87863/', 'name': 'test87863' }) req = next(test) self.assertEqual( req, { 'id': 87864, 'url': 'https://localhost:8001/api/dcim/devices/87864/', 'name': 'test87864' }) test_obj.http_session.get.return_value.json.return_value = { "count": 2, "next": None, "previous": "http://localhost:8001/api/dcim/devices/?limit=2&offset=4", "results": [ { 'id': 87865, 'url': 'https://localhost:8001/api/dcim/devices/87865/', 'name': 'test87865' }, { 'id': 87866, 'url': 'https://localhost:8001/api/dcim/devices/87866/', 'name': 'test87866' }, ], } req = next(test) test_obj.http_session.get.assert_called_with( "http://localhost:8001/api/dcim/devices/?limit=2&offset=4", headers={"accept": "application/json;"}, params={}, json=None, ) self.assertEqual( req, { 'id': 87865, 'url': 'https://localhost:8001/api/dcim/devices/87865/', 'name': 'test87865' }) req = next(test) self.assertEqual( req, { 'id': 87866, 'url': 'https://localhost:8001/api/dcim/devices/87866/', 'name': 'test87866' })