netbox-plugin-dns 1.3b2__py3-none-any.whl → 1.3.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.

netbox_dns/__init__.py CHANGED
@@ -4,7 +4,7 @@ from django.core.exceptions import ImproperlyConfigured
4
4
  from netbox.plugins import PluginConfig
5
5
  from netbox.plugins.utils import get_plugin_config
6
6
 
7
- __version__ = "1.3-beta2"
7
+ __version__ = "1.3.1"
8
8
 
9
9
 
10
10
  def _check_list(setting):
@@ -16,7 +16,7 @@ class DNSConfig(PluginConfig):
16
16
  name = "netbox_dns"
17
17
  verbose_name = _("NetBox DNS")
18
18
  description = _("NetBox plugin for DNS data")
19
- min_version = "4.2.0"
19
+ min_version = "4.3.0"
20
20
  version = __version__
21
21
  author = "Peter Eckel"
22
22
  author_email = "pete@netbox-dns.org"
@@ -62,6 +62,7 @@ class DNSSECKeyTemplateSerializer(NetBoxModelSerializer):
62
62
  help_text=_("Policies using this Key Template"),
63
63
  )
64
64
  tenant = TenantSerializer(
65
+ nested=True,
65
66
  required=False,
66
67
  allow_null=True,
67
68
  )
@@ -136,6 +136,7 @@ class DNSSECPolicySerializer(NetBoxModelSerializer):
136
136
  help_text=_("Zone templates this policy is assigned to"),
137
137
  )
138
138
  tenant = TenantSerializer(
139
+ nested=True,
139
140
  required=False,
140
141
  allow_null=True,
141
142
  )
@@ -48,4 +48,8 @@ class NameServerSerializer(NetBoxModelSerializer):
48
48
  default=None,
49
49
  help_text=_("Zones served by the authoritative nameserver"),
50
50
  )
51
- tenant = TenantSerializer(required=False, allow_null=True)
51
+ tenant = TenantSerializer(
52
+ nested=True,
53
+ required=False,
54
+ allow_null=True,
55
+ )
@@ -35,7 +35,7 @@ class RecordSerializer(NetBoxModelSerializer):
35
35
  "managed",
36
36
  "disable_ptr",
37
37
  "ptr_record",
38
- "address_record",
38
+ "address_records",
39
39
  "active",
40
40
  "custom_fields",
41
41
  "tenant",
@@ -71,14 +71,14 @@ class RecordSerializer(NetBoxModelSerializer):
71
71
  read_only=True,
72
72
  required=False,
73
73
  allow_null=True,
74
- help_text=_("PTR record generated from an address"),
74
+ help_text=_("PTR record related to an address"),
75
75
  )
76
- address_record = NestedRecordSerializer(
77
- many=False,
76
+ address_records = NestedRecordSerializer(
77
+ many=True,
78
78
  read_only=True,
79
79
  required=False,
80
80
  allow_null=True,
81
- help_text=_("Address record defining the PTR"),
81
+ help_text=_("Address records related to the PTR"),
82
82
  )
83
83
  zone = NestedZoneSerializer(
84
84
  many=False,
@@ -63,10 +63,10 @@ class RecordFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
63
63
  label=_("View the Parent Zone belongs to"),
64
64
  )
65
65
  address_record_id = django_filters.ModelMultipleChoiceFilter(
66
- field_name="address_record",
66
+ field_name="address_records",
67
67
  queryset=Record.objects.all(),
68
68
  to_field_name="id",
69
- label=_("Address Record"),
69
+ label=_("Address Records"),
70
70
  )
71
71
  ptr_record_id = django_filters.ModelMultipleChoiceFilter(
72
72
  field_name="ptr_record",
netbox_dns/forms/zone.py CHANGED
@@ -534,7 +534,7 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
534
534
  )
535
535
  parental_agents = forms.GenericIPAddressField(
536
536
  required=False,
537
- label=_("Parental Agent"),
537
+ label=_("Parental Agents"),
538
538
  )
539
539
  registrar_id = DynamicModelMultipleChoiceField(
540
540
  queryset=Registrar.objects.all(),
@@ -165,10 +165,9 @@ class NetBoxDNSRecordType(NetBoxObjectType):
165
165
  Annotated["NetBoxDNSRecordType", strawberry.lazy("netbox_dns.graphql.types")]
166
166
  | None
167
167
  )
168
- address_record: (
168
+ address_records: List[
169
169
  Annotated["NetBoxDNSRecordType", strawberry.lazy("netbox_dns.graphql.types")]
170
- | None
171
- )
170
+ ]
172
171
  rfc2317_ptr_records: List[
173
172
  Annotated["NetBoxDNSRecordType", strawberry.lazy("netbox_dns.graphql.types")]
174
173
  ]
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ # Generated by Django 5.2 on 2025-05-13 09:16
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("netbox_dns", "0020_remove_dnssecpolicy_parental_agents_and_more"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="record",
16
+ name="ptr_record",
17
+ field=models.ForeignKey(
18
+ blank=True,
19
+ null=True,
20
+ on_delete=django.db.models.deletion.SET_NULL,
21
+ related_name="address_records",
22
+ to="netbox_dns.record",
23
+ ),
24
+ ),
25
+ ]
@@ -28,7 +28,6 @@ from netbox_dns.choices import (
28
28
  RecordClassChoices,
29
29
  )
30
30
 
31
-
32
31
  __all__ = (
33
32
  "Record",
34
33
  "RecordIndex",
@@ -143,6 +142,11 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
143
142
  "tenant",
144
143
  )
145
144
 
145
+ def __init__(self, *args, **kwargs):
146
+ super().__init__(*args, **kwargs)
147
+
148
+ self._cleanup_ptr_record = None
149
+
146
150
  def __str__(self):
147
151
  try:
148
152
  fqdn = dns_name.from_text(
@@ -206,11 +210,11 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
206
210
  null=False,
207
211
  default=False,
208
212
  )
209
- ptr_record = models.OneToOneField(
213
+ ptr_record = models.ForeignKey(
210
214
  verbose_name=_("PTR Record"),
211
215
  to="self",
212
216
  on_delete=models.SET_NULL,
213
- related_name="address_record",
217
+ related_name="address_records",
214
218
  null=True,
215
219
  blank=True,
216
220
  )
@@ -255,6 +259,14 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
255
259
  blank=True,
256
260
  )
257
261
 
262
+ @property
263
+ def cleanup_ptr_record(self):
264
+ return self._cleanup_ptr_record
265
+
266
+ @cleanup_ptr_record.setter
267
+ def cleanup_ptr_record(self, ptr_record):
268
+ self._cleanup_ptr_record = ptr_record
269
+
258
270
  @property
259
271
  def display_name(self):
260
272
  return name_to_unicode(self.name)
@@ -348,6 +360,21 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
348
360
  def is_delegation_record(self):
349
361
  return self in self.zone.delegation_records
350
362
 
363
+ def refresh_ptr_record(
364
+ self, ptr_record=None, update_rfc2317_cname=True, save_zone_serial=True
365
+ ):
366
+ if ptr_record is None:
367
+ return
368
+
369
+ if not ptr_record.address_records.exists():
370
+ if ptr_record.rfc2317_cname_record is not None:
371
+ ptr_record.remove_from_rfc2317_cname_record()
372
+
373
+ ptr_record.delete(save_zone_serial=save_zone_serial)
374
+
375
+ elif update_rfc2317_cname:
376
+ ptr_record.update_rfc2317_cname_record(save_zone_serial=save_zone_serial)
377
+
351
378
  def update_ptr_record(self, update_rfc2317_cname=True, save_zone_serial=True):
352
379
  ptr_zone = self.ptr_zone
353
380
 
@@ -357,10 +384,8 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
357
384
  or not self.is_active
358
385
  or self.name.startswith("*")
359
386
  ):
360
- if self.ptr_record is not None:
361
- with transaction.atomic():
362
- self.ptr_record.delete()
363
- self.ptr_record = None
387
+ self.cleanup_ptr_record = self.ptr_record
388
+ self.ptr_record = None
364
389
  return
365
390
 
366
391
  if ptr_zone.is_rfc2317_zone:
@@ -373,7 +398,14 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
373
398
  )
374
399
 
375
400
  ptr_value = self.fqdn
376
- ptr_record = self.ptr_record
401
+ if ptr_record := self.ptr_record:
402
+ if (
403
+ ptr_record.zone == ptr_zone
404
+ and ptr_record.name == ptr_name
405
+ and ptr_record.value == ptr_value
406
+ and ptr_record.ttl == self.ttl
407
+ ):
408
+ return
377
409
 
378
410
  if ptr_record is not None:
379
411
  if (
@@ -384,24 +416,36 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
384
416
  save_zone_serial=save_zone_serial
385
417
  )
386
418
 
419
+ try:
420
+ ptr_record = Record.objects.get(
421
+ name=ptr_name,
422
+ zone=ptr_zone,
423
+ type=RecordTypeChoices.PTR,
424
+ value=ptr_value,
425
+ )
426
+ except Record.DoesNotExist:
427
+ pass
428
+
387
429
  with transaction.atomic():
388
430
  if ptr_record is not None:
389
431
  if ptr_record.zone.pk != ptr_zone.pk:
390
432
  if ptr_record.rfc2317_cname_record is not None:
391
433
  ptr_record.rfc2317_cname_record.delete()
392
- ptr_record.delete(save_zone_serial=save_zone_serial)
393
- ptr_record = None
434
+ ptr_record.rfc2317_cname_record = None
435
+
436
+ if ptr_record.address_records.count() == 1:
437
+ ptr_record.zone = ptr_zone
438
+ ptr_record.name = ptr_name
439
+ ptr_record.value = ptr_value
440
+ ptr_record.ttl = self.ttl
441
+ ptr_record.save(
442
+ update_rfc2317_cname=update_rfc2317_cname,
443
+ save_zone_serial=save_zone_serial,
444
+ )
394
445
 
395
446
  else:
396
- if (
397
- ptr_record.name != ptr_name
398
- or ptr_record.value != ptr_value
399
- or ptr_record.ttl != self.ttl
400
- ):
401
- ptr_record.name = ptr_name
402
- ptr_record.value = ptr_value
403
- ptr_record.ttl = self.ttl
404
- ptr_record.save(save_zone_serial=save_zone_serial)
447
+ self.ptr_record = ptr_record
448
+ return
405
449
 
406
450
  if ptr_record is None:
407
451
  ptr_record = Record(
@@ -905,13 +949,19 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
905
949
  save_zone_serial=save_zone_serial,
906
950
  )
907
951
  elif self.ptr_record is not None:
908
- self.ptr_record.delete()
952
+ self.cleanup_ptr_record = self.ptr_record
909
953
  self.ptr_record = None
910
954
 
911
955
  changed_fields = self.changed_fields
912
956
  if changed_fields is None or changed_fields:
913
957
  super().save(*args, **kwargs)
914
958
 
959
+ self.refresh_ptr_record(
960
+ self.cleanup_ptr_record,
961
+ update_rfc2317_cname=update_rfc2317_cname,
962
+ save_zone_serial=save_zone_serial,
963
+ )
964
+
915
965
  if self.type != RecordTypeChoices.SOA and self.zone.soa_serial_auto:
916
966
  self.zone.update_serial(save_zone_serial=save_zone_serial)
917
967
 
@@ -919,11 +969,16 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
919
969
  if self.rfc2317_cname_record:
920
970
  self.remove_from_rfc2317_cname_record(save_zone_serial=save_zone_serial)
921
971
 
922
- if self.ptr_record:
923
- self.ptr_record.delete()
972
+ ptr_record = self.ptr_record
924
973
 
925
974
  super().delete(*args, **kwargs)
926
975
 
976
+ self.refresh_ptr_record(
977
+ ptr_record,
978
+ update_rfc2317_cname=True,
979
+ save_zone_serial=save_zone_serial,
980
+ )
981
+
927
982
  _zone = self.zone
928
983
  if _zone.soa_serial_auto:
929
984
  _zone.update_serial(save_zone_serial=save_zone_serial)
netbox_dns/models/zone.py CHANGED
@@ -1036,7 +1036,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
1036
1036
  for address_record in address_records:
1037
1037
  address_record.ptr_record.delete()
1038
1038
 
1039
- ptr_records = self.records.filter(address_record__isnull=False)
1039
+ ptr_records = self.records.filter(address_records__isnull=False)
1040
1040
  update_records = list(
1041
1041
  Record.objects.filter(ptr_record__in=ptr_records).values_list(
1042
1042
  "pk", flat=True
@@ -116,9 +116,15 @@ class ManagedRecordTable(RecordBaseTable):
116
116
  "active",
117
117
  )
118
118
 
119
- address_record = tables.Column(
120
- verbose_name=_("Address Record"),
119
+ address_records = tables.ManyToManyColumn(
120
+ verbose_name=_("Address Records"),
121
121
  linkify=True,
122
+ linkify_item=True,
123
+ transform=lambda obj: (
124
+ obj.fqdn.rstrip(".")
125
+ if obj.zone.view.default_view
126
+ else f"[{obj.zone.view.name}] {obj.fqdn.rstrip('.')}"
127
+ ),
122
128
  )
123
129
  ipam_ip_address = tables.Column(
124
130
  verbose_name=_("IPAM IP Address"),
@@ -134,12 +140,16 @@ class ManagedRecordTable(RecordBaseTable):
134
140
  def render_related_ip_address(self, record):
135
141
  if record.ipam_ip_address is not None:
136
142
  address = record.ipam_ip_address
137
- elif (
138
- hasattr(record, "address_record")
139
- and record.address_record.ipam_ip_address is not None
140
- ):
141
- address = record.address_record.ipam_ip_address
142
- else:
143
+ elif hasattr(record, "address_records"):
144
+ address_record = record.address_records.filter(
145
+ ipam_ip_address__isnull=False
146
+ ).first()
147
+ if address_record is not None:
148
+ address = address_record.ipam_ip_address
149
+ else:
150
+ address = None
151
+
152
+ if address is None:
143
153
  return format_html("—")
144
154
 
145
155
  return format_html(f"<a href='{address.get_absolute_url()}'>{address}</a>")
@@ -147,11 +157,14 @@ class ManagedRecordTable(RecordBaseTable):
147
157
  def value_related_ip_address(self, record):
148
158
  if record.ipam_ip_address is not None:
149
159
  return record.ipam_ip_address
150
- elif (
151
- hasattr(record, "address_record")
152
- and record.address_record.ipam_ip_address is not None
153
- ):
154
- return record.address_record.ipam_ip_address
160
+ elif hasattr(record, "address_records"):
161
+ address_record = record.address_records.filter(
162
+ ipam_ip_address__isnull=False
163
+ ).first()
164
+ if address_record is not None:
165
+ return address_record.ipam_ip_address
166
+
167
+ return None
155
168
 
156
169
 
157
170
  class RelatedRecordTable(RecordBaseTable):
netbox_dns/tables/view.py CHANGED
@@ -57,4 +57,5 @@ class RelatedViewTable(TenancyColumnsMixin, NetBoxTable):
57
57
  name = tables.Column(
58
58
  linkify=True,
59
59
  )
60
+ tags = TagColumn(url_name="plugins:netbox_dns:view_list")
60
61
  actions = ActionsColumn(actions=())
@@ -20,6 +20,7 @@ class RelatedDNSRecords(PluginTemplateExtension):
20
20
 
21
21
  def right_page(self):
22
22
  ip_address = self.context.get("object")
23
+ request = self.context.get("request")
23
24
 
24
25
  address_records = ip_address.netbox_dns_records.all()
25
26
  pointer_records = [
@@ -32,6 +33,7 @@ class RelatedDNSRecords(PluginTemplateExtension):
32
33
  address_record_table = RelatedRecordTable(
33
34
  data=address_records,
34
35
  )
36
+ address_record_table.configure(request)
35
37
  else:
36
38
  address_record_table = None
37
39
 
@@ -39,6 +41,7 @@ class RelatedDNSRecords(PluginTemplateExtension):
39
41
  pointer_record_table = RelatedRecordTable(
40
42
  data=pointer_records,
41
43
  )
44
+ pointer_record_table.configure(request)
42
45
  else:
43
46
  pointer_record_table = None
44
47
 
@@ -56,11 +59,16 @@ class RelatedDNSViews(PluginTemplateExtension):
56
59
 
57
60
  def right_page(self):
58
61
  prefix = self.context.get("object")
62
+ request = self.context.get("request")
59
63
 
60
64
  if assigned_views := prefix.netbox_dns_views.all():
61
- context = {"assigned_views": RelatedViewTable(data=assigned_views)}
65
+ assigned_views_table = RelatedViewTable(data=assigned_views)
66
+ assigned_views_table.configure(request)
67
+ context = {"assigned_views": assigned_views_table}
62
68
  elif inherited_views := get_views_by_prefix(prefix):
63
- context = {"inherited_views": RelatedViewTable(data=inherited_views)}
69
+ inherited_views_table = RelatedViewTable(data=inherited_views)
70
+ inherited_views_table.configure(request)
71
+ context = {"inherited_views": inherited_views_table}
64
72
  else:
65
73
  context = {}
66
74
 
@@ -86,6 +94,7 @@ class IPRelatedDNSRecords(PluginTemplateExtension):
86
94
 
87
95
  def right_page(self):
88
96
  ip_address = self.context.get("object")
97
+ request = self.context.get("request")
89
98
 
90
99
  address_records = Record.objects.filter(
91
100
  type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
@@ -100,6 +109,7 @@ class IPRelatedDNSRecords(PluginTemplateExtension):
100
109
  address_record_table = RelatedRecordTable(
101
110
  data=address_records,
102
111
  )
112
+ address_record_table.configure(request)
103
113
  else:
104
114
  address_record_table = None
105
115
 
@@ -107,6 +117,7 @@ class IPRelatedDNSRecords(PluginTemplateExtension):
107
117
  pointer_record_table = RelatedRecordTable(
108
118
  data=pointer_records,
109
119
  )
120
+ pointer_record_table.configure(request)
110
121
  else:
111
122
  pointer_record_table = None
112
123
 
@@ -116,22 +116,24 @@
116
116
  <td>{{ object.ptr_record|linkify }}</td>
117
117
  </tr>
118
118
  {% endif %}
119
- {% if object.address_record %}
119
+ {% if object.address_records.exists %}
120
120
  <tr>
121
- <th scope="row">{% trans "Address Record" %}</th>
122
- <td>{{ object.address_record|linkify }}</td>
123
- </tr>
124
- {% if object.address_record.ipam_ip_address %}
125
- <tr>
126
- <th scope="row">{% trans "IPAM IP Address" %}</th>
127
- <td>{{ object.address_record.ipam_ip_address|linkify }}</td>
121
+ <th scope="row">{% trans "Address Records" %}</th>
122
+ <td>
123
+ <table>
124
+ {% for address_record in object.address_records.all %}
125
+ <tr>
126
+ <td>{{ address_record|linkify:"name" }}.{{ address_record.zone|linkify:"name" }}</td>
127
+ </tr>
128
+ {% endfor %}
129
+ </table>
130
+ </td>
128
131
  </tr>
129
132
  {% endif %}
130
- {% endif %}
131
- {% if object.ipam_ip_address %}
133
+ {% if ipam_ip_address %}
132
134
  <tr>
133
135
  <th scope="row">{% trans "IPAM IP Address" %}</th>
134
- <td>{{ object.ipam_ip_address|linkify }}</td>
136
+ <td>{{ ipam_ip_address|linkify }}</td>
135
137
  </tr>
136
138
  {% endif %}
137
139
  <tr>
@@ -49,7 +49,7 @@ def _get_label(tolerate_leading_underscores=False, always_tolerant=False):
49
49
 
50
50
 
51
51
  def _has_invalid_double_dash(name):
52
- return bool(re.findall(r"\b(?!xn)..--", name, re.IGNORECASE))
52
+ return bool(re.findall(r"(^|\.)(?!xn)..--", name, re.IGNORECASE))
53
53
 
54
54
 
55
55
  def validate_fqdn(name, always_tolerant=False):
@@ -37,9 +37,9 @@ class DNSSECKeyTemplateView(generic.ObjectView):
37
37
 
38
38
  def get_extra_context(self, request, instance):
39
39
  if instance.policies.exists():
40
- return {
41
- "policy_table": DNSSECPolicyDisplayTable(data=instance.policies.all())
42
- }
40
+ policy_table = DNSSECPolicyDisplayTable(data=instance.policies.all())
41
+ policy_table.configure(request)
42
+ return {"policy_table": policy_table}
43
43
 
44
44
  return {}
45
45
 
@@ -51,7 +51,7 @@ class RecordListView(generic.ObjectListView):
51
51
  @register_model_view(Record, "list_managed", path="managed", detail=False)
52
52
  class ManagedRecordListView(generic.ObjectListView):
53
53
  queryset = Record.objects.filter(managed=True).prefetch_related(
54
- "ipam_ip_address", "address_record"
54
+ "ipam_ip_address", "address_records"
55
55
  )
56
56
  filterset = RecordFilterSet
57
57
  filterset_form = RecordFilterForm
@@ -141,11 +141,26 @@ class RecordView(generic.ObjectView):
141
141
 
142
142
  if instance.type == RecordTypeChoices.CNAME:
143
143
  try:
144
- context["cname_target_table"] = self.get_value_records(instance)
144
+ cname_target_table = self.get_value_records(instance)
145
+ if cname_target_table is not None:
146
+ cname_target_table.configure(request)
147
+ context["cname_target_table"] = cname_target_table
145
148
  except CNAMEWarning as exc:
146
149
  context["cname_warning"] = str(exc)
147
150
  else:
148
- context["cname_table"] = self.get_cname_records(instance)
151
+ cname_table = self.get_cname_records(instance)
152
+ if cname_table is not None:
153
+ cname_table.configure(request)
154
+ context["cname_table"] = cname_table
155
+
156
+ if instance.ipam_ip_address is not None:
157
+ context["ipam_ip_address"] = instance.ipam_ip_address
158
+ elif instance.address_records is not None:
159
+ address_record = instance.address_records.filter(
160
+ ipam_ip_address__isnull=False
161
+ ).first()
162
+ if address_record is not None:
163
+ context["ipam_ip_address"] = address_record.ipam_ip_address
149
164
 
150
165
  if not instance.managed:
151
166
  name = dns_name.from_text(instance.name, origin=None)
@@ -155,6 +170,7 @@ class RecordView(generic.ObjectView):
155
170
 
156
171
  if Zone.objects.filter(
157
172
  active=True,
173
+ view=instance.zone.view,
158
174
  name__iregex=regex_from_list(
159
175
  get_parent_zone_names(
160
176
  instance.fqdn,
@@ -50,9 +50,11 @@ class RecordTemplateView(generic.ObjectView):
50
50
  context["unicode_value"] = unicode_value
51
51
 
52
52
  if instance.zone_templates.exists():
53
- context["zone_template_table"] = ZoneTemplateDisplayTable(
53
+ zone_template_table = ZoneTemplateDisplayTable(
54
54
  data=instance.zone_templates.all()
55
55
  )
56
+ zone_template_table.configure(request)
57
+ context["zone_template_table"] = zone_template_table
56
58
 
57
59
  return context
58
60
 
@@ -37,10 +37,12 @@ class ZoneTemplateView(generic.ObjectView):
37
37
 
38
38
  def get_extra_context(self, request, instance):
39
39
  if instance.record_templates.exists():
40
+ record_template_table = RecordTemplateDisplayTable(
41
+ data=instance.record_templates.all()
42
+ )
43
+ record_template_table.configure(request)
40
44
  return {
41
- "record_template_table": RecordTemplateDisplayTable(
42
- data=instance.record_templates.all()
43
- )
45
+ "record_template_table": record_template_table,
44
46
  }
45
47
 
46
48
  return {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netbox-plugin-dns
3
- Version: 1.3b2
3
+ Version: 1.3.1
4
4
  Summary: NetBox DNS is a NetBox plugin for managing DNS data.
5
5
  Author-email: Peter Eckel <pete@netbox-dns.org>
6
6
  Project-URL: Homepage, https://github.com/peteeckel/netbox-plugin-dns
@@ -8,7 +8,7 @@ Project-URL: Documentation, https://github.com/peteeckel/netbox-plugin-dns/blob/
8
8
  Project-URL: Repository, https://github.com/peteeckel/netbox-plugin-dns
9
9
  Project-URL: Issues, https://github.com/peteeckel/netbox-plugin-dns/issues
10
10
  Keywords: netbox,netbox-plugin,dns
11
- Classifier: Development Status :: 4 - Beta
11
+ Classifier: Development Status :: 5 - Production/Stable
12
12
  Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
@@ -52,6 +52,7 @@ The main focus of the plugin is to ensure the quality of the data stored in it.
52
52
  * Support for [RFC 2317](https://datatracker.ietf.org/doc/html/rfc2317) delegation of PTR zones for IPv4 subnets longer than 24 bits
53
53
  * Templating for zones and records enables faster creations of zones with given boilerplate object relations, such as name servers, tags, tenants or registration information, or records like standard SPF or MX records that are the same for a subset of zones
54
54
  * IPAM DNSsync can be used to automatically create address and pointer records for IP addresses by assigning prefixes to DNS views. When an IP address has a DNS name assigned and there are zones with matching names in the DNS views linked to the IP address' prefix, a matching DNS record will be created in these zones
55
+ * DNSSEC support for storing configuration data relevant to DNSSEC operation in NetBox DNS
55
56
 
56
57
  Other main features include:
57
58
 
@@ -1,7 +1,7 @@
1
- netbox_dns/__init__.py,sha256=OL4QOmcjmSwmWCCPgxxTAr5DuCfF8MleRIsmiMJOsfY,4894
1
+ netbox_dns/__init__.py,sha256=GEWbFp50kHBgrhLUzp8A7ExgJAOKlyH0Oz8BdkjQjAk,4890
2
2
  netbox_dns/apps.py,sha256=JCW5eS-AQBUubDJve1DjP-IRFKTFGQh1NLGWzJpC5MI,151
3
3
  netbox_dns/navigation.py,sha256=u90MwWBySg1Z9yfZEdvUctYWEkab5z1Y3019J7U_-3g,7741
4
- netbox_dns/template_content.py,sha256=irgHJe91TnmmL9K1Xnv07uGmOeJMn9zTrIKtJev88XI,4283
4
+ netbox_dns/template_content.py,sha256=nwjbWkMc02vpTmcFQdiAA1TdopJiZ0MkRy6qa18_wLI,4848
5
5
  netbox_dns/urls.py,sha256=wrse8l5scD-jz_O7WY0YXRlYPzpkL-0-kyAd-wCPtbQ,2596
6
6
  netbox_dns/api/field_serializers.py,sha256=nVZ6d69DWagONDwbYCP2j3cmL-x9lryitF1wThEJxyI,725
7
7
  netbox_dns/api/nested_serializers.py,sha256=7ViTZBNMEZ7-NAGn5LXnd7AWxt7TbpFdAq1pcCPtTK8,3695
@@ -9,11 +9,11 @@ netbox_dns/api/serializers.py,sha256=OHrpfJkBn6D1y6b3nIxBEFyE50U5p-Aqv4lBojMEFgk
9
9
  netbox_dns/api/urls.py,sha256=-kQaei47yZeGbDpQ9RaFaFlFb682ThuPA5h321_2cgM,1000
10
10
  netbox_dns/api/views.py,sha256=w71SRyZue5zPD1C64TIr496nYFA_ARjHTlpSVFTZ76o,4522
11
11
  netbox_dns/api/serializers_/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- netbox_dns/api/serializers_/dnssec_key_template.py,sha256=Uz0uJEDuLJd4nO2yKX50ko2FMhiZP8Ye2KsHzq_23Rc,1633
13
- netbox_dns/api/serializers_/dnssec_policy.py,sha256=wNWd_LmXiFsegsL0J75gIAffeHIFV5_KGENyGGk5uwI,4301
14
- netbox_dns/api/serializers_/nameserver.py,sha256=CXwrzUQi_q4XYY9NHCAuinRHVVIYY049voNSG7jw46k,1244
12
+ netbox_dns/api/serializers_/dnssec_key_template.py,sha256=gZNv8hdpTc_X0rhfuKfUcsLzV_l6CV_tTzElw6tyEGw,1654
13
+ netbox_dns/api/serializers_/dnssec_policy.py,sha256=DOGtQDiLLMmH2TvmVp9w-enZtrXygiSwfiREWk2IjH0,4322
14
+ netbox_dns/api/serializers_/nameserver.py,sha256=0ItKFCmDVqMbw9i5LandYMZTpJAGClu6lejaWvpLbBY,1288
15
15
  netbox_dns/api/serializers_/prefix.py,sha256=kZ1DjDly6VFZamXSxGa57YC6MfZZcI5S7jmGBkVB2_I,551
16
- netbox_dns/api/serializers_/record.py,sha256=p33Nw1TV5pvlcEmEVt5Q_4HxLo8D0cop45FP5kNCmgI,2570
16
+ netbox_dns/api/serializers_/record.py,sha256=wHs86KwLCgeC_7ORw2b0gvlpAustwfBSfbPva1yPb-k,2570
17
17
  netbox_dns/api/serializers_/record_template.py,sha256=imRRPkCXQMCpXUUk58kB2KwXC6SyAo4HN18pSZyLpHI,1682
18
18
  netbox_dns/api/serializers_/registrar.py,sha256=ul_6SJVqxvTE2ysXBy52U59oTzwmaD781URH1l1OW9o,927
19
19
  netbox_dns/api/serializers_/registration_contact.py,sha256=P_aoG_1rriHn4KkwTx5Dhw37Rn3VY2whg0vAIm55cjk,1108
@@ -37,7 +37,7 @@ netbox_dns/filtersets/__init__.py,sha256=bKppz_w3X2xNNHOcxZZiIO7zSkDaNTrZJ__k1U7
37
37
  netbox_dns/filtersets/dnssec_key_template.py,sha256=dFaNGYdGXghe_uDMedOPxrMGxhDu4gHXwSQ6VLSY7gk,1625
38
38
  netbox_dns/filtersets/dnssec_policy.py,sha256=FRmHulpWmglf89J6bzQYUVFFxvt0mvp29kp7LHA5080,3071
39
39
  netbox_dns/filtersets/nameserver.py,sha256=4hkFsohhvBptFwY9_LJJN8_8KkMhCPsFujzIlDhlnqw,1251
40
- netbox_dns/filtersets/record.py,sha256=PWNNVIzur_5sJDJ2t6hqThg3TaJjEeMOWtw_uAp9NsA,3914
40
+ netbox_dns/filtersets/record.py,sha256=7asGcd2zePhnIDAvuVE-aKAo_NNM0Pm06epXzEql4y4,3916
41
41
  netbox_dns/filtersets/record_template.py,sha256=Pc4P479MqfgdUMvBK39ic2nsV_gg4GT_tbdVcCL9wSI,1605
42
42
  netbox_dns/filtersets/registrar.py,sha256=6QrsrWXu19bMa99DzwwXqfNqxpvTG0JwGEpybhOSYps,978
43
43
  netbox_dns/filtersets/registration_contact.py,sha256=42j7NkwkbSEfomCDekkIE9ZWNug_qfvmTO_D1e-fFIw,1140
@@ -53,13 +53,13 @@ netbox_dns/forms/record_template.py,sha256=5yuY2ppV2diEOdm_IN3QSLLEdWkOkWZOYRtOh
53
53
  netbox_dns/forms/registrar.py,sha256=oLMcXJOpt0F02a2Aga6A45rja7TvI18nTCZb_Dx_8t0,4038
54
54
  netbox_dns/forms/registration_contact.py,sha256=GtUmHzPmAFNRt81rTgJbmb5TMoEJ-mpmjltkuyppJwc,6157
55
55
  netbox_dns/forms/view.py,sha256=KZ2enzbqAEElt3b5C02kMJwnIDEjdQf_BsgMuMqKP50,10836
56
- netbox_dns/forms/zone.py,sha256=-BU1IqEyZ8LC82OMtnsEwnn2AL2SvfsoTYIxlZdyZP0,29920
56
+ netbox_dns/forms/zone.py,sha256=Z6YypsV9tKdnNPWekLZFZVGoHz8UBO2Hylnium5M26c,29921
57
57
  netbox_dns/forms/zone_template.py,sha256=ACx8YJirsrGMMQExVL-aEOaitsUYMyNBL793CoQZrWQ,11716
58
58
  netbox_dns/graphql/__init__.py,sha256=0xg_5d1PPFTadBOZo752t5sfZeLFrqs2jM51Rbf8ti4,652
59
59
  netbox_dns/graphql/enums.py,sha256=vC-v24AuNbaGoekLTDu1PBVbnR1aYeX6LmvrZkfd2F4,1453
60
60
  netbox_dns/graphql/filter_lookups.py,sha256=P6wW2JrtkzUiIx6mJz_DvwYg5Sov68IKAx0zVQfuvYY,355
61
61
  netbox_dns/graphql/schema.py,sha256=KlbJmlfQEqZhvb6-cYmq94mrMFcQoCh3MldaUD5eVV4,2904
62
- netbox_dns/graphql/types.py,sha256=119sdeUAFIII85LZluBTKeZDEH5pnQ3JSYwUJOUVkAk,10192
62
+ netbox_dns/graphql/types.py,sha256=H03lx5YTkxLevGtTHGV5VkdKbTJbgvUYPGqBWl3X8Q4,10182
63
63
  netbox_dns/graphql/filters/__init__.py,sha256=bKppz_w3X2xNNHOcxZZiIO7zSkDaNTrZJ__k1U7rKik,275
64
64
  netbox_dns/graphql/filters/dnssec_key_template.py,sha256=EPZqXaQyZ6UAnUgKy6_NjxbhXDbOI8oM7I62BuwGzR0,2071
65
65
  netbox_dns/graphql/filters/dnssec_policy.py,sha256=MImrsCGjNKxqCRB8HGOoNKyqxRuZyhq3su_nT5hdxW4,4651
@@ -71,9 +71,9 @@ netbox_dns/graphql/filters/registration_contact.py,sha256=Gwwj55846y90xJiVIdBfPD
71
71
  netbox_dns/graphql/filters/view.py,sha256=dNjGoSj5aKuQmofRDEIhxTs07ZWc8T0uheI6FOPTafQ,929
72
72
  netbox_dns/graphql/filters/zone.py,sha256=y5262E4Xqghny8-oUgkt0pod5KtPvZjxAsEowJ5HCdU,5248
73
73
  netbox_dns/graphql/filters/zone_template.py,sha256=I7_NFFkI8dsVMgIS5PV-VBkoxGZg2w74G3XXq2Fmdco,3095
74
- netbox_dns/locale/de/LC_MESSAGES/django.mo,sha256=2aWnoyYtInSC7wQTIAXO7E4oNxo_g281o8-42-Ilkr8,30000
74
+ netbox_dns/locale/de/LC_MESSAGES/django.mo,sha256=lwJghKXnXryPoDpC8TpvN2QyzY8vCBfF-Bmf_MWhZYs,29944
75
75
  netbox_dns/locale/en/LC_MESSAGES/django.mo,sha256=GDnSZkfHs3yjtTsll7dksEEej4B50F8pc9RGytZNubM,393
76
- netbox_dns/locale/fr/LC_MESSAGES/django.mo,sha256=XjWCnhwjI4Iwht_2JpPLB2btIg6f4ED8F3LqYPwNffA,30023
76
+ netbox_dns/locale/fr/LC_MESSAGES/django.mo,sha256=vL8TcVYyBiDFZ3GVdZe4Kkc42mmtbMF3fot8maY-Q_s,30088
77
77
  netbox_dns/management/commands/cleanup_database.py,sha256=1-tAl0Sht80qaNZyfFyUW19Eh9gBUuc7GdbHN4aemGU,5935
78
78
  netbox_dns/management/commands/cleanup_rrset_ttl.py,sha256=UFRURLBcFeGHUS2lrYFv7UWIebjI72aG1EUQJt0XsXw,2046
79
79
  netbox_dns/management/commands/rebuild_dnssync.py,sha256=Tcl385u6kJTX47SvSyRzKm1RIx4nYRYCMcKr3uVnV60,1246
@@ -101,6 +101,7 @@ netbox_dns/migrations/0018_zone_domain_status_zone_expiration_date.py,sha256=P_J
101
101
  netbox_dns/migrations/0019_dnssecpolicy_parental_agents.py,sha256=ENbj3lhsCYHBflUnb2LrfUyTxwvPwcACmL8sUsm7P7A,655
102
102
  netbox_dns/migrations/0020_netbox_3_4.py,sha256=UMcHdn8ZAuQjUaM_3rEGpktYrM0TuvhccD7Jt7WQnPs,1271
103
103
  netbox_dns/migrations/0020_remove_dnssecpolicy_parental_agents_and_more.py,sha256=Fq2Tv-yz4TAY0yzyVs6j79ztIJa1wOm5oSdbPosYdh0,756
104
+ netbox_dns/migrations/0021_alter_record_ptr_record.py,sha256=arSb_EVRX0RjuldPpFTjfyLHPmzQbyzHq9qw1It50c0,656
104
105
  netbox_dns/migrations/0021_record_ip_address.py,sha256=EqdhWXmq7aiK4X79xTRUZng3zFncCl-8JoO65HqlJKw,3244
105
106
  netbox_dns/migrations/0022_search.py,sha256=KW1ffEZ4-0dppGQ_KD1EN7iw8eQJOnDco-xfJFRZqKQ,172
106
107
  netbox_dns/migrations/0023_alter_record_value.py,sha256=4_4v8YZzU8_jadJqIUUjH6SIhNTeALWhclozTqYDmv0,378
@@ -117,12 +118,12 @@ netbox_dns/models/__init__.py,sha256=CuwFENIVUv0FNMDlY18Am-mvN5kBGkPOGavCP0cle7c
117
118
  netbox_dns/models/dnssec_key_template.py,sha256=Nv0vjdkOFWMptRYR1sT60bM6D8n_SnCpPZhI7WE5_UQ,2588
118
119
  netbox_dns/models/dnssec_policy.py,sha256=REsE8p04bgJVF8yJuWuUITXpsZmvVlXWyQuJ9I6dEMs,5268
119
120
  netbox_dns/models/nameserver.py,sha256=oVfyc_iWRzxVE2tIhfRb1Vuj2gZmlfFFzEtXj9ZEr6s,3848
120
- netbox_dns/models/record.py,sha256=wmKwKKtzd9WQ1oa3G6WThPX9E2lTGsnckzdw_FpFZo4,29614
121
+ netbox_dns/models/record.py,sha256=hXQDW28mau6DJ1p6clol3-5-N-OF2L_PYS--CW9QhrE,31275
121
122
  netbox_dns/models/record_template.py,sha256=Qr43_YZm1z3Od1cBdDY9wpNlV-UCzvpn2c6_dDzFzN8,5145
122
123
  netbox_dns/models/registrar.py,sha256=-ozazecvd-oryEoDlOUvTWhEQKKQp3my6YVTEzWlUuI,1747
123
124
  netbox_dns/models/registration_contact.py,sha256=9ehnTjg8KUrUYJKRRu2SaJX-NE5dO4wy90FRPlT2ys4,3620
124
125
  netbox_dns/models/view.py,sha256=pwo7i8gtukIRgAC1A4rm58jcEpIbsSW_IUq6vSv-mRo,4618
125
- netbox_dns/models/zone.py,sha256=FIGoFs-JM6Su4JZW-zBe3J2IIZUGZTxm6HOFhQyTDZg,35641
126
+ netbox_dns/models/zone.py,sha256=olGZyUsSF0orwefxNUtilsxByr3UceDdF8g8QIYCcsE,35642
126
127
  netbox_dns/models/zone_template.py,sha256=aUkMtWL7SAcmmBd-w33Z5HN6N9LlSlKmYNwf9MlwNq4,5051
127
128
  netbox_dns/signals/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
129
  netbox_dns/signals/dnssec.py,sha256=o4MOEg6ftxoDWFAhDtajkXzb7Nb6KuUHjtx1zNu7C1w,1040
@@ -132,17 +133,17 @@ netbox_dns/tables/dnssec_key_template.py,sha256=5Y4S3Q_RtDdUHI4KxY37Trm7uKQCFUcq
132
133
  netbox_dns/tables/dnssec_policy.py,sha256=6GIhoecku3BjYwx7wsOzzkZ0uEVZk5bA63foJ3_g9sw,3332
133
134
  netbox_dns/tables/ipam_dnssync.py,sha256=7IK95XlA2ter6gsHqXjXPd6WubpOxrV-O5-UT6R1CKU,330
134
135
  netbox_dns/tables/nameserver.py,sha256=NFFHwwW174x_XskHF9oBllnI22PGV0J78mklrJF_psw,741
135
- netbox_dns/tables/record.py,sha256=r6gcZA4iocZDkHR-vZIGSqNV7iO2Q-SHv01f6c4MhIY,4307
136
+ netbox_dns/tables/record.py,sha256=DRe0voUIlqi3Q4CHDp-xgzCqgnSG9ynBhNPO8vnzHQw,4777
136
137
  netbox_dns/tables/record_template.py,sha256=ueNSya2Zyrm_zU1Z-ZxwhsJIfxBtYXXoi2pSX-l4Bt8,1977
137
138
  netbox_dns/tables/registrar.py,sha256=yI4n0jq7igYwa-zs6YT6YVV2FxkgpfkSAsA_iPzel7A,776
138
139
  netbox_dns/tables/registration_contact.py,sha256=PeXp5l2WC5qIwctNdk_WP9LRDq_7bnoUlSS3OS6-SDs,980
139
- netbox_dns/tables/view.py,sha256=4EfI8SZRaCuf8LbnLi1L3Qx2upHnbKBONKF7aS0Ty_Q,1256
140
+ netbox_dns/tables/view.py,sha256=BFM50EgudRvcB32hqi0I5qA5nLBfXLzHbt_2q4_KeJA,1318
140
141
  netbox_dns/tables/zone.py,sha256=0lsfI3N9rY11Cxgr-t0PReyNRSnB10JOh-jMVZ4qEBA,2434
141
142
  netbox_dns/tables/zone_template.py,sha256=90geASGP6jSqKnvx2t-DaSxNZpp7j67lH1t0UzsKZ1Q,1755
142
143
  netbox_dns/templates/netbox_dns/dnsseckeytemplate.html,sha256=dSEyHgUp0k_5JSdR4s4m_7Rom67TqvRIQN0zbQKYfjE,2839
143
144
  netbox_dns/templates/netbox_dns/dnssecpolicy.html,sha256=dXHAt8ISsSWv-vK_kaJMcAzUBh4TZ2hAmeaYa47u0PU,7694
144
145
  netbox_dns/templates/netbox_dns/nameserver.html,sha256=MawPiuAmjFrbv0zRi-7xkm8vr-dT1tlEno8EcoQ9peU,1714
145
- netbox_dns/templates/netbox_dns/record.html,sha256=1KBT4xDooTX9kt1cUoPD2-6QnMizPmbItA0JAAgRzfw,6550
146
+ netbox_dns/templates/netbox_dns/record.html,sha256=8r-tulEu2_Is4b2RU4pjUKS2eASFdZh8z5GfHsRFz6s,6619
146
147
  netbox_dns/templates/netbox_dns/recordtemplate.html,sha256=a29PAUl-KI_I1lxWpVdPp2loJtzgis9DG9erOWrOZM0,3708
147
148
  netbox_dns/templates/netbox_dns/registrar.html,sha256=4kJuj3biiDxQrIMQEQUEmF4iGRE4psr6Fh0CBP1evz8,2308
148
149
  netbox_dns/templates/netbox_dns/registrationcontact.html,sha256=sljVp_MrPSJRc2vJCPFXq9MiWOw4wjbr1kI_YStBntw,3094
@@ -170,23 +171,23 @@ netbox_dns/utilities/conversions.py,sha256=qYnzecmR28l8Je_H0vFvzJ2sikTiEiyxr6drl
170
171
  netbox_dns/utilities/dns.py,sha256=UBiyQe8thiOTnKOmU9e2iRHHnGF9toVLe4efU623kX4,322
171
172
  netbox_dns/utilities/ipam_dnssync.py,sha256=_yuHoah_QN-opsZB51yGCkwjkij7nrmTgKHUZ-bQrBI,9625
172
173
  netbox_dns/validators/__init__.py,sha256=X0hPZlC3VZcXMcvXKZ2_5LSoEJdXPNSBr4QtEIFSBJ0,94
173
- netbox_dns/validators/dns_name.py,sha256=Sil68Av49jfZPzgFMV_1qEcLnuuAWXmbxfAJPDXUsGg,3766
174
+ netbox_dns/validators/dns_name.py,sha256=1MKnYAmkSTIQGf6zInqkpbIj5SCeCM0YGKmYOqFzUK4,3770
174
175
  netbox_dns/validators/dns_value.py,sha256=cADhgTohXAtOLPzaoMKO9DahEUiDanpdiuKonrwFw0E,5278
175
176
  netbox_dns/validators/dnssec.py,sha256=FzWLXX3qwS9ZMaLWHaBJStwJ_D96wp7GI4LYoKjoegc,4909
176
177
  netbox_dns/validators/rfc2317.py,sha256=uKkwxpakiFFKdYA0qy8WSlEnbFwJD4MDw6gGV4F6skg,706
177
178
  netbox_dns/views/__init__.py,sha256=tObkTOHw_6kVtEcwdyshN0Ql-8VGhwsgQw7owL_s2lI,273
178
- netbox_dns/views/dnssec_key_template.py,sha256=2psuQ7IFdomZbw04wseH2YAeybwwl_fY_7Tc4Mi9MyQ,2640
179
+ netbox_dns/views/dnssec_key_template.py,sha256=06omBc2RCTltGH078mNLLwz3A_y9gqrtQ08ex1XEwlg,2694
179
180
  netbox_dns/views/dnssec_policy.py,sha256=ZvkCVfvI78w8e9c0m8lSWgRwg-jg07PM8Od0HwAVjGI,4427
180
181
  netbox_dns/views/nameserver.py,sha256=cLB0W1UnnvEmYdoCYH5HmjrFhbEZ1gWxJTKdMS-wuh0,3564
181
- netbox_dns/views/record.py,sha256=e7pH_312djse7d-YSpIfzzOk5jKBDnSpsCDu0ESvBfM,6371
182
- netbox_dns/views/record_template.py,sha256=p9bg3HoXfKxut-t7gw8xkC-lv3D9Q_B3BC0eIBVbOhU,2936
182
+ netbox_dns/views/record.py,sha256=cPvsc20EUFcVidQ9YGIdsSTLHZKYzZD3JcV9bFv7iak,7123
183
+ netbox_dns/views/record_template.py,sha256=Cye1rjlpAewRgIv7QGD7o5n-knjzqjEUJzZHVxtGX4s,3041
183
184
  netbox_dns/views/registrar.py,sha256=gYpMyz3rRJDmBfEeRfVENvR6fdWXN1y0XbN4JBlXoHc,2625
184
185
  netbox_dns/views/registration_contact.py,sha256=5bJWjNBisqCkBo6d2TJyyBJlc95WM7VcSA6wsEB184k,3383
185
186
  netbox_dns/views/view.py,sha256=xLXt7sKrda3FpNXsBSJk8L8P2XhZ1sVb5OOXovCsKEU,3089
186
187
  netbox_dns/views/zone.py,sha256=tJiQWMmcuWX6OBtsflQwoTNVjp_GzeZ3-jmywRp74ZU,7065
187
- netbox_dns/views/zone_template.py,sha256=bc0oRftfWi_46UirR3zx9JW4b1E1c2Ump2q8rEQJXug,2449
188
- netbox_plugin_dns-1.3b2.dist-info/licenses/LICENSE,sha256=I3tDu11bZfhFm3EkV4zOD5TmWgLjnUNLEFwrdjniZYs,1112
189
- netbox_plugin_dns-1.3b2.dist-info/METADATA,sha256=e3pBY2nDxmGSPMOV-hfUX9Kr-_zU3CAUJOYp3BZ6W4E,7683
190
- netbox_plugin_dns-1.3b2.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
191
- netbox_plugin_dns-1.3b2.dist-info/top_level.txt,sha256=sA1Rwl1mRKvMC6XHe2ylZ1GF-Q1NGd08XedK9Y4xZc4,11
192
- netbox_plugin_dns-1.3b2.dist-info/RECORD,,
188
+ netbox_dns/views/zone_template.py,sha256=5P9DT3XBRL-TiM5zFhBTMlMusL4bP2jTu3GHxKz5ojc,2553
189
+ netbox_plugin_dns-1.3.1.dist-info/licenses/LICENSE,sha256=I3tDu11bZfhFm3EkV4zOD5TmWgLjnUNLEFwrdjniZYs,1112
190
+ netbox_plugin_dns-1.3.1.dist-info/METADATA,sha256=WTrrtHmaWlCmJS3nQRbylLWz445zCDpvXyBzW058wq0,7787
191
+ netbox_plugin_dns-1.3.1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
192
+ netbox_plugin_dns-1.3.1.dist-info/top_level.txt,sha256=sA1Rwl1mRKvMC6XHe2ylZ1GF-Q1NGd08XedK9Y4xZc4,11
193
+ netbox_plugin_dns-1.3.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5