pynetbox icon indicating copy to clipboard operation
pynetbox copied to clipboard

Assigning assigned_object to None doesn't work unless it's referenced

Open aj2s opened this issue 3 months ago • 5 comments

pynetbox version

v7.5.0

NetBox version

v4.3.7

Python version

3.12

Steps to Reproduce

mac_address = nb.dcim.mac_addresses.get(id=30180)
interface = mac_address.assigned_object

# Uncommenting this gets it working as expected
# print(interface.primary_mac_address)

interface.primary_mac_address = None
print(interface.save())

Expected Behavior

I expected the primary mac address to be unset

Observed Behavior

The primary mac address was still set.

aj2s avatar Sep 30 '25 02:09 aj2s

@aj2s This works fine for me, the primary Mac addresss was reset checked in both API and UI. Can you please double-check.

mac_address = nb.dcim.mac_addresses.get(id=1)
print(mac_address)
interface = mac_address.assigned_object
print(interface.primary_mac_address)
interface.primary_mac_address = None
interface.save()
mac_address = nb.dcim.mac_addresses.get(id=1)
interface = mac_address.assigned_object
print(interface.primary_mac_address)

arthanson avatar Sep 30 '25 15:09 arthanson

Thanks for the quick triage! That does work, but that's only because there's the call to print(interface.primary_mac_address) on line 4. It does not work for me when I *do not print / reference interface.primary_mac_address anywhere.

Is that expected? If so, it's not intuitive to me.

Here's an updated snippet with the line in question separated out for clarity

nb = pynetbox.api(os.environ["NETBOX_URL"], os.environ["NETBOX_TOKEN"])
mac_address = nb.dcim.mac_addresses.get(id=MAC_ADDRESS_ID)
interface = mac_address.assigned_object

# Commenting this out / not referencing interface.primary_mac_address causes this snippet to not update interface.primary_mac_address on interface.save()
print("primary mac before", interface.primary_mac_address)

interface.primary_mac_address = None
interface.save()
mac_address = nb.dcim.mac_addresses.get(id=MAC_ADDRESS_ID)
interface = mac_address.assigned_object
print("primary mac after", interface.primary_mac_address)

aj2s avatar Sep 30 '25 17:09 aj2s

I have confirmed the call to save() is not triggering any network request. From what I understand, that means that the call to _diff detects no change, right? I'm interested in deepening my understanding of how pynetbox works internally, but that will not be this week :)

Script:

import os
import pynetbox
import logging

MAC_ADDRESS_ID = 30180

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s: %(message)s")
nb = pynetbox.api(os.environ["NETBOX_URL"], os.environ["NETBOX_TOKEN"])

mac_address = nb.dcim.mac_addresses.get(id=MAC_ADDRESS_ID)
interface = mac_address.assigned_object

logging.info("Setting primary_mac_address to None")
interface.primary_mac_address = None

logging.info("Saving")
interface.save()
logging.info("Supposedly saved")

mac_address = nb.dcim.mac_addresses.get(id=MAC_ADDRESS_ID)
interface = mac_address.assigned_object
logging.info("primary mac after: %s", interface.primary_mac_address)

Output (with redacted domain):

DEBUG: Starting new HTTPS connection (1): netbox.example.com:443
DEBUG: https://netbox.example.com:443 "GET /api/dcim/mac-addresses/?id=30180&limit=0 HTTP/1.1" 200 923
INFO: Setting primary_mac_address to None
INFO: Saving
INFO: Supposedly saved
DEBUG: https://netbox.example.com:443 "GET /api/dcim/mac-addresses/?id=30180&limit=0 HTTP/1.1" 200 923
DEBUG: https://netbox.example.com:443 "GET /api/dcim/interfaces/24648/ HTTP/1.1" 200 797
DEBUG: https://netbox.example.com:443 "GET /api/dcim/mac-addresses/30180/ HTTP/1.1" 200 871
INFO: primary mac after: 8C:1F:64:05:5D:BF

aj2s avatar Sep 30 '25 20:09 aj2s

Does look like the print is causing it to be de-reffed and makes it work. Adding to backlog for more investigation as it does not seem correct.

arthanson avatar Oct 03 '25 16:10 arthanson

Leaving a fix here: https://github.com/netbox-community/pynetbox/compare/master...NeverBehave:pynetbox:nb/test-1?expand=1

It is mostly caused by new fields not properly tracked if API does not return it in the first place AFAIK. Not sure if it is the best way to handle this situation.

NeverBehave avatar Dec 09 '25 23:12 NeverBehave

@NeverBehave, would you like to take ownership of this one?

jnovinger avatar Dec 17 '25 23:12 jnovinger

@NeverBehave, would you like to take ownership of this one?

You can assign me on this since I already have a working branch.

NeverBehave avatar Dec 17 '25 23:12 NeverBehave