From f7137195433ea88ce010991404e8c3e58378b4cc Mon Sep 17 00:00:00 2001 From: Sven Luethi Date: Wed, 8 Apr 2026 16:18:43 +0200 Subject: [PATCH] modified: pyproject.toml Fix paths after restructuring renamed: netbox_dns_bridge/management/commands/export-dns-zone.py -> netbox_dns_bridge/management/commands/dns-export-zone.py renamed: netbox_dns_bridge/management/commands/export-all-dns-zones.py -> netbox_dns_bridge/management/commands/dns-export-zones.py Unify command naming scheme new file: netbox_dns_bridge/migrations/0001_initial.py Adds the missing migration. Since the plugin was renamed this is also an opportunity to merge all changes into a single migration. renamed: netbox_dns_bridge/service/transfer/catalog_zone_manager.py -> netbox_dns_bridge/catalog_zone_manager.py renamed: netbox_dns_bridge/service/transfer/dns_server.py -> netbox_dns_bridge/dns_server.py new file: netbox_dns_bridge/management/commands/dns-settings.py modified: netbox_dns_bridge/management/commands/dns-transfer-endpoint.py renamed: netbox_dns_bridge/service/transfer/request_handler.py -> netbox_dns_bridge/request_handler.py deleted: netbox_dns_bridge/service/transfer/__init__.py Another restructure to simplify code re-use. New command dns-settings added to allow setting of catalog zone serial. This will be needed to migrate from previous versions. --- .../endpoint => }/catalog_zone_manager.py | 16 ++++--- .../{service/endpoint => }/dns_server.py | 2 +- ...{export-dns-zone.py => dns-export-zone.py} | 0 ...t-all-dns-zones.py => dns-export-zones.py} | 0 .../management/commands/dns-settings.py | 47 +++++++++++++++++++ .../commands/dns-transfer-endpoint.py | 9 ++-- netbox_dns_bridge/migrations/0001_initial.py | 38 +++++++++++++++ .../{service/endpoint => }/request_handler.py | 6 +-- .../service/endpoint/__init__.py | 0 pyproject.toml | 4 +- 10 files changed, 106 insertions(+), 16 deletions(-) rename netbox_dns_bridge/{service/endpoint => }/catalog_zone_manager.py (96%) rename netbox_dns_bridge/{service/endpoint => }/dns_server.py (96%) rename netbox_dns_bridge/management/commands/{export-dns-zone.py => dns-export-zone.py} (100%) rename netbox_dns_bridge/management/commands/{export-all-dns-zones.py => dns-export-zones.py} (100%) create mode 100644 netbox_dns_bridge/management/commands/dns-settings.py create mode 100644 netbox_dns_bridge/migrations/0001_initial.py rename netbox_dns_bridge/{service/endpoint => }/request_handler.py (99%) delete mode 100644 netbox_dns_bridge/service/endpoint/__init__.py diff --git a/netbox_dns_bridge/service/endpoint/catalog_zone_manager.py b/netbox_dns_bridge/catalog_zone_manager.py similarity index 96% rename from netbox_dns_bridge/service/endpoint/catalog_zone_manager.py rename to netbox_dns_bridge/catalog_zone_manager.py index 58330f6..fca6b05 100644 --- a/netbox_dns_bridge/service/endpoint/catalog_zone_manager.py +++ b/netbox_dns_bridge/catalog_zone_manager.py @@ -16,7 +16,7 @@ from netbox_dns_bridge.models import IntegerKeyValueSetting, CatalogZoneMemberId from uuid import uuid4 from base64 import b32encode -logger = logging.getLogger("dns-transfer-endpoint") +logger = logging.getLogger(__name__) _LOCK = threading.Lock() _SERIAL_MAX = 0xFFFFFFFF @@ -47,18 +47,22 @@ def _init_serial() -> None: f"Catalog zone SOA serial number was not set in the database. Set to {_SERIAL_OBJ.value}" ) -def _increment_serial() -> None: +def _set_serial(new_serial: int) -> bool: global _SERIAL_OBJ - if 0 < _SERIAL_OBJ.value < _SERIAL_MAX: - _SERIAL_OBJ.value += 1 + if (0 < new_serial < _SERIAL_MAX): + _SERIAL_OBJ.value = new_serial _SERIAL_OBJ.save() + return True else: + return False + +def _increment_serial() -> None: + if not _set_serial( _SERIAL_OBJ.value + 1 ): logger.warning( f"Failed to incremenet catalog serial {_SERIAL_OBJ.value}. Will overflow serial back to 1" ) - _SERIAL_OBJ.value = 1 - _SERIAL_OBJ.save() + _set_serial(1) logger.debug( f"Catalog zone SOA serial number incremented to {_SERIAL_OBJ.value}" ) diff --git a/netbox_dns_bridge/service/endpoint/dns_server.py b/netbox_dns_bridge/dns_server.py similarity index 96% rename from netbox_dns_bridge/service/endpoint/dns_server.py rename to netbox_dns_bridge/dns_server.py index 12d640d..fdb7487 100644 --- a/netbox_dns_bridge/service/endpoint/dns_server.py +++ b/netbox_dns_bridge/dns_server.py @@ -2,7 +2,7 @@ import logging import socketserver import socket -logger = logging.getLogger("dns-transfer-endpoint") +logger = logging.getLogger(__name__) class DNSAddressMixin: def _resolve_address(self, server_address, socktype, proto): diff --git a/netbox_dns_bridge/management/commands/export-dns-zone.py b/netbox_dns_bridge/management/commands/dns-export-zone.py similarity index 100% rename from netbox_dns_bridge/management/commands/export-dns-zone.py rename to netbox_dns_bridge/management/commands/dns-export-zone.py diff --git a/netbox_dns_bridge/management/commands/export-all-dns-zones.py b/netbox_dns_bridge/management/commands/dns-export-zones.py similarity index 100% rename from netbox_dns_bridge/management/commands/export-all-dns-zones.py rename to netbox_dns_bridge/management/commands/dns-export-zones.py diff --git a/netbox_dns_bridge/management/commands/dns-settings.py b/netbox_dns_bridge/management/commands/dns-settings.py new file mode 100644 index 0000000..de1658e --- /dev/null +++ b/netbox_dns_bridge/management/commands/dns-settings.py @@ -0,0 +1,47 @@ +from django.core.management.base import BaseCommand, CommandError +from netbox_dns_bridge.models import IntegerKeyValueSetting + + +class Command(BaseCommand): + help = "Get or set integer key-value settings" + + def add_arguments(self, parser): + parser.add_argument("action", choices=["get", "set", "list"], help="Action to perform") + parser.add_argument("key", nargs="?", help="Setting key") + parser.add_argument("value", nargs="?", type=int, help="Value to set (required for 'set')") + + def handle(self, *args, **options): + action = options["action"] + key = options.get("key") + value = options.get("value") + + if action == "list": + settings = IntegerKeyValueSetting.objects.all() + if not settings.exists(): + self.stdout.write("No settings found.") + return + for setting in settings: + self.stdout.write(str(setting)) + + elif action == "get": + if not key: + raise CommandError("A key is required for GET") + try: + setting = IntegerKeyValueSetting.objects.get(key=key) + self.stdout.write(f"{setting.key}: {setting.value}") + except IntegerKeyValueSetting.DoesNotExist: + raise CommandError(f"No setting was found for {key}") + + elif action == "set": + if not key: + raise CommandError("A setting is required for SET command") + if value is None: + raise CommandError("A value is required for SET command") + try: + setting = IntegerKeyValueSetting.objects.get(key=key) + old_value = setting.value + setting.value = value + setting.save() + self.stdout.write(f"Updated {key} from {old_value} to {value}") + except IntegerKeyValueSetting.DoesNotExist: + raise CommandError(f"No setting found for {key}") diff --git a/netbox_dns_bridge/management/commands/dns-transfer-endpoint.py b/netbox_dns_bridge/management/commands/dns-transfer-endpoint.py index a50382f..e772ef2 100644 --- a/netbox_dns_bridge/management/commands/dns-transfer-endpoint.py +++ b/netbox_dns_bridge/management/commands/dns-transfer-endpoint.py @@ -14,11 +14,12 @@ import dns.renderer from django.core.management.base import BaseCommand from django.conf import settings from netbox_dns.models import View -from netbox_dns_bridge.service.endpoint.request_handler import UDPRequestHandler, TCPRequestHandler -from netbox_dns_bridge.service.endpoint.dns_server import UDPDNSServer, TCPDNSServer -from netbox_dns_bridge.service.endpoint import catalog_zone_manager as catzm +from netbox_dns_bridge.request_handler import UDPRequestHandler, TCPRequestHandler +from netbox_dns_bridge.dns_server import UDPDNSServer, TCPDNSServer +from netbox_dns_bridge import catalog_zone_manager as catzm +from netbox_dns_bridge.models import IntegerKeyValueSetting -logger = logging.getLogger("dns-transfer-endpoint") +logger = logging.getLogger(__name__) class Command(BaseCommand): help = "Run a minimal AXFR DNS server using data from NetBox DNS plugin" diff --git a/netbox_dns_bridge/migrations/0001_initial.py b/netbox_dns_bridge/migrations/0001_initial.py new file mode 100644 index 0000000..764ae6e --- /dev/null +++ b/netbox_dns_bridge/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# Generated by Django 5.2.9 on 2026-04-08 11:29 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('netbox_dns', '0030_dnsseckeytemplate_comments_dnsseckeytemplate_owner_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='IntegerKeyValueSetting', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('key', models.CharField(max_length=64)), + ('value', models.IntegerField()), + ], + options={ + 'default_permissions': (), + }, + ), + migrations.CreateModel( + name='CatalogZoneMemberIdentifier', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=26, unique=True)), + ('zone', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='catz_identifier', to='netbox_dns.zone')), + ], + options={ + 'ordering': ('name',), + }, + ), + ] diff --git a/netbox_dns_bridge/service/endpoint/request_handler.py b/netbox_dns_bridge/request_handler.py similarity index 99% rename from netbox_dns_bridge/service/endpoint/request_handler.py rename to netbox_dns_bridge/request_handler.py index 39b0a39..2edd35c 100644 --- a/netbox_dns_bridge/service/endpoint/request_handler.py +++ b/netbox_dns_bridge/request_handler.py @@ -13,9 +13,9 @@ import dns.exception import dns.renderer from netbox_dns.models import Zone, Record from netbox_dns.choices import ZoneStatusChoices, RecordStatusChoices -from . import catalog_zone_manager as catzm +from netbox_dns_bridge import catalog_zone_manager as catzm -logger = logging.getLogger("dns-transfer-endpoint") +logger = logging.getLogger(__name__) class DNSBaseRequestHandler(socketserver.BaseRequestHandler): @@ -131,7 +131,7 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler): keyname=query.keyname, tsig_error=tsig_error, ) - self.denyRequest(query) + self._denyRequest(query) def _send_response(self, data) -> None: raise NotImplementedError diff --git a/netbox_dns_bridge/service/endpoint/__init__.py b/netbox_dns_bridge/service/endpoint/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pyproject.toml b/pyproject.toml index 6764a5a..898dee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,10 +20,10 @@ dependencies = [ [tool.setuptools] include-package-data = true zip-safe = false -package-dir = { "" = "netbox_dns_bridge" } +package-dir = { "" = "." } [tool.setuptools.packages.find] -where = ["netbox_dns_bridge"] +where = ["."] [tool.setuptools.dynamic] version = { attr = "netbox_dns_bridge.__version__" }