Move from hard-coded CatalogZone SOA values (refresh, retry, expire and minimum)

to DB driven to permit user modification:

modified:   netbox_dns_bridge/models.py
  Add 4 cols for values.

modified:   netbox_dns_bridge/migrations/0003_catalogzone_and_per_zone_identifier.py
  Adjust migration. This expects that the last migration the user has is 0002 (<=v1.5.8)

modified:   netbox_dns_bridge/jobs/notify.py
modified:   netbox_dns_bridge/management/commands/dns_transfer_endpoint/catalog_zone_manager.py
  Update to use new db values for SOA creation.

Change UI to permit editing for SOA values and disable member identifier editing.
modified:   netbox_dns_bridge/forms.py
modified:   netbox_dns_bridge/navigation.py
new file:   netbox_dns_bridge/templates/netbox_dns_bridge/catalog_zone_edit.html
new file:   netbox_dns_bridge/templates/netbox_dns_bridge/catalog_zone_list.html
new file:   netbox_dns_bridge/templates/netbox_dns_bridge/catalog_zone_members.html
deleted:    netbox_dns_bridge/templates/netbox_dns_bridge/catz_overview.html
modified:   netbox_dns_bridge/tables.py
modified:   netbox_dns_bridge/urls.py
modified:   netbox_dns_bridge/views.py
modified:   netbox_dns_bridge/filtersets.py
  AI created/modified: Left the UI update to the LLM.

modified:   netbox_dns_bridge/tests/test_catalog_zone_manager.py
modified:   netbox_dns_bridge/tests/test_models.py
modified:   netbox_dns_bridge/tests/test_notify.py
modified:   netbox_dns_bridge/tests/test_views.py
  AI created/modified: Updating tests
This commit is contained in:
sven committed 2026-08-17 13:20:17 +02:00
1 parent 73d04b956d
commit 14805ed32b
18 files changed
+349 -77

No files matched your search

@@ -174,6 +174,23 @@ class TestCreateZone:
soa = zone.get_rdataset(origin, dns.rdatatype.SOA)
assert soa[0].serial == catz_serial
def test_soa_parameters_from_model(self, make_zone, make_view):
view = make_view(name="cz-soa-params-view")
make_zone(name="soa-params.test", view=view)
CatalogZone.objects.filter(view=view).update(
soa_refresh=300,
soa_retry=100,
soa_expire=86400,
soa_minimum=3600,
)
zone = catzm.create_zone("catz", "cz-soa-params-view")
origin = dns.name.from_text("catz", dns.name.root)
soa = zone.get_rdataset(origin, dns.rdatatype.SOA)
assert soa[0].refresh == 300
assert soa[0].retry == 100
assert soa[0].expire == 86400
assert soa[0].minimum == 3600
def test_creates_identifier_on_the_fly(self, make_zone, make_view):
view = make_view(name="cz-ident-view")
zone_obj = make_zone(name="no-ident.test", view=view)
+22
View File
@@ -20,6 +20,28 @@ class TestCatalogZone:
cz = CatalogZone.objects.create(view=view)
assert cz.soa_serial == 1
def test_default_soa_parameters(self, make_view):
view = make_view(name="cz-soa-default-view")
cz = CatalogZone.objects.create(view=view)
assert cz.soa_refresh == 60
assert cz.soa_retry == 10
assert cz.soa_expire == 1209600
assert cz.soa_minimum == 0
def test_custom_soa_parameters(self, make_view):
view = make_view(name="cz-soa-custom-view")
cz = CatalogZone.objects.create(
view=view,
soa_refresh=300,
soa_retry=100,
soa_expire=86400,
soa_minimum=3600,
)
assert cz.soa_refresh == 300
assert cz.soa_retry == 100
assert cz.soa_expire == 86400
assert cz.soa_minimum == 3600
def test_one_to_one_relationship(self, make_view):
view = make_view(name="cz-oto-view")
cz = CatalogZone.objects.create(view=view, soa_serial=7)
+11 -1
View File
@@ -229,12 +229,22 @@ class TestScheduleCatalogZoneNotify:
nh.schedule_catalog_zone_notify(view)
assert mock_enq.call_count == 2
mock_enq.assert_any_call(
zone_name="catz", soa_serial=42, view_name="catz-notify-view"
zone_name="catz",
soa_serial=42,
view_name="catz-notify-view",
soa_refresh=60,
soa_retry=10,
soa_expire=1209600,
soa_minimum=0,
)
mock_enq.assert_any_call(
zone_name="catz-notify-view.catz",
soa_serial=42,
view_name="catz-notify-view",
soa_refresh=60,
soa_retry=10,
soa_expire=1209600,
soa_minimum=0,
)
def test_does_not_enqueue_when_notify_clients_disabled(self, make_view, monkeypatch):
+90 -13
View File
@@ -1,4 +1,4 @@
"""Tests for views: CatzOverviewView, NotifyOverviewView — auth gate and context."""
"""Tests for views: CatalogZoneMembersView, CatalogZoneListView, CatalogZoneEditView, NotifyOverviewView — auth gate and context."""
import pytest
from django.test import Client
from django.contrib.auth import get_user_model
@@ -28,36 +28,113 @@ def regular_user(db):
@pytest.mark.django_db
class TestCatzOverviewView:
class TestCatalogZoneMembersView:
def test_unauthenticated_redirects_to_login(self, client):
resp = client.get("/plugins/dns-bridge/catz/")
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
assert resp.status_code in (302, 403)
def test_regular_user_forbidden(self, client, regular_user):
client.login(username="regular", password="testpass")
resp = client.get("/plugins/dns-bridge/catz/")
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
assert resp.status_code in (302, 403)
def test_superuser_can_access(self, client, superuser):
client.login(username="admin", password="testpass")
resp = client.get("/plugins/dns-bridge/catz/")
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
assert resp.status_code == 200
def test_context_contains_catalog_zones(self, client, superuser, catz_serial, make_zone):
@pytest.mark.django_db
class TestCatalogZoneListView:
def test_unauthenticated_redirects_to_login(self, client):
resp = client.get("/plugins/dns-bridge/catalog-zones/")
assert resp.status_code in (302, 403)
def test_regular_user_forbidden(self, client, regular_user):
client.login(username="regular", password="testpass")
resp = client.get("/plugins/dns-bridge/catalog-zones/")
assert resp.status_code in (302, 403)
def test_superuser_can_access(self, client, superuser):
client.login(username="admin", password="testpass")
resp = client.get("/plugins/dns-bridge/catalog-zones/")
assert resp.status_code == 200
def test_list_contains_catalog_zones(self, client, superuser, catz_serial, make_zone):
zone = make_zone(name="ctx.test")
client.login(username="admin", password="testpass")
resp = client.get("/plugins/dns-bridge/catz/")
assert "catalog_zones" in resp.context
cz_list = list(resp.context["catalog_zones"])
resp = client.get("/plugins/dns-bridge/catalog-zones/")
cz_list = list(resp.context["table"].data)
assert len(cz_list) >= 1
cz = next(c for c in cz_list if c.view_id == zone.view_id)
assert cz.soa_serial == catz_serial
def test_context_no_catalog_zones_when_empty(self, client, superuser):
def test_list_empty_when_no_catalog_zones(self, client, superuser):
client.login(username="admin", password="testpass")
resp = client.get("/plugins/dns-bridge/catz/")
assert "catalog_zones" in resp.context
assert list(resp.context["catalog_zones"]) == []
resp = client.get("/plugins/dns-bridge/catalog-zones/")
cz_list = list(resp.context["table"].data)
assert cz_list == []
@pytest.mark.django_db
class TestCatalogZoneEditView:
def test_unauthenticated_redirects_to_login(self, client, make_view):
view = make_view(name="edit-cz-view")
from netbox_dns_bridge.models import CatalogZone
cz = CatalogZone.objects.create(view=view)
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/edit/")
assert resp.status_code in (302, 403)
def test_regular_user_forbidden(self, client, regular_user, make_view):
view = make_view(name="edit-cz-view-forbidden")
from netbox_dns_bridge.models import CatalogZone
cz = CatalogZone.objects.create(view=view)
client.login(username="regular", password="testpass")
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/edit/")
assert resp.status_code in (302, 403)
def test_superuser_can_get_edit_form(self, client, superuser, make_view):
view = make_view(name="edit-cz-view-get")
from netbox_dns_bridge.models import CatalogZone
cz = CatalogZone.objects.create(view=view)
client.login(username="admin", password="testpass")
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/edit/")
assert resp.status_code == 200
def test_superuser_can_update_soa_fields(self, client, superuser, make_view):
view = make_view(name="edit-cz-view-post")
from netbox_dns_bridge.models import CatalogZone
cz = CatalogZone.objects.create(view=view)
client.login(username="admin", password="testpass")
resp = client.post(
f"/plugins/dns-bridge/catalog-zones/{cz.pk}/edit/",
{
"soa_serial": 100,
"soa_refresh": 300,
"soa_retry": 100,
"soa_expire": 86400,
"soa_minimum": 3600,
},
)
cz.refresh_from_db()
assert cz.soa_serial == 100
assert cz.soa_refresh == 300
assert cz.soa_retry == 100
assert cz.soa_expire == 86400
assert cz.soa_minimum == 3600
def test_no_create_route(self, client, superuser):
client.login(username="admin", password="testpass")
resp = client.get("/plugins/dns-bridge/catalog-zones/add/")
assert resp.status_code == 404
def test_no_delete_route(self, client, superuser, make_view):
view = make_view(name="edit-cz-view-delete")
from netbox_dns_bridge.models import CatalogZone
cz = CatalogZone.objects.create(view=view)
client.login(username="admin", password="testpass")
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/delete/")
assert resp.status_code == 404
@pytest.mark.django_db