netbox-bgp
netbox-bgp copied to clipboard
BGP session pynetbox Update method errors with error 400 when specific attributes are sent
NetBox version Tested on Netbox v.3.2.1 and v3.0.10. netbox_bgp v0.6.1
Describe the bug BGP session (/api/plugins/bgp/session/) Update method using Pynetbox, returns a 400 error (Bad Request: {'error': ['BGP Session with this Device, Local address, Local AS, Remote address and Remote AS already exists.']}), when already existing attributes 'device', 'local_address', 'local_as', 'remote_address and 'remote_as' are sent to the endpoint.
I am using Pynetbox to move data from a different inventory to Netbox, with a simple logic:
- Build a dictionary object from a separate inventory to be sent to Netbox
- Get the existing object from Netbox with the .get() method.
- If .get() returns None, use the .create() method to create a new object in Netbox.
- If .get() is not None, use the .update() method to check if there are any updates needed on the object.
- Based on the True/False return result of .update(), the script informs if there were any changes made.
By default on all Netbox endpoints, .update()(PATCH) returns True if the sent data is different from Netbox. Returns False if the sent data and Netbox data matches. The only endpoint where this doesn't work is the BGP plugin Session endpoint, when all 'device', 'local_address', 'local_as', 'remote_address' and 'remote_as are specified. It doesn't return the error, if at least one of these attributes is not sent.
I would expect for this error to be returned when the .create()(POST) method is called, so we don't create duplicate entries, but not with the .update()(PATCH) method.
I am not an advanced user, so not creating this as a BUG, but just as a plain issue. Please let me know if I am missing something basic here, or this is in fact a BUG.
Thank you!
To Reproduce
>>> inventory_data = {
... "device": {"name": "TestDevice"},
... "local_address": {"address": "1.1.1.1/32"},
... "local_as": {"number": 65555},
... "remote_address": {"address": "1.1.1.2/32"},
... "remote_as": {"number": 65556},
... "site": {"name": "TestSite"},
... "name": "test_name:ISP",
... "description": "ISP",
... }
>>> bgp_session = netbox.plugins.bgp.session.get(name=inventory_data["name"])
>>> pprint(dict(bgp_session))
{'created': '2022-05-10T14:51:59.555795Z',
'custom_field_data': {},
'custom_fields': {},
'description': 'ISP',
'device': {'display': 'TestDevice',
'id': 315,
'name': 'TestDevice',
'url': 'https://10.10.10.10/api/dcim/devices/315/'},
'display': 'TestDevice:test_name:ISP',
'export_policies': [],
'id': 613,
'import_policies': [],
'last_updated': '2022-05-12T09:03:10.126122Z',
'local_address': {'address': '1.1.1.1/32',
'display': '1.1.1.1/32',
'family': 4,
'id': 498,
'url': 'https://10.10.10.10/api/ipam/ip-addresses/498/'},
'local_as': {'description': 'Local_AS',
'id': 34,
'number': 65555,
'url': 'https://10.10.10.10/plugins/bgp/asn/34/'},
'name': 'test_name:ISP',
'peer_group': None,
'remote_address': {'address': '1.1.1.2/32',
'display': '1.1.1.2/32',
'family': 4,
'id': 499,
'url': 'https://10.10.10.10/api/ipam/ip-addresses/499/'},
'remote_as': {'description': 'Remote_AS',
'id': 35,
'number': 65556,
'url': 'https://10.10.10.10/plugins/bgp/asn/35/'},
'site': {'display': 'TestSite',
'id': 294,
'name': 'TestSite',
'slug': 'testsite',
'url': 'https://10.10.10.10/api/dcim/sites/294/'},
'status': {'label': 'Active', 'value': 'active'},
'tags': [],
'tenant': None}
>>> bgp_session.update(inventory_data)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/*/Library/Python/3.8/lib/python/site-packages/pynetbox/core/response.py", line 565, in update
return self.save()
File "/Users/*/Library/Python/3.8/lib/python/site-packages/pynetbox/core/response.py", line 538, in save
if req.patch(updates):
File "/Users/*/Library/Python/3.8/lib/python/site-packages/pynetbox/core/query.py", line 427, in patch
return self._make_call(verb="patch", data=data)
File "/Users/*/Library/Python/3.8/lib/python/site-packages/pynetbox/core/query.py", line 287, in _make_call
raise RequestError(req)
pynetbox.core.query.RequestError: The request failed with code 400 Bad Request: {'error': ['BGP Session with this Device, Local address, Local AS, Remote address and Remote AS already exists.']}
Expected behavior No changes made to the object and the Update returns False
Screenshots n/a - the output above should be sufficient.
Additional context
{'django-version': '4.0.4',
'installed-apps': {'debug_toolbar': '3.2.4',
'django_filters': '21.1',
'django_prometheus': '2.2.0',
'django_rq': '2.5.1',
'django_tables2': '2.4.1',
'drf_yasg': '1.20.0',
'graphene_django': '2.15.0',
'graphiql_debug_toolbar': '0.2.0',
'mptt': '0.13.4',
'netbox_bgp': '0.6.1',
'rest_framework': '3.13.1',
'social_django': '5.0.0',
'taggit': '2.1.0',
'timezone_field': '5.0'},
'netbox-version': '3.2.1',
'plugins': {'netbox_bgp': '0.6.1'},
'python-version': '3.9.2',
'rq-workers-running': 1}```
Should be related to commit e391240c54f64ed6528b4e838efd775637e0b149, as removing that validate() function, fixes this