netbox-plugin-dns 1.1.0b6__py3-none-any.whl → 1.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of netbox-plugin-dns might be problematic. Click here for more details.

Files changed (79) hide show
  1. netbox_dns/__init__.py +1 -1
  2. netbox_dns/api/nested_serializers.py +17 -16
  3. netbox_dns/api/serializers.py +1 -1
  4. netbox_dns/api/serializers_/record.py +1 -0
  5. netbox_dns/api/serializers_/{contact.py → registration_contact.py} +5 -5
  6. netbox_dns/api/serializers_/zone.py +5 -5
  7. netbox_dns/api/serializers_/zone_template.py +5 -5
  8. netbox_dns/api/urls.py +2 -2
  9. netbox_dns/api/views.py +7 -35
  10. netbox_dns/filtersets/__init__.py +1 -1
  11. netbox_dns/filtersets/nameserver.py +0 -0
  12. netbox_dns/filtersets/record.py +0 -0
  13. netbox_dns/filtersets/record_template.py +0 -0
  14. netbox_dns/filtersets/{contact.py → registration_contact.py} +4 -4
  15. netbox_dns/filtersets/zone.py +15 -15
  16. netbox_dns/filtersets/zone_template.py +15 -15
  17. netbox_dns/forms/__init__.py +1 -1
  18. netbox_dns/forms/nameserver.py +0 -0
  19. netbox_dns/forms/record.py +0 -0
  20. netbox_dns/forms/record_template.py +0 -0
  21. netbox_dns/forms/{contact.py → registration_contact.py} +16 -16
  22. netbox_dns/forms/zone.py +13 -13
  23. netbox_dns/forms/zone_template.py +13 -13
  24. netbox_dns/graphql/__init__.py +2 -2
  25. netbox_dns/graphql/filters.py +5 -5
  26. netbox_dns/graphql/schema.py +24 -44
  27. netbox_dns/graphql/types.py +38 -12
  28. netbox_dns/management/commands/rebuild_dnssync.py +18 -0
  29. netbox_dns/migrations/0007_alter_ordering_options.py +25 -0
  30. netbox_dns/migrations/{0007_view_prefixes.py → 0008_view_prefixes.py} +1 -1
  31. netbox_dns/migrations/0009_rename_contact_registrationcontact.py +36 -0
  32. netbox_dns/models/__init__.py +1 -1
  33. netbox_dns/models/nameserver.py +8 -3
  34. netbox_dns/models/record.py +42 -20
  35. netbox_dns/models/record_template.py +4 -1
  36. netbox_dns/models/registrar.py +7 -1
  37. netbox_dns/models/{contact.py → registration_contact.py} +15 -9
  38. netbox_dns/models/view.py +9 -2
  39. netbox_dns/models/zone.py +48 -30
  40. netbox_dns/models/zone_template.py +12 -9
  41. netbox_dns/navigation.py +7 -7
  42. netbox_dns/signals/ipam_dnssync.py +6 -2
  43. netbox_dns/tables/__init__.py +1 -1
  44. netbox_dns/tables/nameserver.py +1 -7
  45. netbox_dns/tables/record.py +10 -37
  46. netbox_dns/tables/record_template.py +0 -17
  47. netbox_dns/tables/registrar.py +0 -2
  48. netbox_dns/tables/{contact.py → registration_contact.py} +5 -6
  49. netbox_dns/tables/view.py +1 -8
  50. netbox_dns/tables/zone.py +0 -15
  51. netbox_dns/tables/zone_template.py +2 -16
  52. netbox_dns/templates/netbox_dns/{contact.html → registrationcontact.html} +1 -1
  53. netbox_dns/urls/__init__.py +2 -2
  54. netbox_dns/urls/nameserver.py +14 -38
  55. netbox_dns/urls/record.py +7 -19
  56. netbox_dns/urls/record_template.py +18 -27
  57. netbox_dns/urls/registrar.py +11 -35
  58. netbox_dns/urls/registration_contact.py +60 -0
  59. netbox_dns/urls/view.py +8 -22
  60. netbox_dns/urls/zone.py +8 -46
  61. netbox_dns/urls/zone_template.py +16 -26
  62. netbox_dns/utilities/ipam_dnssync.py +26 -24
  63. netbox_dns/validators/dns_name.py +9 -0
  64. netbox_dns/views/__init__.py +1 -1
  65. netbox_dns/views/nameserver.py +7 -3
  66. netbox_dns/views/record.py +12 -7
  67. netbox_dns/views/record_template.py +1 -1
  68. netbox_dns/views/registrar.py +0 -1
  69. netbox_dns/views/registration_contact.py +94 -0
  70. netbox_dns/views/view.py +6 -1
  71. netbox_dns/views/zone.py +7 -6
  72. netbox_dns/views/zone_template.py +2 -2
  73. {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/METADATA +14 -14
  74. {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/RECORD +78 -74
  75. {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/WHEEL +2 -1
  76. netbox_plugin_dns-1.1.1.dist-info/top_level.txt +1 -0
  77. netbox_dns/urls/contact.py +0 -51
  78. netbox_dns/views/contact.py +0 -95
  79. {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/LICENSE +0 -0
@@ -10,6 +10,7 @@ from django.urls import reverse
10
10
  from django.conf import settings
11
11
 
12
12
  from netbox.models import NetBoxModel
13
+ from netbox.models.features import ContactsMixin
13
14
  from netbox.search import SearchIndex, register_search
14
15
  from netbox.plugins.utils import get_plugin_config
15
16
  from utilities.querysets import RestrictedQuerySet
@@ -100,7 +101,7 @@ class RecordManager(models.Manager.from_queryset(RestrictedQuerySet)):
100
101
  )
101
102
 
102
103
 
103
- class Record(ObjectModificationMixin, NetBoxModel):
104
+ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
104
105
  ACTIVE_STATUS_LIST = (RecordStatusChoices.STATUS_ACTIVE,)
105
106
 
106
107
  unique_ptr_qs = Q(
@@ -193,7 +194,7 @@ class Record(ObjectModificationMixin, NetBoxModel):
193
194
  objects = RecordManager()
194
195
  raw_objects = RestrictedQuerySet.as_manager()
195
196
 
196
- clone_fields = [
197
+ clone_fields = (
197
198
  "zone",
198
199
  "type",
199
200
  "name",
@@ -202,10 +203,20 @@ class Record(ObjectModificationMixin, NetBoxModel):
202
203
  "ttl",
203
204
  "disable_ptr",
204
205
  "description",
205
- ]
206
+ )
206
207
 
207
208
  class Meta:
208
- ordering = ("zone", "name", "type", "value", "status")
209
+ verbose_name = "Record"
210
+ verbose_name_plural = "Records"
211
+
212
+ ordering = (
213
+ "fqdn",
214
+ "zone",
215
+ "name",
216
+ "type",
217
+ "value",
218
+ "status",
219
+ )
209
220
 
210
221
  def __str__(self):
211
222
  try:
@@ -493,20 +504,33 @@ class Record(ObjectModificationMixin, NetBoxModel):
493
504
  **data,
494
505
  )
495
506
 
507
+ def update_fqdn(self, zone=None):
508
+ if zone is None:
509
+ zone = self.zone
510
+
511
+ _zone = dns_name.from_text(zone.name, origin=dns_name.root)
512
+ name = dns_name.from_text(self.name, origin=None)
513
+ fqdn = dns_name.from_text(self.name, origin=_zone)
514
+
515
+ if not fqdn.is_subdomain(_zone):
516
+ raise ValidationError(
517
+ {
518
+ "name": f"{self.name} is not a name in {zone.name}",
519
+ }
520
+ )
521
+
522
+ _zone.to_unicode()
523
+ name.to_unicode()
524
+
525
+ self.name = name.relativize(_zone).to_text()
526
+ self.fqdn = fqdn.to_text()
527
+
496
528
  def validate_name(self, new_zone=None):
497
529
  if new_zone is None:
498
530
  new_zone = self.zone
499
531
 
500
532
  try:
501
- _zone = dns_name.from_text(new_zone.name, origin=dns_name.root)
502
- name = dns_name.from_text(self.name, origin=None)
503
- fqdn = dns_name.from_text(self.name, origin=_zone)
504
-
505
- _zone.to_unicode()
506
- name.to_unicode()
507
-
508
- self.name = name.relativize(_zone).to_text()
509
- self.fqdn = fqdn.to_text()
533
+ self.update_fqdn(zone=new_zone)
510
534
 
511
535
  except dns.exception.DNSException as exc:
512
536
  raise ValidationError(
@@ -515,13 +539,6 @@ class Record(ObjectModificationMixin, NetBoxModel):
515
539
  }
516
540
  )
517
541
 
518
- if not fqdn.is_subdomain(_zone):
519
- raise ValidationError(
520
- {
521
- "name": f"{self.name} is not a name in {new_zone.name}",
522
- }
523
- )
524
-
525
542
  if self.type not in get_plugin_config(
526
543
  "netbox_dns", "tolerate_non_rfc1035_types", default=[]
527
544
  ):
@@ -613,6 +630,11 @@ class Record(ObjectModificationMixin, NetBoxModel):
613
630
  if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
614
631
  return
615
632
 
633
+ if self.ipam_ip_address is not None and get_plugin_config(
634
+ "netbox_dns", "dnssync_conflict_deactivate", False
635
+ ):
636
+ return
637
+
616
638
  if self.type == RecordTypeChoices.PTR and self.managed:
617
639
  return
618
640
 
@@ -85,7 +85,10 @@ class RecordTemplate(NetBoxModel):
85
85
  )
86
86
 
87
87
  class Meta:
88
- ordering = ["name"]
88
+ verbose_name = "Record Template"
89
+ verbose_name_plural = "Record Templates"
90
+
91
+ ordering = ("name",)
89
92
 
90
93
  def __str__(self):
91
94
  return str(self.name)
@@ -59,7 +59,13 @@ class Registrar(NetBoxModel):
59
59
  return str(self.name)
60
60
 
61
61
  class Meta:
62
- ordering = ("name", "iana_id")
62
+ verbose_name = "Registrar"
63
+ verbose_name_plural = "Registrars"
64
+
65
+ ordering = (
66
+ "name",
67
+ "iana_id",
68
+ )
63
69
 
64
70
 
65
71
  @register_search
@@ -8,12 +8,12 @@ from taggit.managers import TaggableManager
8
8
 
9
9
 
10
10
  __all__ = (
11
- "Contact",
12
- "ContactIndex",
11
+ "RegistrationContact",
12
+ "RegistrationContactIndex",
13
13
  )
14
14
 
15
15
 
16
- class Contact(NetBoxModel):
16
+ class RegistrationContact(NetBoxModel):
17
17
  # +
18
18
  # Data fields according to https://www.icann.org/resources/pages/rdds-labeling-policy-2017-02-01-en
19
19
  # -
@@ -87,7 +87,7 @@ class Contact(NetBoxModel):
87
87
  related_name="netbox_dns_contact_set",
88
88
  )
89
89
 
90
- clone_fields = [
90
+ clone_fields = (
91
91
  "name",
92
92
  "description",
93
93
  "organization",
@@ -102,10 +102,10 @@ class Contact(NetBoxModel):
102
102
  "fax_ext",
103
103
  "email",
104
104
  "tags",
105
- ]
105
+ )
106
106
 
107
107
  def get_absolute_url(self):
108
- return reverse("plugins:netbox_dns:contact", kwargs={"pk": self.pk})
108
+ return reverse("plugins:netbox_dns:registrationcontact", kwargs={"pk": self.pk})
109
109
 
110
110
  def __str__(self):
111
111
  if self.name is not None:
@@ -114,7 +114,13 @@ class Contact(NetBoxModel):
114
114
  return self.contact_id
115
115
 
116
116
  class Meta:
117
- ordering = ("name", "contact_id")
117
+ verbose_name = "Registration Contact"
118
+ verbose_name_plural = "Registration Contacts"
119
+
120
+ ordering = (
121
+ "name",
122
+ "contact_id",
123
+ )
118
124
 
119
125
  @property
120
126
  def zones(self):
@@ -127,8 +133,8 @@ class Contact(NetBoxModel):
127
133
 
128
134
 
129
135
  @register_search
130
- class ContactIndex(SearchIndex):
131
- model = Contact
136
+ class RegistrationContactIndex(SearchIndex):
137
+ model = RegistrationContact
132
138
  fields = (
133
139
  ("name", 100),
134
140
  ("contact_id", 100),
netbox_dns/models/view.py CHANGED
@@ -3,6 +3,7 @@ from django.urls import reverse
3
3
  from django.core.exceptions import ValidationError
4
4
 
5
5
  from netbox.models import NetBoxModel
6
+ from netbox.models.features import ContactsMixin
6
7
  from netbox.search import SearchIndex, register_search
7
8
  from netbox.context import current_request
8
9
  from utilities.exceptions import AbortRequest
@@ -16,7 +17,7 @@ __all__ = (
16
17
  )
17
18
 
18
19
 
19
- class View(ObjectModificationMixin, NetBoxModel):
20
+ class View(ObjectModificationMixin, ContactsMixin, NetBoxModel):
20
21
  name = models.CharField(
21
22
  unique=True,
22
23
  max_length=255,
@@ -41,7 +42,10 @@ class View(ObjectModificationMixin, NetBoxModel):
41
42
  null=True,
42
43
  )
43
44
 
44
- clone_fields = ["name", "description"]
45
+ clone_fields = (
46
+ "name",
47
+ "description",
48
+ )
45
49
 
46
50
  @classmethod
47
51
  def get_default_view(cls):
@@ -54,6 +58,9 @@ class View(ObjectModificationMixin, NetBoxModel):
54
58
  return str(self.name)
55
59
 
56
60
  class Meta:
61
+ verbose_name = "View"
62
+ verbose_name_plural = "Views"
63
+
57
64
  ordering = ("name",)
58
65
 
59
66
  def delete(self, *args, **kwargs):
netbox_dns/models/zone.py CHANGED
@@ -3,9 +3,8 @@ from math import ceil
3
3
  from datetime import datetime
4
4
 
5
5
  from dns import name as dns_name
6
- from dns.rdtypes.ANY import SOA
7
6
  from dns.exception import DNSException
8
-
7
+ from dns.rdtypes.ANY import SOA
9
8
  from django.core.validators import (
10
9
  MinValueValidator,
11
10
  MaxValueValidator,
@@ -19,6 +18,7 @@ from django.dispatch import receiver
19
18
  from django.conf import settings
20
19
 
21
20
  from netbox.models import NetBoxModel
21
+ from netbox.models.features import ContactsMixin
22
22
  from netbox.search import SearchIndex, register_search
23
23
  from netbox.plugins.utils import get_plugin_config
24
24
  from utilities.querysets import RestrictedQuerySet
@@ -36,7 +36,7 @@ from netbox_dns.utilities import (
36
36
  NameFormatError,
37
37
  )
38
38
  from netbox_dns.validators import (
39
- validate_fqdn,
39
+ validate_rname,
40
40
  validate_domain_name,
41
41
  )
42
42
  from netbox_dns.mixins import ObjectModificationMixin
@@ -69,7 +69,7 @@ class ZoneManager(models.Manager.from_queryset(RestrictedQuerySet)):
69
69
  )
70
70
 
71
71
 
72
- class Zone(ObjectModificationMixin, NetBoxModel):
72
+ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
73
73
  ACTIVE_STATUS_LIST = (ZoneStatusChoices.STATUS_ACTIVE,)
74
74
 
75
75
  def __init__(self, *args, **kwargs):
@@ -78,6 +78,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
78
78
  super().__init__(*args, **kwargs)
79
79
 
80
80
  self._soa_serial_dirty = False
81
+ self._ip_addresses_checked = False
81
82
 
82
83
  view = models.ForeignKey(
83
84
  to="View",
@@ -191,7 +192,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
191
192
  null=True,
192
193
  )
193
194
  registrant = models.ForeignKey(
194
- to="Contact",
195
+ to="RegistrationContact",
195
196
  on_delete=models.SET_NULL,
196
197
  verbose_name="Registrant",
197
198
  help_text="The owner of the domain",
@@ -199,7 +200,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
199
200
  null=True,
200
201
  )
201
202
  admin_c = models.ForeignKey(
202
- to="Contact",
203
+ to="RegistrationContact",
203
204
  on_delete=models.SET_NULL,
204
205
  verbose_name="Admin Contact",
205
206
  related_name="admin_c_zones",
@@ -208,16 +209,16 @@ class Zone(ObjectModificationMixin, NetBoxModel):
208
209
  null=True,
209
210
  )
210
211
  tech_c = models.ForeignKey(
211
- to="Contact",
212
+ to="RegistrationContact",
212
213
  on_delete=models.SET_NULL,
213
- verbose_name="Tech Contact",
214
+ verbose_name="Technical Contact",
214
215
  related_name="tech_c_zones",
215
216
  help_text="The technical contact for the domain",
216
217
  blank=True,
217
218
  null=True,
218
219
  )
219
220
  billing_c = models.ForeignKey(
220
- to="Contact",
221
+ to="RegistrationContact",
221
222
  on_delete=models.SET_NULL,
222
223
  verbose_name="Billing Contact",
223
224
  related_name="billing_c_zones",
@@ -248,7 +249,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
248
249
 
249
250
  objects = ZoneManager()
250
251
 
251
- clone_fields = [
252
+ clone_fields = (
252
253
  "view",
253
254
  "name",
254
255
  "status",
@@ -262,9 +263,12 @@ class Zone(ObjectModificationMixin, NetBoxModel):
262
263
  "soa_expire",
263
264
  "soa_minimum",
264
265
  "description",
265
- ]
266
+ )
266
267
 
267
268
  class Meta:
269
+ verbose_name = "Zone"
270
+ verbose_name_plural = "Zones"
271
+
268
272
  ordering = (
269
273
  "view",
270
274
  "name",
@@ -280,7 +284,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
280
284
  else:
281
285
  try:
282
286
  name = dns_name.from_text(self.name, origin=None).to_unicode()
283
- except dns_name.IDNAException:
287
+ except DNSException:
284
288
  name = self.name
285
289
 
286
290
  try:
@@ -308,6 +312,14 @@ class Zone(ObjectModificationMixin, NetBoxModel):
308
312
  def soa_serial_dirty(self, soa_serial_dirty):
309
313
  self._soa_serial_dirty = soa_serial_dirty
310
314
 
315
+ @property
316
+ def ip_addresses_checked(self):
317
+ return self._ip_addresses_checked
318
+
319
+ @ip_addresses_checked.setter
320
+ def ip_addresses_checked(self, ip_addresses_checked):
321
+ self._ip_addresses_checked = ip_addresses_checked
322
+
311
323
  @property
312
324
  def display_name(self):
313
325
  return name_to_unicode(self.name)
@@ -621,7 +633,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
621
633
  raise ValidationError("soa_rname not set and no default value defined")
622
634
  try:
623
635
  dns_name.from_text(self.soa_rname, origin=dns_name.root)
624
- validate_fqdn(self.soa_rname)
636
+ validate_rname(self.soa_rname)
625
637
  except (DNSException, ValidationError) as exc:
626
638
  raise ValidationError(
627
639
  {
@@ -641,7 +653,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
641
653
  old_zone = Zone.objects.get(pk=self.pk)
642
654
  if not self.soa_serial_auto:
643
655
  self.check_soa_serial_increment(old_zone.soa_serial, self.soa_serial)
644
- else:
656
+ elif not old_zone.soa_serial_auto:
645
657
  try:
646
658
  self.check_soa_serial_increment(
647
659
  old_zone.soa_serial, self.get_auto_serial()
@@ -653,24 +665,26 @@ class Zone(ObjectModificationMixin, NetBoxModel):
653
665
  }
654
666
  )
655
667
 
656
- if old_zone.name != self.name or old_zone.view != self.view:
657
- for ip_address in get_ip_addresses_by_zone(self):
658
- try:
659
- check_dns_records(ip_address, zone=self)
660
- except ValidationError as exc:
661
- raise ValidationError(exc.messages)
662
-
668
+ if (
669
+ not self.ip_addresses_checked
670
+ and old_zone.name != self.name
671
+ or old_zone.view != self.view
672
+ ):
663
673
  ip_addresses = IPAddress.objects.filter(
664
674
  netbox_dns_records__in=self.record_set.filter(
665
675
  ipam_ip_address__isnull=False
666
676
  )
667
677
  )
668
- for ip_address in ip_addresses:
678
+ ip_addresses |= get_ip_addresses_by_zone(self)
679
+
680
+ for ip_address in ip_addresses.distinct():
669
681
  try:
670
682
  check_dns_records(ip_address, zone=self)
671
683
  except ValidationError as exc:
672
684
  raise ValidationError(exc.messages)
673
685
 
686
+ self.ip_addresses_checked = True
687
+
674
688
  if self.is_reverse_zone:
675
689
  self.arpa_network = self.network_from_name
676
690
 
@@ -785,12 +799,13 @@ class Zone(ObjectModificationMixin, NetBoxModel):
785
799
 
786
800
  elif changed_fields is not None and {"name", "view", "status"} & changed_fields:
787
801
  for address_record in self.record_set.filter(
788
- type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
802
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
803
+ ipam_ip_address__isnull=True,
789
804
  ):
790
805
  address_record.save(update_fields=["ptr_record"])
791
806
 
792
807
  if changed_fields is not None and "name" in changed_fields:
793
- for _record in self.record_set.all():
808
+ for _record in self.record_set.filter(ipam_ip_address__isnull=True):
794
809
  _record.save(
795
810
  update_fields=["fqdn"],
796
811
  save_zone_serial=False,
@@ -799,13 +814,14 @@ class Zone(ObjectModificationMixin, NetBoxModel):
799
814
  )
800
815
 
801
816
  if changed_fields is None or {"name", "view"} & changed_fields:
802
- update_ip_addresses = IPAddress.objects.filter(
803
- pk__in=self.record_set.filter(
817
+ ip_addresses = IPAddress.objects.filter(
818
+ netbox_dns_records__in=self.record_set.filter(
804
819
  ipam_ip_address__isnull=False
805
- ).values_list("ipam_ip_address", flat=True)
820
+ )
806
821
  )
807
- update_ip_addresses |= get_ip_addresses_by_zone(self)
808
- for ip_address in update_ip_addresses:
822
+ ip_addresses |= get_ip_addresses_by_zone(self)
823
+
824
+ for ip_address in ip_addresses.distinct():
809
825
  update_dns_records(ip_address)
810
826
 
811
827
  self.save_soa_serial()
@@ -848,7 +864,9 @@ class Zone(ObjectModificationMixin, NetBoxModel):
848
864
  netbox_dns_records__in=self.record_set.filter(
849
865
  ipam_ip_address__isnull=False
850
866
  )
851
- ).values_list("pk", flat=True)
867
+ )
868
+ .distinct()
869
+ .values_list("pk", flat=True)
852
870
  )
853
871
 
854
872
  super().delete(*args, **kwargs)
@@ -47,7 +47,7 @@ class ZoneTemplate(NetBoxModel):
47
47
  null=True,
48
48
  )
49
49
  registrant = models.ForeignKey(
50
- to="Contact",
50
+ to="RegistrationContact",
51
51
  on_delete=models.SET_NULL,
52
52
  related_name="+",
53
53
  help_text="The owner of the domain",
@@ -55,7 +55,7 @@ class ZoneTemplate(NetBoxModel):
55
55
  null=True,
56
56
  )
57
57
  admin_c = models.ForeignKey(
58
- to="Contact",
58
+ to="RegistrationContact",
59
59
  on_delete=models.SET_NULL,
60
60
  verbose_name="Admin contact",
61
61
  related_name="+",
@@ -64,7 +64,7 @@ class ZoneTemplate(NetBoxModel):
64
64
  null=True,
65
65
  )
66
66
  tech_c = models.ForeignKey(
67
- to="Contact",
67
+ to="RegistrationContact",
68
68
  on_delete=models.SET_NULL,
69
69
  verbose_name="Tech contact",
70
70
  related_name="+",
@@ -73,7 +73,7 @@ class ZoneTemplate(NetBoxModel):
73
73
  null=True,
74
74
  )
75
75
  billing_c = models.ForeignKey(
76
- to="Contact",
76
+ to="RegistrationContact",
77
77
  on_delete=models.SET_NULL,
78
78
  verbose_name="Billing contact",
79
79
  related_name="+",
@@ -82,7 +82,7 @@ class ZoneTemplate(NetBoxModel):
82
82
  null=True,
83
83
  )
84
84
 
85
- clone_fields = [
85
+ clone_fields = (
86
86
  "description",
87
87
  "nameservers",
88
88
  "record_templates",
@@ -92,19 +92,22 @@ class ZoneTemplate(NetBoxModel):
92
92
  "admin_c",
93
93
  "tech_c",
94
94
  "billing_c",
95
- ]
95
+ )
96
96
 
97
- template_fields = [
97
+ template_fields = (
98
98
  "tenant",
99
99
  "registrar",
100
100
  "registrant",
101
101
  "admin_c",
102
102
  "tech_c",
103
103
  "billing_c",
104
- ]
104
+ )
105
105
 
106
106
  class Meta:
107
- ordering = ["name"]
107
+ verbose_name = "Zone Template"
108
+ verbose_name_plural = "Zone Templates"
109
+
110
+ ordering = ("name",)
108
111
 
109
112
  def __str__(self):
110
113
  return str(self.name)
netbox_dns/navigation.py CHANGED
@@ -151,21 +151,21 @@ registrar_menu_item = PluginMenuItem(
151
151
  )
152
152
 
153
153
  contact_menu_item = PluginMenuItem(
154
- link="plugins:netbox_dns:contact_list",
155
- link_text="Contacts",
156
- permissions=["netbox_dns.view_contact"],
154
+ link="plugins:netbox_dns:registrationcontact_list",
155
+ link_text="Registration Contacts",
156
+ permissions=["netbox_dns.view_registrationcontact"],
157
157
  buttons=(
158
158
  PluginMenuButton(
159
- "plugins:netbox_dns:contact_add",
159
+ "plugins:netbox_dns:registrationcontact_add",
160
160
  "Add",
161
161
  "mdi mdi-plus-thick",
162
- permissions=["netbox_dns.add_contact"],
162
+ permissions=["netbox_dns.add_registrationcontact"],
163
163
  ),
164
164
  PluginMenuButton(
165
- "plugins:netbox_dns:contact_import",
165
+ "plugins:netbox_dns:registrationcontact_import",
166
166
  "Import",
167
167
  "mdi mdi-upload",
168
- permissions=["netbox_dns.add_contact"],
168
+ permissions=["netbox_dns.add_registrationcontact"],
169
169
  ),
170
170
  ),
171
171
  )
@@ -215,6 +215,10 @@ def ipam_dnssync_view_prefix_changed(**kwargs):
215
215
  return
216
216
 
217
217
  check_view = action != "post_remove"
218
+
219
+ ip_addresses = IPAddress.objects.none()
218
220
  for prefix in Prefix.objects.filter(pk__in=kwargs.get("pk_set")):
219
- for ip_address in get_ip_addresses_by_prefix(prefix, check_view=check_view):
220
- update_dns_records(ip_address)
221
+ ip_addresses |= get_ip_addresses_by_prefix(prefix, check_view=check_view)
222
+
223
+ for ip_address in ip_addresses.distinct():
224
+ update_dns_records(ip_address)
@@ -2,7 +2,7 @@ from .view import *
2
2
  from .zone import *
3
3
  from .nameserver import *
4
4
  from .record import *
5
- from .contact import *
5
+ from .registration_contact import *
6
6
  from .registrar import *
7
7
  from .zone_template import *
8
8
  from .record_template import *
@@ -22,13 +22,7 @@ class NameServerTable(TenancyColumnsMixin, NetBoxTable):
22
22
 
23
23
  class Meta(NetBoxTable.Meta):
24
24
  model = NameServer
25
- fields = (
26
- "name",
27
- "description",
28
- "tags",
29
- "tenant",
30
- "tenant_group",
31
- )
25
+ fields = ("description",)
32
26
  default_columns = (
33
27
  "name",
34
28
  "tags",