Beispiel #1
0
 def test_get_count(self):
     test_obj = Request(
         http_session=Mock(),
         base="http://localhost:8001/api/dcim/devices",
         filters={"q": "abcd"},
     )
     test_obj.http_session.get.return_value.json.return_value = {
         "count": 42,
         "next":
         "http://localhost:8001/api/dcim/devices?limit=1&offset=1&q=abcd",
         "previous": False,
         "results": [],
     }
     expected = call(
         "http://localhost:8001/api/dcim/devices/",
         params={
             "q": "abcd",
             "limit": 1
         },
         headers={"accept": "application/json;"},
     )
     test_obj.http_session.get.ok = True
     test = test_obj.get_count()
     self.assertEqual(test, 42)
     test_obj.http_session.get.assert_called_with(
         "http://localhost:8001/api/dcim/devices/",
         params={
             "q": "abcd",
             "limit": 1
         },
         headers={"accept": "application/json;"},
         json=None,
     )
Beispiel #2
0
    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)
Beispiel #3
0
    def save(self):
        """Saves changes to an existing object.

        Takes a diff between the objects current state and its state at init
        and sends them as a dictionary to Request.patch().

        :returns: True if PATCH request was successful.
        :example:

        >>> x = nb.dcim.devices.get(name='test1-a3-tor1b')
        >>> x.serial
        u''
        >>> x.serial = '1234'
        >>> x.save()
        True
        >>>
        """
        if self.id:
            diff = self._diff()
            if diff:
                serialized = self.serialize()
                req = Request(
                    key=self.id,
                    base=self.endpoint.url,
                    token=self.api.token,
                    session_key=self.api.session_key,
                    http_session=self.api.http_session,
                )
                if req.patch({i: serialized[i] for i in diff}):
                    self.api.api_version = req.api_version
                    return True

        return False
Beispiel #4
0
 def test_get_openapi(self):
     test = Request("http://localhost:8080/api", Mock())
     test.get_openapi()
     test.http_session.get.assert_called_with(
         "http://localhost:8080/api/docs/?format=openapi",
         headers={"Content-Type": "application/json;"},
     )
Beispiel #5
0
 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,
     )
Beispiel #6
0
    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)
Beispiel #7
0
    def delete(self, objects):
        r"""Bulk deletes objects on an endpoint.

        Allows for batch deletion of multiple objects from
        a single endpoint

        :arg list objects: A list of either ids or Records or
            a single RecordSet to delete.
        :returns: True if bulk DELETE operation was successful.

        :Examples:

        Deleting all `devices`:

        >>> netbox.dcim.devices.delete(netbox.dcim.devices.all(0))
        >>>

        Use bulk deletion by passing a list of ids:

        >>> netbox.dcim.devices.delete([2, 243, 431, 700])
        >>>

        Use bulk deletion to delete objects eg. when filtering
        on a `custom_field`:
        >>> netbox.dcim.devices.delete([
        >>>         d for d in netbox.dcim.devices.all(0) \
        >>>             if d.custom_fields.get('field', False)
        >>>     ])
        >>>
        """
        cleaned_ids = []
        if not isinstance(objects, list) and not isinstance(
                objects, RecordSet):
            raise ValueError("objects must be list[str|int|Record]"
                             "|RecordSet - was " + str(type(objects)))
        for o in objects:
            if isinstance(o, int):
                cleaned_ids.append(o)
            elif isinstance(o, str) and o.isnumeric():
                cleaned_ids.append(int(o))
            elif isinstance(o, Record):
                if not hasattr(o, "id"):
                    raise ValueError(
                        "Record from '" + o.url +
                        "' does not have an id and cannot be bulk deleted")
                cleaned_ids.append(o.id)
            else:
                raise ValueError("Invalid object in list of "
                                 "objects to delete: " + str(type(o)))

        req = Request(
            base=self.url,
            token=self.token,
            session_key=self.session_key,
            http_session=self.api.http_session,
        )
        return True if req.delete(data=[{
            "id": i
        } for i in cleaned_ids]) else False
Beispiel #8
0
 def load_models(item):
     app, url = item
     appobj = getattr(self.netbox, app)
     models = Request(url, self.netbox.http_session).get()
     for model in models.keys():
         if model[0] != '_':
             modelname = model.title().replace('-', '')
             modelobj = getattr(appobj, model.replace('-', '_'))
             if app == 'virtualization' and model == "interfaces":
                 modelname = 'VirtualInterfaces'
             self.ns[modelname] = modelobj
Beispiel #9
0
    def choices(self):
        """ Returns all choices from the endpoint.

        The returned dict is also saved in the endpoint object (in
        ``_choices`` attribute) so that later calls will return the same data
        without recurring requests to NetBox. When using ``.choices()`` in
        long-running applications, consider restarting them whenever NetBox is
        upgraded, to prevent using stale choices data.

        :Returns: Dict containing the available choices.

        :Example (from NetBox 2.8.x):

        >>> from pprint import pprint
        >>> pprint(nb.ipam.ip_addresses.choices())
        {'role': [{'display_name': 'Loopback', 'value': 'loopback'},
                  {'display_name': 'Secondary', 'value': 'secondary'},
                  {'display_name': 'Anycast', 'value': 'anycast'},
                  {'display_name': 'VIP', 'value': 'vip'},
                  {'display_name': 'VRRP', 'value': 'vrrp'},
                  {'display_name': 'HSRP', 'value': 'hsrp'},
                  {'display_name': 'GLBP', 'value': 'glbp'},
                  {'display_name': 'CARP', 'value': 'carp'}],
         'status': [{'display_name': 'Active', 'value': 'active'},
                    {'display_name': 'Reserved', 'value': 'reserved'},
                    {'display_name': 'Deprecated', 'value': 'deprecated'},
                    {'display_name': 'DHCP', 'value': 'dhcp'}]}
        >>>
        """
        if self._choices:
            return self._choices

        req = Request(
            base=self.url,
            token=self.api.token,
            private_key=self.api.private_key,
            http_session=self.api.http_session,
        )
        req.options()
        self.api.api_version = req.api_version

        try:
            post_data = req["actions"]["POST"]
        except KeyError:
            raise ValueError(
                "Unexpected format in the OPTIONS response at {}".format(
                    self.url))
        self._choices = {}
        for prop in post_data:
            if "choices" in post_data[prop]:
                self._choices[prop] = post_data[prop]["choices"]

        return self._choices
Beispiel #10
0
    def count(self, *args, **kwargs):
        r"""Returns the count of objects in a query.

        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. If no
        arguments are passed the count for all objects on an endpoint
        are returned.

        :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: Integer with count of objects returns by query.

        :Examples:

        To return a count of objects matching a named argument filter.

        >>> nb.dcim.devices.count(site='tst1')
        5827
        >>>

        To return a count of objects on an entire endpoint.

        >>> nb.dcim.devices.count()
        87382
        >>>
        """

        if args:
            kwargs.update({"q": args[0]})

        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)
            )

        ret = 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,
        )

        return ret.get_count()
Beispiel #11
0
        def search(ep):
            req = Request(filters=dict(q=self.args.searchterm),
                          base=ep.url,
                          token=ep.token,
                          session_key=ep.session_key,
                          http_session=ep.api.http_session)

            rep = req._make_call(add_params=dict(limit=15))

            result = list()

            if rep.get('results'):
                result = response_loader(rep['results'], ep.return_obj, ep)

            return result
Beispiel #12
0
    def create(self, *args, **kwargs):
        r"""Creates an object on an endpoint.

        Allows for the creation of new objects on an endpoint. Named
        arguments are converted to json properties, and a single object
        is created. NetBox's bulk creation capabilities can be used by
        passing a list of dictionaries as the first argument.

        .. note:

            Any positional arguments will supercede named ones.

        :arg list \*args: A list of dictionaries containing the
            properties of the objects to be created.
        :arg str \**kwargs: key/value strings representing
            properties on a json object.

        :returns: A list or single :py:class:`.Record` object depending
            on whether a bulk creation was requested.

        :Examples:

        Creating an object on the `devices` endpoint:

        >>> device = netbox.dcim.devices.create(
        ...    name='test',
        ...    device_role=1,
        ... )
        >>>

        Use bulk creation by passing a list of dictionaries:

        >>> nb.dcim.devices.create([
        ...     {
        ...         "name": "test1-core3",
        ...         "device_role": 3,
        ...         "site": 1,
        ...         "device_type": 1,
        ...         "status": 1
        ...     },
        ...     {
        ...         "name": "test1-core4",
        ...         "device_role": 3,
        ...         "site": 1,
        ...         "device_type": 1,
        ...         "status": 1
        ...     }
        ... ])
        """

        req = Request(
            base=self.url,
            token=self.token,
            session_key=self.session_key,
            http_session=self.api.http_session,
        ).post(args[0] if args else kwargs)

        if isinstance(req, list):
            return [self.return_obj(i, self.api, self) for i in req]
        return self.return_obj(req, self.api, self)
Beispiel #13
0
    def all(self, limit=0, offset=None):
        """Queries the 'ListView' of a given endpoint.

        Returns all objects from an endpoint.

        :arg int,optional limit: Overrides the max page size on
            paginated returns.
        :arg int,optional offset: Overrides the offset on paginated returns.

        :Returns: A :py:class:`.RecordSet` object.

        :Examples:

        >>> devices = nb.dcim.devices.all()
        >>> for device in devices:
        ...     print(device.name)
        ...
        test1-leaf1
        test1-leaf2
        test1-leaf3
        >>>
        """
        if limit == 0 and offset is not None:
            raise ValueError("offset requires a positive limit value")
        req = Request(
            base="{}/".format(self.url),
            token=self.token,
            session_key=self.session_key,
            http_session=self.api.http_session,
            threading=self.api.threading,
            limit=limit,
            offset=offset,
        )

        return RecordSet(self, req)
Beispiel #14
0
    def custom_choices(self):
        """ Returns _custom_field_choices response from app

        .. note::

            This method only works with NetBox version 2.9.x or older. NetBox
            2.10.0 introduced the ``/extras/custom-fields/`` endpoint that can
            be used f.ex. like ``nb.extras.custom_fields.all()``.

        :Returns: Raw response from NetBox's _custom_field_choices endpoint.
        :Raises: :py:class:`.RequestError` if called for an invalid endpoint.
        :Example:

        >>> nb.extras.custom_choices()
        {'Testfield1': {'Testvalue2': 2, 'Testvalue1': 1},
         'Testfield2': {'Othervalue2': 4, 'Othervalue1': 3}}
        """
        custom_field_choices = Request(
            base="{}/{}/_custom_field_choices/".format(
                self.api.base_url,
                self.name,
            ),
            token=self.api.token,
            private_key=self.api.private_key,
            http_session=self.api.http_session,
        ).get()
        return custom_field_choices
Beispiel #15
0
    def all(self, limit=0):
        """Queries the 'ListView' of a given endpoint.

        Returns all objects from an endpoint.

        :arg int,optional limit: Overrides the max page size on
            paginated returns.

        :Returns: A :py:class:`.RecordSet` object.

        :Examples:

        >>> devices = nb.dcim.devices.all()
        >>> for device in devices:
        ...     print(device.name)
        ...
        test1-leaf1
        test1-leaf2
        test1-leaf3
        >>>
        """
        req = Request(
            base="{}/".format(self.url),
            token=self.token,
            session_key=self.session_key,
            http_session=self.api.http_session,
            threading=self.api.threading,
            limit=limit,
        )

        return RecordSet(self, req)
Beispiel #16
0
    def version(self):
        """ Gets the API version of NetBox.

        Can be used to check the NetBox API version if there are
        version-dependent features or syntaxes in the API.

        :Returns: Version number as a string.
        :Example:

        >>> import pynetbox
        >>> nb = pynetbox.api(
        ...     'http://localhost:8000',
        ...     private_key_file='/path/to/private-key.pem',
        ...     token='d6f4e314a5b5fefd164995169f28ae32d987704f'
        ... )
        >>> nb.version
        '2.6'
        >>>
        """
        version = Request(
            base=self.base_url,
            ssl_verify=self.ssl_verify,
            http_session=self.http_session,
        ).get_version()
        return version
Beispiel #17
0
    def create(self, data=None):
        """The write operation for a detail endpoint.

        Creates objects on a detail endpoint in NetBox.

        :arg dict/list,optional data: A dictionary containing the
            key/value pair of the items you're creating on the parent
            object. Defaults to empty dict which will create a single
            item with default values.

        :returns: A dictionary or list of dictionaries its created in
            NetBox.
        """
        if not data:
            return Request(**self.request_kwargs).post({})
        return Request(**self.request_kwargs).post(data)
Beispiel #18
0
    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).get(add_params=kwargs)

        if self.custom_return:
            if isinstance(req, list):
                return [
                    self.custom_return(
                        i, self.parent_obj.api, self.parent_obj.endpoint
                    )
                    for i in req
                ]
            return self.custom_return(
                req, self.parent_obj.api, self.parent_obj.endpoint
            )
        return req
Beispiel #19
0
    def create(self, data=None):
        """The write operation for a detail endpoint.

        Creates objects on a detail endpoint in NetBox.

        :arg dict/list,optional data: A dictionary containing the
            key/value pair of the items you're creating on the parent
            object. Defaults to empty dict which will create a single
            item with default values.

        :returns: A :py:class:`.Record` object or list of :py:class:`.Record` objects created
            from data created in NetBox.
        """
        data = data or {}
        req = Request(**self.request_kwargs).post(data)
        if self.custom_return:
            if isinstance(req, list):
                return [
                    self.custom_return(req_item, self.parent_obj.endpoint.api,
                                       self.parent_obj.endpoint)
                    for req_item in req
                ]
            else:
                return self.custom_return(req, self.parent_obj.endpoint.api,
                                          self.parent_obj.endpoint)
        return req
Beispiel #20
0
    def config(self):
        """ Returns config response from app

        :Returns: Raw response from NetBox's config endpoint.
        :Raises: :py:class:`.RequestError` if called for an invalid endpoint.
        :Example:

        >>> pprint.pprint(nb.users.config())
        {'tables': {'DeviceTable': {'columns': ['name',
                                                'status',
                                                'tenant',
                                                'device_role',
                                                'site',
                                                'primary_ip',
                                                'tags']}}}
        """
        config = Request(
            base="{}/{}/config/".format(
                self.api.base_url,
                self.name,
            ),
            token=self.api.token,
            private_key=self.api.private_key,
            http_session=self.api.http_session,
        ).get()
        return config
Beispiel #21
0
    def status(self):
        """Gets the status information from NetBox.

        Available in NetBox 2.10.0 or newer.

        :Returns: Dictionary as returned by NetBox.
        :Raises: :py:class:`.RequestError` if the request is not successful.
        :Example:

        >>> pprint.pprint(nb.status())
        {'django-version': '3.1.3',
         'installed-apps': {'cacheops': '5.0.1',
                            'debug_toolbar': '3.1.1',
                            'django_filters': '2.4.0',
                            'django_prometheus': '2.1.0',
                            'django_rq': '2.4.0',
                            'django_tables2': '2.3.3',
                            'drf_yasg': '1.20.0',
                            'mptt': '0.11.0',
                            'rest_framework': '3.12.2',
                            'taggit': '1.3.0',
                            'timezone_field': '4.0'},
         'netbox-version': '2.10.2',
         'plugins': {},
         'python-version': '3.7.3',
         'rq-workers-running': 1}
        >>>
        """
        status = Request(
            base=self.base_url,
            token=self.token,
            http_session=self.http_session,
        ).get_status()
        return status
Beispiel #22
0
    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)
Beispiel #23
0
    def update(self, objects):
        r"""Bulk updates existing objects on an endpoint.

        Allows for bulk updating of existing objects on an endpoint.
        Objects is a list whic contain either json/dicts or Record
        derived objects, which contain the updates to apply.
        If json/dicts are used, then the id of the object *must* be
        included

        :arg list objects: A list of dicts or Record.

        :returns: True if the update succeeded

        :Examples:

        Updating objects on the `devices` endpoint:

        >>> device = netbox.dcim.devices.update([
        ...    {'id': 1, 'name': 'test'},
        ...    {'id': 2, 'name': 'test2'},
        ... ])
        >>> True

        Use bulk update by passing a list of Records:

        >>> devices = nb.dcim.devices.all()
        >>> for d in devices:
        >>>     d.name = d.name+'-test'
        >>> nb.dcim.devices.update(devices)
        >>> True
        """
        series = []
        if not isinstance(objects, list):
            raise ValueError(
                "Objects passed must be list[dict|Record] - was " +
                type(objects))
        for o in objects:
            if isinstance(o, Record):
                data = o.updates()
                if data:
                    data["id"] = o.id
                    series.append(data)
            elif isinstance(o, dict):
                if "id" not in o:
                    raise ValueError("id is missing from object: " + str(o))
                series.append(o)
            else:
                raise ValueError("Object passed must be dict|Record - was " +
                                 type(objects))
        req = Request(
            base=self.url,
            token=self.token,
            session_key=self.session_key,
            http_session=self.api.http_session,
        ).patch(series)

        if isinstance(req, list):
            return [self.return_obj(i, self.api, self) for i in req]
        return self.return_obj(req, self.api, self)
Beispiel #24
0
    def __init__(
        self,
        url,
        token=None,
        private_key=None,
        private_key_file=None,
        ssl_verify=True,
        threading=False,
    ):
        if private_key and private_key_file:
            raise ValueError(
                '"private_key" and "private_key_file" cannot be used together.'
            )
        base_url = "{}/api".format(url if url[-1] != "/" else url[:-1])
        self.token = token
        self.private_key = private_key
        self.private_key_file = private_key_file
        self.base_url = base_url
        self.ssl_verify = ssl_verify
        self.session_key = None
        self.http_session = requests.Session()
        if threading and sys.version_info.major == 2:
            raise NotImplementedError("Threaded pynetbox calls not supported \
                in Python 2")
        self.threading = threading

        if self.private_key_file:
            with open(self.private_key_file, "r") as kf:
                private_key = kf.read()
                self.private_key = private_key

        req = Request(base=base_url,
                      token=token,
                      private_key=private_key,
                      ssl_verify=ssl_verify,
                      http_session=self.http_session)
        if self.token and self.private_key:
            self.session_key = req.get_session_key()

        self.dcim = App(self, "dcim")
        self.ipam = App(self, "ipam")
        self.circuits = App(self, "circuits")
        self.secrets = App(self, "secrets")
        self.tenancy = App(self, "tenancy")
        self.extras = App(self, "extras")
        self.virtualization = App(self, "virtualization")
Beispiel #25
0
    def delete(self):
        """Deletes an existing object.

        :returns: True if DELETE operation was successful.
        :example:

        >>> x = nb.dcim.devices.get(name='test1-a3-tor1b')
        >>> x.delete()
        True
        >>>
        """
        req = Request(
            key=self.id,
            base=self.endpoint.url,
            token=self.api.token,
            session_key=self.api.session_key,
            http_session=self.api.http_session,
        )
        return True if req.delete() else False
Beispiel #26
0
 def _set_session_key(self):
     if getattr(self.api, "session_key"):
         return
     if self.api.token and self.api.private_key:
         self.api.session_key = Request(
             base=self.api.base_url,
             token=self.api.token,
             private_key=self.api.private_key,
             http_session=self.api.http_session,
         ).get_session_key()
Beispiel #27
0
    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
Beispiel #28
0
    def __init__(
        self,
        url,
        token=None,
        private_key=None,
        private_key_file=None,
        ssl_verify=True,
    ):
        if private_key and private_key_file:
            raise ValueError(
                '"private_key" and "private_key_file" cannot be used together.'
            )
        base_url = "{}/api".format(url if url[-1] != "/" else url[:-1])
        self.token = token
        self.private_key = private_key
        self.private_key_file = private_key_file
        self.base_url = base_url
        self.ssl_verify = ssl_verify
        self.session_key = None

        if self.private_key_file:
            with open(self.private_key_file, "r") as kf:
                private_key = kf.read()
                self.private_key = private_key

        req = Request(
            base=base_url,
            token=token,
            private_key=private_key,
            ssl_verify=ssl_verify,
        )
        if self.token and self.private_key:
            self.session_key = req.get_session_key()

        self.dcim = App(self, "dcim")
        self.ipam = App(self, "ipam")
        self.circuits = App(self, "circuits")
        self.secrets = App(self, "secrets")
        self.tenancy = App(self, "tenancy")
        self.extras = App(self, "extras")
        self.virtualization = App(self, "virtualization")
Beispiel #29
0
    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
Beispiel #30
0
    def choices(self):
        """ Returns all choices from the endpoint.

        The returned dict is also saved in the endpoint object (in
        ``_choices`` attribute) so that later calls will return the same data
        without recurring requests to NetBox. When using ``.choices()`` in
        long-running applications, consider restarting them whenever NetBox is
        upgraded, to prevent using stale choices data.

        :Returns: Dict containing the available choices.

        :Examples:

        >>> from pprint import pprint
        >>> pprint(nb.ipam.ip_addresses.choices())
        {'role': [{'display_name': 'Secondary', 'value': 20},
                  {'display_name': 'VIP', 'value': 40},
                  {'display_name': 'VRRP', 'value': 41},
                  {'display_name': 'Loopback', 'value': 10},
                  {'display_name': 'GLBP', 'value': 43},
                  {'display_name': 'CARP', 'value': 44},
                  {'display_name': 'HSRP', 'value': 42},
                  {'display_name': 'Anycast', 'value': 30}],
         'status': [{'display_name': 'Active', 'value': 1},
                    {'display_name': 'Reserved', 'value': 2},
                    {'display_name': 'Deprecated', 'value': 3},
                    {'display_name': 'DHCP', 'value': 5}]}
        >>>
        """
        if self._choices:
            return self._choices

        req = Request(
            base=self.url,
            token=self.api.token,
            private_key=self.api.private_key,
            ssl_verify=self.api.ssl_verify,
            http_session=self.api.http_session,
        ).options()
        try:
            post_data = req['actions']['POST']
        except KeyError:
            raise ValueError(
                "Unexpected format in the OPTIONS response at {}".format(
                    self.url
                )
            )
        self._choices = {}
        for prop in post_data:
            if 'choices' in post_data[prop]:
                self._choices[prop] = post_data[prop]['choices']

        return self._choices