netbox-community / pynetbox

Python API client library for Netbox.
Apache License 2.0
538 stars 165 forks source link

Cables.serialize() is inconsistent #555

Open srfwx opened 1 year ago

srfwx commented 1 year ago

Hi,

I am currently looking at upgrading our NetBox instance to the latest version, which means jumping over 3.3 with breaking changes in the Cable model.

Thanks @arthanson for the adapted Pynetbox version 7! Seems to work well for most of our usage. However I am slightly concerned with the output of the .serialize() method on Cable objects.

Indeed, when looking at the raw API output for a cable, we have the object, object_id and object_type values for each of the a_terminations and b_terminations :

{
    "id": 242006,
    "url": "http://0.0.0.0:8000/api/dcim/cables/242006/",
    "display": "#242006",
    "type": "",
    "a_terminations": [
        {
            "object_type": "dcim.interface",
            "object_id": 838544,
            "object": {
                "id": 838544,
                "url": "http://0.0.0.0:8000/api/dcim/interfaces/838544/",
                "display": "Ethernet22 (22)",
                "device": {
                    "id": 106322,
                    "url": "http://0.0.0.0:8000/api/dcim/devices/106322/",
                    "display": "ENGINE-RED-13.SW02R",
                    "name": "ENGINE-RED-13.SW02R"
                },
                "name": "Ethernet22",
                "cable": 242006,
                "_occupied": true
            }
        }
    ],

However, it looks like the new generic_list_parser is "obfuscating" this by reconstructing a list of Rear/FrontPorts/Interfaces objects. Kind of nice, but then when you call serialize() the output is as follows:

{'a_terminations': [838544],
 'b_terminations': [838887],
 'color': '',
 'comments': '',
 'created': '2023-03-23T14:59:10.939106Z',
 'custom_fields': {'copied_from': None, 'last_sync': None},
 'description': '',
 'display': '#242006',
 'id': 242006,
 'label': '',
 'last_updated': '2023-03-23T14:59:10.939131Z',
 'length': None,
 'length_unit': None,
 'status': 'connected',
 'tags': [38],
 'tenant': 3962,
 'type': '',
 'url': 'http://172.17.0.1:8000/api/dcim/cables/242006/'}

The docstring for serialize() says "Pulls all the attributes in an object and creates a dict that can be turned into the json that netbox is expecting."

I don't think this is the case here, as the POST action needs the dict structure with object_id and object_type in the termination list.

On a side note, we've implemented an extra caching layer between our app and Pynetbox where we store the raw/seralized records. When calling back this data and asking Pynetbox to reconstruct objects, we're now getting plain "Record" objects instead of Rear/FrontPorts/Interfaces because of the missing fields.

Shouldn't generic_list_parser keep the API structure and put the Port object into the "object" field ?