netbox-plugin-dns 1.3.4__py3-none-any.whl → 1.3.6__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.4"
7
+ __version__ = "1.3.6"
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.3.0"
19
+ min_version = "4.3.2"
20
20
  version = __version__
21
21
  author = "Peter Eckel"
22
22
  author_email = "pete@netbox-dns.org"
@@ -1,176 +1,205 @@
1
- from netaddr import IPAddress, IPNetwork, AddrFormatError
1
+ from netaddr import IPAddress
2
2
 
3
3
  from django.core.management.base import BaseCommand
4
4
 
5
5
  from netbox_dns.models import Zone, Record
6
- from netbox_dns.choices import ZoneStatusChoices, RecordTypeChoices
6
+ from netbox_dns.choices import RecordTypeChoices
7
7
 
8
8
 
9
- def zone_rename_passive_status_to_parked(verbose=False):
10
- passive_zones = Zone.objects.filter(status="passive")
11
- if passive_zones:
12
- if verbose:
13
- print("Renaming 'passive' zone status to 'parked'")
14
-
15
- for zone in passive_zones:
16
- zone.status = ZoneStatusChoices.STATUS_PARKED
17
- zone.save()
18
-
19
-
20
- def zone_cleanup_ns_records(verbose=False):
21
- ns_name = "@"
22
-
23
- for zone in Zone.objects.all():
24
- nameservers = zone.nameservers.all()
25
- nameserver_names = [f'{ns.name.rstrip(".")}.' for ns in nameservers]
26
-
27
- delete_ns = zone.records.filter(
28
- name=ns_name, type=RecordTypeChoices.NS
29
- ).exclude(value__in=nameserver_names)
30
- for record in delete_ns:
31
- if verbose:
32
- print(f"Deleting obsolete NS record {record}")
33
- record.delete()
34
-
35
- for ns in nameserver_names:
36
- ns_records = zone.records.filter(
37
- name=ns_name,
38
- type=RecordTypeChoices.NS,
39
- value=ns,
40
- )
9
+ class Command(BaseCommand):
10
+ help = "Clean up NetBox DNS database"
41
11
 
42
- delete_ns = ns_records[1:]
12
+ def handle(self, *model_names, **options):
13
+ self._zone_cleanup_ns_records(**options)
14
+ self._zone_cleanup_soa_records(**options)
15
+ self._zone_update_arpa_network(**options)
16
+ self._record_cleanup_disable_ptr(**options)
17
+ self._record_update_ptr_records(**options)
18
+ self._record_update_ip_address(**options)
19
+ self._record_remove_orphaned_ptr_records(**options)
20
+ self._record_remove_orphaned_address_records(**options)
21
+
22
+ if options.get("verbosity"):
23
+ self.stdout.write("Database cleanup completed.")
24
+
25
+ def _zone_cleanup_ns_records(self, **options):
26
+ if options.get("verbosity"):
27
+ self.stdout.write("Cleaning up the NS records for all zones")
28
+
29
+ ns_name = "@"
30
+
31
+ for zone in Zone.objects.all():
32
+ nameservers = zone.nameservers.all()
33
+ nameserver_names = [f'{ns.name.rstrip(".")}.' for ns in nameservers]
34
+
35
+ delete_ns = zone.records.filter(
36
+ name=ns_name, type=RecordTypeChoices.NS
37
+ ).exclude(value__in=nameserver_names)
43
38
  for record in delete_ns:
44
- if verbose:
45
- print(f"Deleting duplicate NS record {record}")
39
+ if options.get("verbosity") > 1:
40
+ self.stdout.write(
41
+ f"Removing obsolete NS record '{record}' with value '{record.value}'"
42
+ )
46
43
  record.delete()
47
44
 
48
- try:
49
- ns_record = zone.records.get(
45
+ for ns in nameserver_names:
46
+ ns_records = zone.records.filter(
50
47
  name=ns_name,
51
48
  type=RecordTypeChoices.NS,
52
49
  value=ns,
53
50
  )
54
51
 
55
- if ns_record.ttl is not None or not ns_record.managed:
56
- if verbose:
57
- print(f"Updating NS record '{ns_record}'")
58
- ns_record.ttl = None
59
- ns_record.managed = True
60
- ns_record.save()
61
-
62
- except Record.DoesNotExist:
63
- if verbose:
64
- print(f"Creating NS record for '{ns.rstrip('.')}' in zone '{zone}'")
65
- Record.objects.create(
66
- name=ns_name,
67
- zone=zone,
68
- type=RecordTypeChoices.NS,
69
- value=ns,
70
- ttl=None,
71
- managed=True,
72
- )
52
+ delete_ns = ns_records[1:]
53
+ for record in delete_ns:
54
+ if options.get("verbosity") > 1:
55
+ self.stdout.write(
56
+ f"Removing duplicate NS record '{record}' with value '{record.value}'"
57
+ )
58
+ record.delete()
59
+
60
+ try:
61
+ ns_record = zone.records.get(
62
+ name=ns_name,
63
+ type=RecordTypeChoices.NS,
64
+ value=ns,
65
+ )
73
66
 
67
+ if ns_record.ttl is not None or not ns_record.managed:
68
+ if options.get("verbosity") > 1:
69
+ self.stdout.write(
70
+ f"Updating NS record '{ns_record}' with value '{record.value}'"
71
+ )
72
+ ns_record.ttl = None
73
+ ns_record.managed = True
74
+ ns_record.save()
75
+
76
+ except Record.DoesNotExist:
77
+ if options.get("verbosity") > 1:
78
+ self.stdout.write(
79
+ f"Creating NS record for '{ns.rstrip('.')}' in zone '{zone}'"
80
+ )
81
+ Record.objects.create(
82
+ name=ns_name,
83
+ zone=zone,
84
+ type=RecordTypeChoices.NS,
85
+ value=ns,
86
+ ttl=None,
87
+ managed=True,
88
+ )
74
89
 
75
- def zone_update_soa_records(verbose=False):
76
- soa_name = "@"
90
+ def _zone_cleanup_soa_records(self, **options):
91
+ if options.get("verbosity"):
92
+ self.stdout.write("Cleaning up the SOA record for all zones")
77
93
 
78
- for zone in Zone.objects.all():
79
- delete_soa = zone.records.filter(name=soa_name, type=RecordTypeChoices.SOA)[1:]
80
- for record in delete_soa:
81
- if verbose:
82
- print(f"Deleting duplicate SOA record {record}")
83
- record.delete()
94
+ soa_name = "@"
84
95
 
85
- zone.update_soa_record()
96
+ for zone in Zone.objects.all():
97
+ delete_soa = zone.records.filter(name=soa_name, type=RecordTypeChoices.SOA)[
98
+ 1:
99
+ ]
100
+ for record in delete_soa:
101
+ if options.get("verbosity") > 1:
102
+ self.stdout.write(
103
+ f"Deleting duplicate SOA record '{record}' for zone '{zone}'"
104
+ )
105
+ record.delete()
86
106
 
107
+ zone.update_soa_record()
87
108
 
88
- def zone_update_arpa_network(verbose=False):
89
- for zone in Zone.objects.filter(name__endswith=".arpa"):
90
- name = zone.name
109
+ def _zone_update_arpa_network(self, **options):
110
+ if options.get("verbosity"):
111
+ self.stdout.write("Updating the ARPA network for reverse zones")
91
112
 
92
- # TODO: Rewrite with utility function
93
- if name.endswith(".in-addr.arpa"):
94
- address = ".".join(reversed(name.replace(".in-addr.arpa", "").split(".")))
95
- mask = len(address.split(".")) * 8
113
+ for zone in Zone.objects.filter(name__endswith=".arpa"):
114
+ if zone.arpa_network != (arpa_network := zone.network_from_name):
115
+ if options.get("verbosity") > 1:
116
+ self.stdout.write(
117
+ f"Setting the ARPA network for zone '{zone}' to '{arpa_network}'"
118
+ )
96
119
 
97
- try:
98
- prefix = IPNetwork(f"{address}/{mask}")
99
- except AddrFormatError:
100
- prefix = None
120
+ zone.arpa_network = arpa_network
121
+ zone.save()
101
122
 
102
- elif name.endswith("ip6.arpa"):
103
- address = "".join(reversed(name.replace(".ip6.arpa", "").split(".")))
104
- mask = len(address)
105
- address = address + "0" * (32 - mask)
123
+ def _record_cleanup_disable_ptr(self, **options):
124
+ if options.get("verbosity"):
125
+ self.stdout.write("Updating 'Disable PTR' for non-address records")
106
126
 
107
- try:
108
- prefix = IPNetwork(
109
- f"{':'.join([(address[i:i+4]) for i in range(0, 32, 4)])}/{mask*4}"
127
+ records = Record.objects.filter(
128
+ disable_ptr=True,
129
+ ).exclude(type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA))
130
+
131
+ for record in records:
132
+ if options.get("verbosity") > 1:
133
+ self.stdout.write(
134
+ f"Setting 'Disable PTR' to False for record '{record}'"
110
135
  )
111
- except AddrFormatError:
112
- prefix = None
113
- # TODO: End
114
-
115
- if zone.arpa_network != prefix:
116
- if verbose:
117
- print(f"Updating ARPA prefix for zone '{zone}' to '{prefix}'")
118
- zone.arpa_network = prefix
119
- zone.save()
120
-
121
-
122
- def record_cleanup_disable_ptr(verbose=False):
123
- Record.objects.filter(
124
- disable_ptr=False,
125
- ).exclude(
126
- type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
127
- ).update(disable_ptr=True)
128
-
129
-
130
- def record_update_ptr_records(verbose=False):
131
- for record in Record.objects.filter(
132
- type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
133
- ):
134
- record.save(update_fields=["ptr_record"])
135
-
136
-
137
- def record_update_ip_address(verbose=False):
138
- for record in Record.objects.filter(
139
- type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA, RecordTypeChoices.PTR)
140
- ):
141
- if record.is_ptr_record:
142
- if record.ip_address != record.address_from_name:
143
- if verbose:
144
- print(
145
- f"Updating IP address of pointer record {record} to {record.address_from_name}"
146
- )
147
- record.ip_address = record.address_from_name
148
- record.save()
149
- else:
150
- if record.ip_address != IPAddress(record.value):
151
- if verbose:
152
- print(
153
- f"Updating IP address of address record {record} to {IPAddress(record.value)}"
154
- )
155
- record.ip_address = record.value
156
- record.save()
157
136
 
137
+ record.disable_ptr = False
138
+ record.save(update_fields=["disable_ptr"])
158
139
 
159
- class Command(BaseCommand):
160
- help = "Clean up NetBox DNS database"
140
+ def _record_update_ptr_records(self, **options):
141
+ if options.get("verbosity"):
142
+ self.stdout.write("Updating the PTR record for all address records")
143
+
144
+ for record in Record.objects.filter(
145
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
146
+ ):
147
+ record.save(update_fields=["ptr_record"])
161
148
 
162
- def add_arguments(self, parser):
163
- parser.add_argument(
164
- "--verbose", action="store_true", help="Increase output verbosity"
149
+ def _record_update_ip_address(self, **options):
150
+ if options.get("verbosity"):
151
+ self.stdout.write("Updating the IP address for all address and PTR records")
152
+
153
+ for record in Record.objects.filter(
154
+ type__in=(
155
+ RecordTypeChoices.A,
156
+ RecordTypeChoices.AAAA,
157
+ RecordTypeChoices.PTR,
158
+ )
159
+ ):
160
+ if record.is_ptr_record:
161
+ if record.ip_address != record.address_from_name:
162
+ if options.get("verbosity") > 1:
163
+ self.stdout.write(
164
+ f"Setting the IP Address for pointer record '{record}' to '{record.address_from_name}'"
165
+ )
166
+ record.ip_address = record.address_from_name
167
+ record.save()
168
+ else:
169
+ if record.ip_address != IPAddress(record.value):
170
+ if options.get("verbosity") > 1:
171
+ self.stdout.write(
172
+ f"Updating the IP address for address record '{record}' to '{IPAddress(record.value)}'"
173
+ )
174
+ record.ip_address = record.value
175
+ record.save()
176
+
177
+ def _record_remove_orphaned_ptr_records(self, **options):
178
+ if options.get("verbosity"):
179
+ self.stdout.write("Removing orphaned managed PTR records")
180
+
181
+ orphaned_ptr_records = Record.objects.filter(
182
+ type=RecordTypeChoices.PTR,
183
+ managed=True,
184
+ address_records__isnull=True,
165
185
  )
166
186
 
167
- def handle(self, *model_names, **options):
168
- zone_rename_passive_status_to_parked(options["verbose"])
169
- zone_cleanup_ns_records(options["verbose"])
170
- zone_update_soa_records(options["verbose"])
171
- zone_update_arpa_network(options["verbose"])
172
- record_cleanup_disable_ptr(options["verbose"])
173
- record_update_ptr_records(options["verbose"])
174
- record_update_ip_address(options["verbose"])
175
-
176
- self.stdout.write("Database cleanup completed.")
187
+ for record in orphaned_ptr_records:
188
+ if options.get("verbosity") > 1:
189
+ self.stdout.write(f"Removing orphaned PTR record '{record}'")
190
+ record.delete()
191
+
192
+ def _record_remove_orphaned_address_records(self, **options):
193
+ if options.get("verbosity"):
194
+ self.stdout.write("Removing orphaned managed address records")
195
+
196
+ orphaned_address_records = Record.objects.filter(
197
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
198
+ managed=True,
199
+ ipam_ip_address__isnull=True,
200
+ )
201
+
202
+ for record in orphaned_address_records:
203
+ if options.get("verbosity") > 1:
204
+ self.stdout.write(f"Removing orphaned address record '{record}'")
205
+ record.delete()
@@ -22,11 +22,12 @@ class Command(BaseCommand):
22
22
  )
23
23
 
24
24
  def handle(self, *model_names, **options):
25
- self.cleanup_rrset_ttl(**options)
25
+ self._cleanup_rrset_ttl(**options)
26
26
 
27
- self.stdout.write("RRSet cleanup completed.")
27
+ def _cleanup_rrset_ttl(self, **options):
28
+ if options.get("verbosity"):
29
+ self.stdout.write("Cleaning up diverging RRset TTL values")
28
30
 
29
- def cleanup_rrset_ttl(self, **options):
30
31
  ttl_records = (
31
32
  Record.objects.filter(ttl__isnull=False)
32
33
  .exclude(type=RecordTypeChoices.SOA)
@@ -37,11 +38,13 @@ class Command(BaseCommand):
37
38
  name=record.name,
38
39
  zone=record.zone,
39
40
  type=record.type,
40
- ).exclude(type=RecordTypeChoices.PTR, maanged=True)
41
+ ).exclude(type=RecordTypeChoices.PTR, managed=True)
41
42
 
42
43
  if records.count() == 1:
43
44
  if options.get("verbosity") > 2:
44
- self.stdout.write(f"Ignoring single record {record.pk} ({record})")
45
+ self.stdout.write(
46
+ f"Ignoring single record '{record.pk}' ('{record}')"
47
+ )
45
48
  continue
46
49
 
47
50
  if options.get("max"):
@@ -52,7 +55,10 @@ class Command(BaseCommand):
52
55
  for record in records.exclude(ttl=ttl):
53
56
  if options.get("verbosity") > 1:
54
57
  self.stdout.write(
55
- f"Updating TTL for record {record.pk} ({record}) to {ttl}"
58
+ f"Setting TTL for record '{record.pk}' ('{record}') to {ttl}"
56
59
  )
57
60
  record.ttl = ttl
58
61
  record.save(update_fields=["ttl"], update_rrset_ttl=False)
62
+
63
+ if options.get("verbosity"):
64
+ self.stdout.write("RRSet TTL cleanup completed.")
@@ -8,13 +8,6 @@ from netbox_dns.utilities import update_dns_records, get_zones
8
8
  class Command(BaseCommand):
9
9
  help = "Rebuild DNSsync relationships between IP addresses and records"
10
10
 
11
- def add_arguments(self, parser):
12
- parser.add_argument(
13
- "--force",
14
- action="store_true",
15
- help="Update records even if DNS name was not changed (required for rebuilding filtered views",
16
- )
17
-
18
11
  def handle(self, *model_names, **options):
19
12
  ip_addresses = IPAddress.objects.all()
20
13
  for ip_address in ip_addresses:
@@ -24,10 +17,7 @@ class Command(BaseCommand):
24
17
  )
25
18
  if options.get("verbosity") >= 3:
26
19
  self.stdout.write(f" Zones: {get_zones(ip_address)}")
27
- if (
28
- update_dns_records(ip_address, force=options.get("force"))
29
- and options.get("verbosity") >= 1
30
- ):
20
+ if update_dns_records(ip_address) and options.get("verbosity") >= 1:
31
21
  self.stdout.write(
32
22
  f"Updated DNS records for IP Address {ip_address}, VRF {ip_address.vrf}"
33
23
  )
@@ -0,0 +1,27 @@
1
+ # Generated by Django 5.2.3 on 2025-07-30 18:54
2
+
3
+ from django.db import migrations
4
+
5
+ from netbox_dns.choices import RecordTypeChoices
6
+
7
+
8
+ def set_disable_ptr_false(apps, schema_editor):
9
+ Record = apps.get_model("netbox_dns", "Record")
10
+
11
+ for record in Record.objects.exclude(
12
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
13
+ ):
14
+ if record.disable_ptr:
15
+ record.disable_ptr = False
16
+ record.save()
17
+
18
+
19
+ class Migration(migrations.Migration):
20
+
21
+ dependencies = [
22
+ ("netbox_dns", "0022_alter_record_ipam_ip_address"),
23
+ ]
24
+
25
+ operations = [
26
+ migrations.RunPython(set_disable_ptr_false),
27
+ ]
@@ -418,6 +418,26 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
418
418
  ):
419
419
  return
420
420
 
421
+ # +
422
+ # If the existing PTR record no longer matches the address record,
423
+ # check whether there is an existing PTR record that does. In that
424
+ # case, mark the old PTR record for cleanup and use the existing one.
425
+ # -
426
+ try:
427
+ existing_ptr_record = Record.objects.get(
428
+ name=ptr_name,
429
+ zone=ptr_zone,
430
+ type=RecordTypeChoices.PTR,
431
+ value=ptr_value,
432
+ )
433
+
434
+ self.cleanup_ptr_record = self.ptr_record
435
+ self.ptr_record = existing_ptr_record
436
+ ptr_record = self.ptr_record
437
+
438
+ except Record.DoesNotExist:
439
+ pass
440
+
421
441
  # +
422
442
  # If there is an RFC2317 CNAME for the PTR record and it is either
423
443
  # not required or needs to be changed, remove it.
@@ -435,10 +455,12 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
435
455
  # modified to match the new name, zone, value and TTL.
436
456
  # -
437
457
  if ptr_record.address_records.count() == 1:
458
+ ptr_record.snapshot()
438
459
  ptr_record.zone = ptr_zone
439
460
  ptr_record.name = ptr_name
440
461
  ptr_record.value = ptr_value
441
462
  ptr_record.ttl = self.ttl
463
+ ptr_record.managed = True
442
464
  ptr_record.save(
443
465
  update_rfc2317_cname=update_rfc2317_cname,
444
466
  save_zone_serial=save_zone_serial,
@@ -447,7 +469,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
447
469
 
448
470
  # +
449
471
  # Either there was no PTR record or the existing PTR record could not be re-used,
450
- # so we need to either get find a matching PTR record or create a new one.
472
+ # so we need to either find a matching PTR record or create a new one.
451
473
  # -
452
474
  try:
453
475
  ptr_record = Record.objects.get(
@@ -846,6 +868,9 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
846
868
  if self._state.adding:
847
869
  self.check_unique_rrset_ttl()
848
870
 
871
+ if not self.is_address_record:
872
+ self.disable_ptr = False
873
+
849
874
  if not self.is_active:
850
875
  return
851
876
 
netbox_dns/models/zone.py CHANGED
@@ -550,7 +550,12 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
550
550
  try:
551
551
  soa_record = self.records.get(type=RecordTypeChoices.SOA, name=soa_name)
552
552
 
553
- if soa_record.ttl != soa_ttl or soa_record.value != soa_rdata.to_text():
553
+ if (
554
+ soa_record.ttl != soa_ttl
555
+ or soa_record.value != soa_rdata.to_text()
556
+ or not soa_record.managed
557
+ ):
558
+ soa_record.snapshot()
554
559
  soa_record.ttl = soa_ttl
555
560
  soa_record.value = soa_rdata.to_text()
556
561
  soa_record.managed = True
@@ -177,6 +177,8 @@ def update_dns_records(ip_address, view=None, force=False):
177
177
  address_records = ip_address.netbox_dns_records.filter(zone__view=view)
178
178
 
179
179
  for record in address_records:
180
+ record.snapshot()
181
+
180
182
  if record.zone not in zones or ip_address.custom_field_data.get(
181
183
  "ipaddress_dns_disabled"
182
184
  ):
@@ -185,15 +187,14 @@ def update_dns_records(ip_address, view=None, force=False):
185
187
  continue
186
188
 
187
189
  record.update_fqdn()
188
- if not _match_data(ip_address, record) or force:
189
- updated, deleted = record.update_from_ip_address(ip_address)
190
-
191
- if deleted:
192
- record.delete()
193
- updated = True
194
- elif updated:
195
- record.save()
196
- updated = True
190
+ updated, deleted = record.update_from_ip_address(ip_address)
191
+
192
+ if deleted:
193
+ record.delete()
194
+ updated = True
195
+ elif updated:
196
+ record.save()
197
+ updated = True
197
198
 
198
199
  zones = Zone.objects.filter(pk__in=[zone.pk for zone in zones]).exclude(
199
200
  pk__in=set(ip_address.netbox_dns_records.values_list("zone", flat=True))
@@ -68,7 +68,9 @@ class RecordView(generic.ObjectView):
68
68
  value_fqdn = dns_name.from_text(instance.value_fqdn)
69
69
 
70
70
  cname_targets = Record.objects.filter(
71
- zone__view=instance.zone.view, fqdn=value_fqdn
71
+ zone__view=instance.zone.view,
72
+ fqdn=value_fqdn,
73
+ active=True,
72
74
  )
73
75
 
74
76
  if cname_targets:
@@ -98,6 +100,7 @@ class RecordView(generic.ObjectView):
98
100
  zone__view=instance.zone.view,
99
101
  value=instance.fqdn,
100
102
  type=RecordTypeChoices.CNAME,
103
+ active=True,
101
104
  )
102
105
  )
103
106
 
@@ -112,6 +115,7 @@ class RecordView(generic.ObjectView):
112
115
  zone__view=instance.zone.view,
113
116
  type=RecordTypeChoices.CNAME,
114
117
  zone=parent_zone,
118
+ active=True,
115
119
  )
116
120
  cname_records = cname_records.union(
117
121
  {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netbox-plugin-dns
3
- Version: 1.3.4
3
+ Version: 1.3.6
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
@@ -1,4 +1,4 @@
1
- netbox_dns/__init__.py,sha256=7cUgAlRJDPqry-F9FMUjy3q8pMPXMG4GQMeEIDpZmaY,4890
1
+ netbox_dns/__init__.py,sha256=xq8VZKxTI6bdiMeHJM-s2IPaZTbGczYbTTEy8B3174w,4890
2
2
  netbox_dns/apps.py,sha256=JCW5eS-AQBUubDJve1DjP-IRFKTFGQh1NLGWzJpC5MI,151
3
3
  netbox_dns/navigation.py,sha256=ZF2-bKRfuxXnLArSCvozyRXRd7GME14sVJZdmDEMhBk,7741
4
4
  netbox_dns/template_content.py,sha256=nwjbWkMc02vpTmcFQdiAA1TdopJiZ0MkRy6qa18_wLI,4848
@@ -74,12 +74,10 @@ netbox_dns/graphql/filters/zone_template.py,sha256=6ZxBN_VPXvBDGXXwcYlkX6wJXx_Il
74
74
  netbox_dns/locale/de/LC_MESSAGES/django.mo,sha256=fSlYDunygrkHE4TAIlHI0ol67Lz3qiu2hUkeirewlOQ,29995
75
75
  netbox_dns/locale/en/LC_MESSAGES/django.mo,sha256=GDnSZkfHs3yjtTsll7dksEEej4B50F8pc9RGytZNubM,393
76
76
  netbox_dns/locale/fr/LC_MESSAGES/django.mo,sha256=hZjbClaXZndP8VtqAiXWBdYEFVD9CQrKJXelL6kMOPE,30021
77
- netbox_dns/management/commands/cleanup_database.py,sha256=1-tAl0Sht80qaNZyfFyUW19Eh9gBUuc7GdbHN4aemGU,5935
78
- netbox_dns/management/commands/cleanup_rrset_ttl.py,sha256=UFRURLBcFeGHUS2lrYFv7UWIebjI72aG1EUQJt0XsXw,2046
79
- netbox_dns/management/commands/rebuild_dnssync.py,sha256=Tcl385u6kJTX47SvSyRzKm1RIx4nYRYCMcKr3uVnV60,1246
80
- netbox_dns/management/commands/remove_orphaned_ptr_records.py,sha256=vYYvI2yr4U1EiAoWm26PkULzaz3rr_Yfaw2eg9i4oIw,1142
77
+ netbox_dns/management/commands/cleanup_database.py,sha256=Dv1DCN55MzIHoQk3TBV-SmaNf_mFo-PbzCm7fOmZspY,7953
78
+ netbox_dns/management/commands/cleanup_rrset_ttl.py,sha256=7W4_qRzm_Crnb1L4X8lfrXRJanBqDGLC1yCLvrIaGG4,2256
79
+ netbox_dns/management/commands/rebuild_dnssync.py,sha256=Wnix38pzuC1AtGm9-xU8W8j7NYLlUIMpmw5mT2rhBYc,929
81
80
  netbox_dns/management/commands/setup_dnssync.py,sha256=qtVj6egSjclaQbuI60hLfl-zg89VJVbX-TB17f1k77Y,5730
82
- netbox_dns/management/commands/update_soa.py,sha256=Rj_Xk-qpwkAVRubVnM5OqSTwgzi93E0PqjwGb3rYjf0,660
83
81
  netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py,sha256=3U0810NWSHPu2dTSHpfzlleDgwMS04FhJ_CkO76SDaw,10283
84
82
  netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py,sha256=ML6Hp17lrXiaG0eUlBjKMm6HUNhw0AHPnKrb9AN-F6E,20279
85
83
  netbox_dns/migrations/0002_contact_description_registrar_description.py,sha256=ZrI-L3jJ5GzdVx21pomgM4waE-njixHQjl_grjsGr0I,583
@@ -107,6 +105,7 @@ netbox_dns/migrations/0021_record_ip_address.py,sha256=EqdhWXmq7aiK4X79xTRUZng3z
107
105
  netbox_dns/migrations/0022_alter_record_ipam_ip_address.py,sha256=KKmB3moxPJBKytOBymy0tS6ABIKjpNd5YY6cG--Lluk,727
108
106
  netbox_dns/migrations/0022_search.py,sha256=KW1ffEZ4-0dppGQ_KD1EN7iw8eQJOnDco-xfJFRZqKQ,172
109
107
  netbox_dns/migrations/0023_alter_record_value.py,sha256=4_4v8YZzU8_jadJqIUUjH6SIhNTeALWhclozTqYDmv0,378
108
+ netbox_dns/migrations/0023_disable_ptr_false.py,sha256=Wo-d60QmPCcvdVIVShF8L7z-L2eofJwWTIiyrr51bjU,652
110
109
  netbox_dns/migrations/0024_tenancy.py,sha256=3kc5l5_AyfhOI6g6mbCfReUAbSgb2DAv0MDMZqJ-3YQ,1745
111
110
  netbox_dns/migrations/0025_ipam_coupling_cf.py,sha256=7uHujclWrsYw5QMLWft0Po78Ow5Q8MjPuU7moKyQ2qs,620
112
111
  netbox_dns/migrations/0026_domain_registration.py,sha256=qUJ1oUGHIGGNWD7QRLnxElbM5eNp7dYNNn_OYIw8Xvo,5796
@@ -120,12 +119,12 @@ netbox_dns/models/__init__.py,sha256=CuwFENIVUv0FNMDlY18Am-mvN5kBGkPOGavCP0cle7c
120
119
  netbox_dns/models/dnssec_key_template.py,sha256=Nv0vjdkOFWMptRYR1sT60bM6D8n_SnCpPZhI7WE5_UQ,2588
121
120
  netbox_dns/models/dnssec_policy.py,sha256=REsE8p04bgJVF8yJuWuUITXpsZmvVlXWyQuJ9I6dEMs,5268
122
121
  netbox_dns/models/nameserver.py,sha256=oVfyc_iWRzxVE2tIhfRb1Vuj2gZmlfFFzEtXj9ZEr6s,3848
123
- netbox_dns/models/record.py,sha256=2HSxvroCGhvb7eg4qSXl1ACN7yzGGywbyBjhPR6siEk,31867
122
+ netbox_dns/models/record.py,sha256=7f4h3ngUvPpQ4IQroTJAWO8wD2fqy1u8j-LuA23PWtM,32761
124
123
  netbox_dns/models/record_template.py,sha256=Qr43_YZm1z3Od1cBdDY9wpNlV-UCzvpn2c6_dDzFzN8,5145
125
124
  netbox_dns/models/registrar.py,sha256=-ozazecvd-oryEoDlOUvTWhEQKKQp3my6YVTEzWlUuI,1747
126
125
  netbox_dns/models/registration_contact.py,sha256=9ehnTjg8KUrUYJKRRu2SaJX-NE5dO4wy90FRPlT2ys4,3620
127
126
  netbox_dns/models/view.py,sha256=pwo7i8gtukIRgAC1A4rm58jcEpIbsSW_IUq6vSv-mRo,4618
128
- netbox_dns/models/zone.py,sha256=8MB8p6R9K-5K8eR2AKZXb6rwnnWDvcd-_KFLi5JqviQ,35825
127
+ netbox_dns/models/zone.py,sha256=qZ5yYNbj4mYm61zfq-aFL_5sVSxJo1PQSMY4cAj8vEQ,35953
129
128
  netbox_dns/models/zone_template.py,sha256=ShPg6_ts6W-dpdGzUg3oZnGHEEQ-_Jf0EdYwVWzaPwI,5093
130
129
  netbox_dns/signals/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
130
  netbox_dns/signals/dnssec.py,sha256=o4MOEg6ftxoDWFAhDtajkXzb7Nb6KuUHjtx1zNu7C1w,1040
@@ -171,7 +170,7 @@ netbox_dns/templatetags/netbox_dns.py,sha256=DND1DMPzv636Rak3M6Hor_Vw6pjqUfSTquo
171
170
  netbox_dns/utilities/__init__.py,sha256=cSGf-nGaRWx9b-Xrh3dLMJYoWNsZ6FF-qdmV4F1uOgg,74
172
171
  netbox_dns/utilities/conversions.py,sha256=qYnzecmR28l8Je_H0vFvzJ2sikTiEiyxr6drl_aRocg,3016
173
172
  netbox_dns/utilities/dns.py,sha256=UBiyQe8thiOTnKOmU9e2iRHHnGF9toVLe4efU623kX4,322
174
- netbox_dns/utilities/ipam_dnssync.py,sha256=IB26jxdijjjkcRj5JTV2We3frqbfzBXhPb3xegRQg0w,10462
173
+ netbox_dns/utilities/ipam_dnssync.py,sha256=PZXnn2TIPhCMh9Mxjbl9LfP63w0lMPRzO1lNPDyYpVo,10404
175
174
  netbox_dns/validators/__init__.py,sha256=X0hPZlC3VZcXMcvXKZ2_5LSoEJdXPNSBr4QtEIFSBJ0,94
176
175
  netbox_dns/validators/dns_name.py,sha256=1MKnYAmkSTIQGf6zInqkpbIj5SCeCM0YGKmYOqFzUK4,3770
177
176
  netbox_dns/validators/dns_value.py,sha256=cADhgTohXAtOLPzaoMKO9DahEUiDanpdiuKonrwFw0E,5278
@@ -181,15 +180,15 @@ netbox_dns/views/__init__.py,sha256=tObkTOHw_6kVtEcwdyshN0Ql-8VGhwsgQw7owL_s2lI,
181
180
  netbox_dns/views/dnssec_key_template.py,sha256=06omBc2RCTltGH078mNLLwz3A_y9gqrtQ08ex1XEwlg,2694
182
181
  netbox_dns/views/dnssec_policy.py,sha256=ZvkCVfvI78w8e9c0m8lSWgRwg-jg07PM8Od0HwAVjGI,4427
183
182
  netbox_dns/views/nameserver.py,sha256=cLB0W1UnnvEmYdoCYH5HmjrFhbEZ1gWxJTKdMS-wuh0,3564
184
- netbox_dns/views/record.py,sha256=cPvsc20EUFcVidQ9YGIdsSTLHZKYzZD3JcV9bFv7iak,7123
183
+ netbox_dns/views/record.py,sha256=eAHMxsd2xKL9Yc_lijSC28RkvDnOolh-tdYLxb0d9aA,7219
185
184
  netbox_dns/views/record_template.py,sha256=Cye1rjlpAewRgIv7QGD7o5n-knjzqjEUJzZHVxtGX4s,3041
186
185
  netbox_dns/views/registrar.py,sha256=gYpMyz3rRJDmBfEeRfVENvR6fdWXN1y0XbN4JBlXoHc,2625
187
186
  netbox_dns/views/registration_contact.py,sha256=5bJWjNBisqCkBo6d2TJyyBJlc95WM7VcSA6wsEB184k,3383
188
187
  netbox_dns/views/view.py,sha256=xLXt7sKrda3FpNXsBSJk8L8P2XhZ1sVb5OOXovCsKEU,3089
189
188
  netbox_dns/views/zone.py,sha256=rxf0ETFnBF88JbhxUZWtcid_CAm7tssYfp2EFjk7zyg,7160
190
189
  netbox_dns/views/zone_template.py,sha256=5P9DT3XBRL-TiM5zFhBTMlMusL4bP2jTu3GHxKz5ojc,2553
191
- netbox_plugin_dns-1.3.4.dist-info/licenses/LICENSE,sha256=I3tDu11bZfhFm3EkV4zOD5TmWgLjnUNLEFwrdjniZYs,1112
192
- netbox_plugin_dns-1.3.4.dist-info/METADATA,sha256=wbc1V3I53MwepXrnhT2D4Q1v39PpOccje8VlP6DjKqw,7787
193
- netbox_plugin_dns-1.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
194
- netbox_plugin_dns-1.3.4.dist-info/top_level.txt,sha256=sA1Rwl1mRKvMC6XHe2ylZ1GF-Q1NGd08XedK9Y4xZc4,11
195
- netbox_plugin_dns-1.3.4.dist-info/RECORD,,
190
+ netbox_plugin_dns-1.3.6.dist-info/licenses/LICENSE,sha256=I3tDu11bZfhFm3EkV4zOD5TmWgLjnUNLEFwrdjniZYs,1112
191
+ netbox_plugin_dns-1.3.6.dist-info/METADATA,sha256=cOlM0ppA8UzYmjsx5LD8j-tPLRr6TthsafOgcDh1w0w,7787
192
+ netbox_plugin_dns-1.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
193
+ netbox_plugin_dns-1.3.6.dist-info/top_level.txt,sha256=sA1Rwl1mRKvMC6XHe2ylZ1GF-Q1NGd08XedK9Y4xZc4,11
194
+ netbox_plugin_dns-1.3.6.dist-info/RECORD,,
@@ -1,35 +0,0 @@
1
- from django.core.management.base import BaseCommand
2
-
3
- from netbox_dns.models import Record
4
- from netbox_dns.choices import RecordTypeChoices
5
-
6
-
7
- class Command(BaseCommand):
8
- help = "Remove managed PTR records without an address record"
9
-
10
- def handle(self, *model_names, **options):
11
- orphaned_ptr_records = Record.objects.filter(
12
- type=RecordTypeChoices.PTR,
13
- address_records__isnull=True,
14
- managed=True,
15
- )
16
-
17
- if not orphaned_ptr_records.exists():
18
- if options.get("verbosity") >= 1:
19
- self.stdout.write("No orphaned PTR records found")
20
- return
21
-
22
- if options.get("verbosity") >= 1:
23
- self.stdout.write(
24
- f"Removing {orphaned_ptr_records.count()} orphaned PTR record(s) ..."
25
- )
26
-
27
- for record in orphaned_ptr_records:
28
- if options.get("verbosity") >= 2:
29
- self.stdout.write(
30
- f"removing PTR record {record} from zone {record.zone}"
31
- )
32
- record.delete()
33
-
34
- if options.get("verbosity") >= 1:
35
- self.stdout.write("... done.")
@@ -1,22 +0,0 @@
1
- from django.core.management.base import BaseCommand
2
-
3
- from netbox_dns.models import Zone
4
-
5
-
6
- class Command(BaseCommand):
7
- help = "Create or update SOA records for all zones"
8
-
9
- def add_arguments(self, parser):
10
- parser.add_argument(
11
- "--verbose", action="store_true", help="Increase output verbosity"
12
- )
13
-
14
- def handle(self, *model_names, **options):
15
- zones = Zone.objects.all()
16
-
17
- for zone in zones:
18
- if options["verbose"]:
19
- self.stdout.write(f"Updating the SOA record for zone {zone.name}")
20
- zone.update_soa_record()
21
-
22
- self.stdout.write("All SOA records have been updated")