From 55f662299730f2c99ec6f9484098b1d0b9f7824d Mon Sep 17 00:00:00 2001 From: Sven Luthi Date: Tue, 14 Jul 2026 14:53:12 +0200 Subject: [PATCH 1/4] modified: README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c3c3e9..4de3bf6 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,8 @@ multiple views yields unpredicted behavior. #### NOTIFY Clients may be notified of zone changes using the NOTIFY mechanism defined in RFC 1996. When enabled, the zone transfer endpoint keeps track of any client that successfully queried the -endpoint and when a zone changes. Once a zone has changed, NetBox informs each client of said -change. +endpoint. Once a zone has changed, NetBox informs each client about the zone changed so that the +client can request a new zone transfer. Note that this feature uses NetBox's background job system to schedule the messages asynchronously. In order to work, you need at least one `rq-worker` service running in the background to handle From e50cfd7cb61e9d848eb127b90c581d33673050a2 Mon Sep 17 00:00:00 2001 From: Sven Luthi Date: Tue, 14 Jul 2026 17:51:37 +0200 Subject: [PATCH 2/4] modified: netbox_dns_bridge/__init__.py Bump version --- netbox_dns_bridge/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox_dns_bridge/__init__.py b/netbox_dns_bridge/__init__.py index 5276320..2c0ecfe 100644 --- a/netbox_dns_bridge/__init__.py +++ b/netbox_dns_bridge/__init__.py @@ -2,7 +2,7 @@ from netbox.plugins import PluginConfig from django.conf import settings from .logger import get_logger -__version__ = "1.5.4" +__version__ = "1.5.5" LOGGER = get_logger(__name__) From 41d48f2807c4c21c39827ef5d85f4e36ef976b35 Mon Sep 17 00:00:00 2001 From: Sven Luthi Date: Wed, 15 Jul 2026 17:48:49 +0200 Subject: [PATCH 3/4] modified: netbox_dns_bridge/__init__.py modified: netbox_dns_bridge/catalog_zone_manager.py Fix wrong import in previous version and slight change to meachanism to create catz member identifier. --- netbox_dns_bridge/__init__.py | 2 +- netbox_dns_bridge/catalog_zone_manager.py | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/netbox_dns_bridge/__init__.py b/netbox_dns_bridge/__init__.py index 2c0ecfe..cd8e4af 100644 --- a/netbox_dns_bridge/__init__.py +++ b/netbox_dns_bridge/__init__.py @@ -2,7 +2,7 @@ from netbox.plugins import PluginConfig from django.conf import settings from .logger import get_logger -__version__ = "1.5.5" +__version__ = "1.5.6" LOGGER = get_logger(__name__) diff --git a/netbox_dns_bridge/catalog_zone_manager.py b/netbox_dns_bridge/catalog_zone_manager.py index 1a9d305..162fb1e 100644 --- a/netbox_dns_bridge/catalog_zone_manager.py +++ b/netbox_dns_bridge/catalog_zone_manager.py @@ -3,16 +3,11 @@ import dns.zone import dns.rdatatype import dns.rdataclass from .logger import get_logger -from netbox_dns.models import Zone +from netbox_dns.models import Zone as NBZone from netbox_dns_bridge.models import IntegerKeyValueSetting, CatalogZoneMemberIdentifier from uuid import uuid4 from base64 import b32encode -from django.db import ( - transaction, - close_old_connections, - OperationalError, - RelatedObjectDoesNotExist -) +from django.db import transaction, close_old_connections, OperationalError LOGGER = get_logger(__name__) @@ -58,7 +53,7 @@ def create_zone(name, view_name) -> dns.zone.Zone: try: # get zones from netbox - nb_zones = Zone.objects.filter( + nb_zones = NBZone.objects.filter( view__name=view_name, active=True ).select_related("catz_identifier") @@ -71,9 +66,9 @@ def create_zone(name, view_name) -> dns.zone.Zone: # Create PTR record try: catz_identifier = nb_zone.catz_identifier - except RelatedObjectDoesNotExist: - catz_identifier = nb_zone.catz_identifier.create( - name=_generate_member_identifier() + except NBZone.catz_identifier.RelatedObjectDoesNotExist: + catz_identifier = CatalogZoneMemberIdentifier.objects.create( + zone=nb_zone, name=_generate_member_identifier() ) p_name = catz_identifier.name @@ -129,7 +124,7 @@ def _generate_member_identifier() -> str: return b32encode(uuid4().bytes)[0:26].lower().decode("UTF-8") -def update_member_identifier(zone: Zone) -> None: +def update_member_identifier(zone: NBZone) -> None: try: CatalogZoneMemberIdentifier.objects.update_or_create( zone=zone, From db09fd70be7507d5490abb8d5a2e49df638a2d0b Mon Sep 17 00:00:00 2001 From: d_ev Date: Wed, 15 Jul 2026 22:38:08 +0300 Subject: [PATCH 4/4] Fix get_or_create tuple unpacking in catalog_zone_manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1.5.6 fixed the wrong RelatedObjectDoesNotExist import and the catz member-identifier creation, but two get_or_create() calls still used the returned value directly instead of unpacking the (obj, created) tuple: - increment_soa_serial(): `soa_serial_obj.value` on a tuple - _create_soa_rdataset(): `.get_or_create(...).value` on a tuple Both raised `'tuple' object has no attribute 'value'` at runtime — the first on every zone save, the second on every catalog-zone (catz) query. Unpack the tuple in both places. --- netbox_dns_bridge/catalog_zone_manager.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/netbox_dns_bridge/catalog_zone_manager.py b/netbox_dns_bridge/catalog_zone_manager.py index 162fb1e..d5d43cf 100644 --- a/netbox_dns_bridge/catalog_zone_manager.py +++ b/netbox_dns_bridge/catalog_zone_manager.py @@ -15,7 +15,7 @@ LOGGER = get_logger(__name__) def increment_soa_serial() -> int: with transaction.atomic(): try: - soa_serial_obj = ( + soa_serial_obj, _ = ( IntegerKeyValueSetting.objects.select_for_update().get_or_create( key="catalog-zone-soa-serial", defaults={"value": 1}, @@ -137,9 +137,10 @@ def update_member_identifier(zone: NBZone) -> None: def _create_soa_rdataset() -> dns.rdataset: try: - serial = IntegerKeyValueSetting.objects.get_or_create( + serial_obj, _ = IntegerKeyValueSetting.objects.get_or_create( key="catalog-zone-soa-serial", defaults={"value": 1} - ).value + ) + serial = serial_obj.value # SOA Record components ttl = 0