netbox-plugin-dns 0.22.4__py3-none-any.whl → 0.22.5__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 +3 -2
- netbox_dns/api/serializers.py +1 -0
- netbox_dns/filters/registrar.py +1 -0
- netbox_dns/forms/registrar.py +11 -1
- netbox_dns/forms/zone.py +31 -21
- netbox_dns/management/commands/cleanup_rrset_ttl.py +62 -0
- netbox_dns/models/record.py +141 -25
- netbox_dns/models/zone.py +82 -18
- netbox_dns/templates/netbox_dns/registrar.html +4 -0
- netbox_dns/templates/netbox_dns/zone.html +7 -0
- {netbox_plugin_dns-0.22.4.dist-info → netbox_plugin_dns-0.22.5.dist-info}/METADATA +11 -11
- {netbox_plugin_dns-0.22.4.dist-info → netbox_plugin_dns-0.22.5.dist-info}/RECORD +14 -13
- {netbox_plugin_dns-0.22.4.dist-info → netbox_plugin_dns-0.22.5.dist-info}/LICENSE +0 -0
- {netbox_plugin_dns-0.22.4.dist-info → netbox_plugin_dns-0.22.5.dist-info}/WHEEL +0 -0
netbox_dns/__init__.py
CHANGED
|
@@ -10,7 +10,7 @@ except ImportError:
|
|
|
10
10
|
# NetBox 3.5.8
|
|
11
11
|
from extras.plugins.utils import get_plugin_config
|
|
12
12
|
|
|
13
|
-
__version__ = "0.22.
|
|
13
|
+
__version__ = "0.22.5"
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class DNSConfig(PluginConfig):
|
|
@@ -38,7 +38,8 @@ class DNSConfig(PluginConfig):
|
|
|
38
38
|
],
|
|
39
39
|
"tolerate_non_rfc1035_types": [],
|
|
40
40
|
"enable_root_zones": False,
|
|
41
|
-
"enforce_unique_records":
|
|
41
|
+
"enforce_unique_records": True,
|
|
42
|
+
"enforce_unique_rrset_ttl": True,
|
|
42
43
|
}
|
|
43
44
|
base_url = "netbox-dns"
|
|
44
45
|
|
netbox_dns/api/serializers.py
CHANGED
netbox_dns/filters/registrar.py
CHANGED
netbox_dns/forms/registrar.py
CHANGED
|
@@ -17,6 +17,7 @@ class RegistrarForm(NetBoxModelForm):
|
|
|
17
17
|
fields = (
|
|
18
18
|
"name",
|
|
19
19
|
"iana_id",
|
|
20
|
+
"address",
|
|
20
21
|
"referral_url",
|
|
21
22
|
"whois_server",
|
|
22
23
|
"abuse_email",
|
|
@@ -29,12 +30,18 @@ class RegistrarFilterForm(NetBoxModelFilterSetForm):
|
|
|
29
30
|
model = Registrar
|
|
30
31
|
fieldsets = (
|
|
31
32
|
(None, ("q", "name", "iana_id", "tags")),
|
|
32
|
-
(
|
|
33
|
+
(
|
|
34
|
+
"Contact",
|
|
35
|
+
("address", "referral_url", "whois_server", "abuse_email", "abuse_phone"),
|
|
36
|
+
),
|
|
33
37
|
)
|
|
34
38
|
|
|
35
39
|
name = forms.CharField(
|
|
36
40
|
required=False,
|
|
37
41
|
)
|
|
42
|
+
address = forms.CharField(
|
|
43
|
+
required=False,
|
|
44
|
+
)
|
|
38
45
|
iana_id = forms.IntegerField(
|
|
39
46
|
required=False,
|
|
40
47
|
label="IANA ID",
|
|
@@ -64,6 +71,7 @@ class RegistrarImportForm(NetBoxModelImportForm):
|
|
|
64
71
|
fields = (
|
|
65
72
|
"name",
|
|
66
73
|
"iana_id",
|
|
74
|
+
"address",
|
|
67
75
|
"referral_url",
|
|
68
76
|
"whois_server",
|
|
69
77
|
"abuse_email",
|
|
@@ -96,6 +104,7 @@ class RegistrarBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
96
104
|
(
|
|
97
105
|
None,
|
|
98
106
|
(
|
|
107
|
+
"address",
|
|
99
108
|
"referral_url",
|
|
100
109
|
"whois_server",
|
|
101
110
|
"abuse_email",
|
|
@@ -105,6 +114,7 @@ class RegistrarBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
105
114
|
)
|
|
106
115
|
|
|
107
116
|
nullable_fields = (
|
|
117
|
+
"address",
|
|
108
118
|
"referral_url",
|
|
109
119
|
"whois_server",
|
|
110
120
|
"abuse_email",
|
netbox_dns/forms/zone.py
CHANGED
|
@@ -315,7 +315,7 @@ class ZoneImportForm(NetBoxModelImportForm):
|
|
|
315
315
|
required=False,
|
|
316
316
|
help_text="Mailbox of the zone's administrator",
|
|
317
317
|
)
|
|
318
|
-
soa_serial_auto = forms.
|
|
318
|
+
soa_serial_auto = forms.NullBooleanField(
|
|
319
319
|
required=False,
|
|
320
320
|
help_text="Generate the SOA serial",
|
|
321
321
|
)
|
|
@@ -443,26 +443,6 @@ class ZoneImportForm(NetBoxModelImportForm):
|
|
|
443
443
|
def clean_soa_rname(self):
|
|
444
444
|
return self._clean_field_with_defaults("soa_rname")
|
|
445
445
|
|
|
446
|
-
def clean_soa_serial_auto(self):
|
|
447
|
-
try:
|
|
448
|
-
return self._clean_field_with_defaults("soa_serial_auto")
|
|
449
|
-
except ValidationError:
|
|
450
|
-
if self.cleaned_data["soa_serial"] or self._get_default_value("soa_serial"):
|
|
451
|
-
return None
|
|
452
|
-
|
|
453
|
-
raise
|
|
454
|
-
|
|
455
|
-
def clean_soa_serial(self):
|
|
456
|
-
try:
|
|
457
|
-
return self._clean_field_with_defaults("soa_serial")
|
|
458
|
-
except ValidationError:
|
|
459
|
-
if self.cleaned_data["soa_serial_auto"] or self._get_default_value(
|
|
460
|
-
"soa_serial_auto"
|
|
461
|
-
):
|
|
462
|
-
return None
|
|
463
|
-
|
|
464
|
-
raise
|
|
465
|
-
|
|
466
446
|
def clean_soa_refresh(self):
|
|
467
447
|
return self._clean_field_with_defaults("soa_refresh")
|
|
468
448
|
|
|
@@ -475,6 +455,36 @@ class ZoneImportForm(NetBoxModelImportForm):
|
|
|
475
455
|
def clean_soa_minimum(self):
|
|
476
456
|
return self._clean_field_with_defaults("soa_minimum")
|
|
477
457
|
|
|
458
|
+
def clean(self, *args, **kwargs):
|
|
459
|
+
super().clean(*args, **kwargs)
|
|
460
|
+
|
|
461
|
+
soa_serial_auto = self.cleaned_data.get("soa_serial_auto")
|
|
462
|
+
soa_serial = self.cleaned_data.get("soa_serial")
|
|
463
|
+
|
|
464
|
+
if soa_serial is None:
|
|
465
|
+
soa_serial = self._get_default_value("soa_serial")
|
|
466
|
+
|
|
467
|
+
if soa_serial_auto is None:
|
|
468
|
+
if self._get_default_value("soa_serial_auto") is not None:
|
|
469
|
+
soa_serial_auto = self._get_default_value("soa_serial_auto")
|
|
470
|
+
|
|
471
|
+
elif soa_serial is not None:
|
|
472
|
+
soa_serial_auto = False
|
|
473
|
+
|
|
474
|
+
else:
|
|
475
|
+
raise ValidationError(
|
|
476
|
+
"SOA Serial Auto not set and no default value and SOA Serial available"
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
if "soa_serial_auto" in self.cleaned_data:
|
|
480
|
+
self.cleaned_data["soa_serial_auto"] = soa_serial_auto
|
|
481
|
+
|
|
482
|
+
if "soa_serial" in self.cleaned_data:
|
|
483
|
+
if soa_serial_auto:
|
|
484
|
+
self.cleaned_data["soa_serial"] = None
|
|
485
|
+
else:
|
|
486
|
+
self.cleaned_data["soa_serial"] = soa_serial
|
|
487
|
+
|
|
478
488
|
class Meta:
|
|
479
489
|
model = Zone
|
|
480
490
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from django.core.management.base import BaseCommand
|
|
2
|
+
from django.db.models import Max, Min
|
|
3
|
+
|
|
4
|
+
from netbox_dns.models import (
|
|
5
|
+
Record,
|
|
6
|
+
RecordTypeChoices,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Command(BaseCommand):
|
|
11
|
+
help = "Clean up the TTLs for RRSets"
|
|
12
|
+
|
|
13
|
+
def add_arguments(self, parser):
|
|
14
|
+
min_max = parser.add_mutually_exclusive_group()
|
|
15
|
+
min_max.add_argument(
|
|
16
|
+
"--min",
|
|
17
|
+
action="store_true",
|
|
18
|
+
help="Use the minimum TTL of an RRSet for all Records",
|
|
19
|
+
)
|
|
20
|
+
min_max.add_argument(
|
|
21
|
+
"--max",
|
|
22
|
+
action="store_true",
|
|
23
|
+
help="Use the maximum TTL of an RRSet for all Records",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def handle(self, *model_names, **options):
|
|
27
|
+
self.cleanup_rrset_ttl(**options)
|
|
28
|
+
|
|
29
|
+
self.stdout.write("RRSet cleanup completed.")
|
|
30
|
+
|
|
31
|
+
def cleanup_rrset_ttl(self, **options):
|
|
32
|
+
verbose = options.get("verbosity") > 1
|
|
33
|
+
|
|
34
|
+
ttl_records = (
|
|
35
|
+
Record.objects.filter(ttl__isnull=False)
|
|
36
|
+
.exclude(type=RecordTypeChoices.SOA)
|
|
37
|
+
.exclude(type=RecordTypeChoices.PTR, maanged=True)
|
|
38
|
+
)
|
|
39
|
+
for record in ttl_records:
|
|
40
|
+
records = Record.objects.filter(
|
|
41
|
+
name=record.name,
|
|
42
|
+
zone=record.zone,
|
|
43
|
+
type=record.type,
|
|
44
|
+
).exclude(type=RecordTypeChoices.PTR, maanged=True)
|
|
45
|
+
|
|
46
|
+
if records.count() == 1:
|
|
47
|
+
if options.get("verbosity") > 2:
|
|
48
|
+
self.stdout.write(f"Ignoring single record {record.id} ({record})")
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
if options.get("max"):
|
|
52
|
+
ttl = records.aggregate(Max("ttl")).get("ttl__max")
|
|
53
|
+
else:
|
|
54
|
+
ttl = records.aggregate(Min("ttl")).get("ttl__min")
|
|
55
|
+
|
|
56
|
+
for record in records.exclude(ttl=ttl):
|
|
57
|
+
if options.get("verbosity") > 1:
|
|
58
|
+
self.stdout.write(
|
|
59
|
+
f"Updating TTL for record {record.id} ({record}) to {ttl}"
|
|
60
|
+
)
|
|
61
|
+
record.ttl = ttl
|
|
62
|
+
record.save(update_fields=["ttl"], update_rrset_ttl=False)
|
netbox_dns/models/record.py
CHANGED
|
@@ -6,7 +6,7 @@ from dns import name as dns_name
|
|
|
6
6
|
|
|
7
7
|
from django.core.exceptions import ValidationError
|
|
8
8
|
from django.db import transaction, models
|
|
9
|
-
from django.db.models import Q, ExpressionWrapper, BooleanField
|
|
9
|
+
from django.db.models import Q, ExpressionWrapper, BooleanField, Min
|
|
10
10
|
from django.db.models.functions import Length
|
|
11
11
|
from django.urls import reverse
|
|
12
12
|
|
|
@@ -38,6 +38,10 @@ from netbox_dns.validators import (
|
|
|
38
38
|
import netbox_dns.models.zone as zone
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
def min_ttl(*ttl_list):
|
|
42
|
+
return min((ttl for ttl in ttl_list if ttl is not None), default=None)
|
|
43
|
+
|
|
44
|
+
|
|
41
45
|
class RecordManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
42
46
|
"""Special Manager for records providing the activity status annotation"""
|
|
43
47
|
|
|
@@ -207,7 +211,8 @@ class Record(NetBoxModel):
|
|
|
207
211
|
try:
|
|
208
212
|
name = (
|
|
209
213
|
dns_name.from_text(
|
|
210
|
-
|
|
214
|
+
str(self.name),
|
|
215
|
+
origin=dns_name.from_text(self.zone.name, origin=None),
|
|
211
216
|
)
|
|
212
217
|
.relativize(dns_name.root)
|
|
213
218
|
.to_unicode()
|
|
@@ -309,7 +314,7 @@ class Record(NetBoxModel):
|
|
|
309
314
|
|
|
310
315
|
return ptr_zone
|
|
311
316
|
|
|
312
|
-
def update_ptr_record(self, update_rfc2317_cname=True):
|
|
317
|
+
def update_ptr_record(self, update_rfc2317_cname=True, save_zone_serial=True):
|
|
313
318
|
ptr_zone = self.ptr_zone
|
|
314
319
|
|
|
315
320
|
if (
|
|
@@ -339,14 +344,16 @@ class Record(NetBoxModel):
|
|
|
339
344
|
not ptr_record.zone.is_rfc2317_zone
|
|
340
345
|
and ptr_record.rfc2317_cname_record is not None
|
|
341
346
|
):
|
|
342
|
-
ptr_record.rfc2317_cname_record.delete(
|
|
347
|
+
ptr_record.rfc2317_cname_record.delete(
|
|
348
|
+
save_zone_serial=save_zone_serial
|
|
349
|
+
)
|
|
343
350
|
|
|
344
351
|
with transaction.atomic():
|
|
345
352
|
if ptr_record is not None:
|
|
346
353
|
if ptr_record.zone.pk != ptr_zone.pk:
|
|
347
354
|
if ptr_record.rfc2317_cname_record is not None:
|
|
348
355
|
ptr_record.rfc2317_cname_record.delete()
|
|
349
|
-
ptr_record.delete()
|
|
356
|
+
ptr_record.delete(save_zone_serial=save_zone_serial)
|
|
350
357
|
ptr_record = None
|
|
351
358
|
|
|
352
359
|
else:
|
|
@@ -358,7 +365,7 @@ class Record(NetBoxModel):
|
|
|
358
365
|
ptr_record.name = ptr_name
|
|
359
366
|
ptr_record.value = ptr_value
|
|
360
367
|
ptr_record.ttl = self.ttl
|
|
361
|
-
ptr_record.save()
|
|
368
|
+
ptr_record.save(save_zone_serial=save_zone_serial)
|
|
362
369
|
|
|
363
370
|
if ptr_record is None:
|
|
364
371
|
ptr_record = Record(
|
|
@@ -369,11 +376,14 @@ class Record(NetBoxModel):
|
|
|
369
376
|
value=ptr_value,
|
|
370
377
|
managed=True,
|
|
371
378
|
)
|
|
372
|
-
ptr_record.save(
|
|
379
|
+
ptr_record.save(
|
|
380
|
+
update_rfc2317_cname=update_rfc2317_cname,
|
|
381
|
+
save_zone_serial=save_zone_serial,
|
|
382
|
+
)
|
|
373
383
|
|
|
374
384
|
self.ptr_record = ptr_record
|
|
375
385
|
|
|
376
|
-
def update_rfc2317_cname_record(self):
|
|
386
|
+
def update_rfc2317_cname_record(self, save_zone_serial=True):
|
|
377
387
|
if self.zone.rfc2317_parent_managed:
|
|
378
388
|
cname_name = dns_name.from_text(
|
|
379
389
|
ipaddress.ip_address(self.ip_address).reverse_pointer
|
|
@@ -383,7 +393,13 @@ class Record(NetBoxModel):
|
|
|
383
393
|
self.rfc2317_cname_record.name = cname_name
|
|
384
394
|
self.rfc2317_cname_record.zone = self.zone.rfc2317_parent_zone
|
|
385
395
|
self.rfc2317_cname_record.value = self.fqdn
|
|
386
|
-
self.rfc2317_cname_record.
|
|
396
|
+
self.rfc2317_cname_record.ttl = min_ttl(
|
|
397
|
+
self.rfc2317_cname_record.rfc2317_ptr_records.exclude(pk=self.pk)
|
|
398
|
+
.aggregate(Min("ttl"))
|
|
399
|
+
.get("ttl__min"),
|
|
400
|
+
self.ttl,
|
|
401
|
+
)
|
|
402
|
+
self.rfc2317_cname_record.save(save_zone_serial=save_zone_serial)
|
|
387
403
|
else:
|
|
388
404
|
rfc2317_cname_record = Record.objects.filter(
|
|
389
405
|
name=cname_name,
|
|
@@ -392,20 +408,34 @@ class Record(NetBoxModel):
|
|
|
392
408
|
managed=True,
|
|
393
409
|
value=self.fqdn,
|
|
394
410
|
).first()
|
|
395
|
-
|
|
396
|
-
|
|
411
|
+
|
|
412
|
+
if rfc2317_cname_record is not None:
|
|
413
|
+
rfc2317_cname_record.ttl = min_ttl(
|
|
414
|
+
rfc2317_cname_record.rfc2317_ptr_records.exclude(pk=self.pk)
|
|
415
|
+
.aggregate(Min("ttl"))
|
|
416
|
+
.get("ttl__min"),
|
|
417
|
+
self.ttl,
|
|
418
|
+
)
|
|
419
|
+
rfc2317_cname_record.save(
|
|
420
|
+
update_fields=["ttl"], save_zone_serial=save_zone_serial
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
else:
|
|
424
|
+
rfc2317_cname_record = Record(
|
|
397
425
|
name=cname_name,
|
|
398
426
|
type=RecordTypeChoices.CNAME,
|
|
399
427
|
zone=self.zone.rfc2317_parent_zone,
|
|
400
428
|
managed=True,
|
|
401
429
|
value=self.fqdn,
|
|
430
|
+
ttl=self.ttl,
|
|
402
431
|
)
|
|
432
|
+
rfc2317_cname_record.save(save_zone_serial=save_zone_serial)
|
|
403
433
|
|
|
404
434
|
self.rfc2317_cname_record = rfc2317_cname_record
|
|
405
435
|
|
|
406
436
|
else:
|
|
407
437
|
if self.rfc2317_cname_record is not None:
|
|
408
|
-
self.rfc2317_cname_record.delete()
|
|
438
|
+
self.rfc2317_cname_record.delete(save_zone_serial=save_zone_serial)
|
|
409
439
|
self.rfc2317_cname_record = None
|
|
410
440
|
|
|
411
441
|
def validate_name(self):
|
|
@@ -475,7 +505,7 @@ class Record(NetBoxModel):
|
|
|
475
505
|
}
|
|
476
506
|
) from None
|
|
477
507
|
|
|
478
|
-
def
|
|
508
|
+
def check_unique_record(self):
|
|
479
509
|
if not get_plugin_config("netbox_dns", "enforce_unique_records", False):
|
|
480
510
|
return
|
|
481
511
|
|
|
@@ -489,6 +519,10 @@ class Record(NetBoxModel):
|
|
|
489
519
|
value=self.value,
|
|
490
520
|
status__in=Record.ACTIVE_STATUS_LIST,
|
|
491
521
|
)
|
|
522
|
+
|
|
523
|
+
if self.pk is not None:
|
|
524
|
+
records = records.exclude(pk=self.pk)
|
|
525
|
+
|
|
492
526
|
if len(records):
|
|
493
527
|
raise ValidationError(
|
|
494
528
|
{
|
|
@@ -496,6 +530,64 @@ class Record(NetBoxModel):
|
|
|
496
530
|
}
|
|
497
531
|
) from None
|
|
498
532
|
|
|
533
|
+
def check_unique_rrset_ttl(self):
|
|
534
|
+
if self.pk is not None:
|
|
535
|
+
return
|
|
536
|
+
|
|
537
|
+
if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
|
|
538
|
+
return
|
|
539
|
+
|
|
540
|
+
if self.type == RecordTypeChoices.PTR and self.managed:
|
|
541
|
+
return
|
|
542
|
+
|
|
543
|
+
records = (
|
|
544
|
+
Record.objects.filter(
|
|
545
|
+
zone=self.zone,
|
|
546
|
+
name=self.name,
|
|
547
|
+
type=self.type,
|
|
548
|
+
)
|
|
549
|
+
.exclude(ttl=self.ttl)
|
|
550
|
+
.exclude(type=RecordTypeChoices.PTR, managed=True)
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
if not records.exists():
|
|
554
|
+
return
|
|
555
|
+
|
|
556
|
+
conflicting_ttls = ", ".join(set(str(record.ttl) for record in records))
|
|
557
|
+
raise ValidationError(
|
|
558
|
+
{
|
|
559
|
+
"ttl": f"There is at least one active {self.type} record for name {self.name} in zone {self.zone} and TTL is different ({conflicting_ttls})."
|
|
560
|
+
}
|
|
561
|
+
) from None
|
|
562
|
+
|
|
563
|
+
def update_rrset_ttl(self, ttl=None):
|
|
564
|
+
if self.pk is None:
|
|
565
|
+
return
|
|
566
|
+
|
|
567
|
+
if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
|
|
568
|
+
return
|
|
569
|
+
|
|
570
|
+
if self.type == RecordTypeChoices.PTR and self.managed:
|
|
571
|
+
return
|
|
572
|
+
|
|
573
|
+
if ttl is None:
|
|
574
|
+
ttl = self.ttl
|
|
575
|
+
|
|
576
|
+
records = (
|
|
577
|
+
Record.objects.filter(
|
|
578
|
+
zone=self.zone,
|
|
579
|
+
name=self.name,
|
|
580
|
+
type=self.type,
|
|
581
|
+
)
|
|
582
|
+
.exclude(pk=self.pk)
|
|
583
|
+
.exclude(ttl=ttl)
|
|
584
|
+
.exclude(type=RecordTypeChoices.PTR, managed=True)
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
for record in records:
|
|
588
|
+
record.ttl = ttl
|
|
589
|
+
record.save(update_fields=["ttl"], update_rrset_ttl=False)
|
|
590
|
+
|
|
499
591
|
def clean_fields(self, *args, **kwargs):
|
|
500
592
|
self.type = self.type.upper()
|
|
501
593
|
super().clean_fields(*args, **kwargs)
|
|
@@ -503,7 +595,9 @@ class Record(NetBoxModel):
|
|
|
503
595
|
def clean(self, *args, **kwargs):
|
|
504
596
|
self.validate_name()
|
|
505
597
|
self.validate_value()
|
|
506
|
-
self.
|
|
598
|
+
self.check_unique_record()
|
|
599
|
+
if self.pk is None:
|
|
600
|
+
self.check_unique_rrset_ttl()
|
|
507
601
|
|
|
508
602
|
if not self.is_active:
|
|
509
603
|
return
|
|
@@ -578,14 +672,24 @@ class Record(NetBoxModel):
|
|
|
578
672
|
}
|
|
579
673
|
) from None
|
|
580
674
|
|
|
581
|
-
def save(
|
|
675
|
+
def save(
|
|
676
|
+
self,
|
|
677
|
+
*args,
|
|
678
|
+
update_rfc2317_cname=True,
|
|
679
|
+
save_zone_serial=True,
|
|
680
|
+
update_rrset_ttl=True,
|
|
681
|
+
**kwargs,
|
|
682
|
+
):
|
|
582
683
|
self.full_clean()
|
|
583
684
|
|
|
685
|
+
if self.pk is not None and update_rrset_ttl:
|
|
686
|
+
self.update_rrset_ttl()
|
|
687
|
+
|
|
584
688
|
if self.is_ptr_record:
|
|
585
689
|
if self.zone.is_rfc2317_zone:
|
|
586
690
|
self.ip_address = self.address_from_rfc2317_name
|
|
587
691
|
if update_rfc2317_cname:
|
|
588
|
-
self.update_rfc2317_cname_record()
|
|
692
|
+
self.update_rfc2317_cname_record(save_zone_serial=save_zone_serial)
|
|
589
693
|
else:
|
|
590
694
|
self.ip_address = self.address_from_name
|
|
591
695
|
|
|
@@ -595,7 +699,10 @@ class Record(NetBoxModel):
|
|
|
595
699
|
self.ip_address = None
|
|
596
700
|
|
|
597
701
|
if self.is_address_record:
|
|
598
|
-
self.update_ptr_record(
|
|
702
|
+
self.update_ptr_record(
|
|
703
|
+
update_rfc2317_cname=update_rfc2317_cname,
|
|
704
|
+
save_zone_serial=save_zone_serial,
|
|
705
|
+
)
|
|
599
706
|
elif self.ptr_record is not None:
|
|
600
707
|
self.ptr_record.delete()
|
|
601
708
|
self.ptr_record = None
|
|
@@ -604,15 +711,24 @@ class Record(NetBoxModel):
|
|
|
604
711
|
|
|
605
712
|
zone = self.zone
|
|
606
713
|
if self.type != RecordTypeChoices.SOA and zone.soa_serial_auto:
|
|
607
|
-
zone.update_serial()
|
|
714
|
+
zone.update_serial(save_zone_serial=save_zone_serial)
|
|
608
715
|
|
|
609
|
-
def delete(self, *args, **kwargs):
|
|
716
|
+
def delete(self, *args, save_zone_serial=True, **kwargs):
|
|
610
717
|
if self.rfc2317_cname_record:
|
|
611
|
-
if
|
|
612
|
-
self.rfc2317_cname_record.
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
718
|
+
if self.rfc2317_cname_record.pk:
|
|
719
|
+
if self.rfc2317_cname_record.rfc2317_ptr_records.count() == 1:
|
|
720
|
+
self.rfc2317_cname_record.delete()
|
|
721
|
+
else:
|
|
722
|
+
self.rfc2317_cname_record.ttl = (
|
|
723
|
+
self.rfc2317_cname_record.rfc2317_ptr_records.exclude(
|
|
724
|
+
pk=self.pk
|
|
725
|
+
)
|
|
726
|
+
.aggregate(Min("ttl"))
|
|
727
|
+
.get("ttl__min")
|
|
728
|
+
)
|
|
729
|
+
self.rfc2317_cname_record.save(
|
|
730
|
+
update_fields=["ttl"], save_zone_serial=save_zone_serial
|
|
731
|
+
)
|
|
616
732
|
|
|
617
733
|
if self.ptr_record:
|
|
618
734
|
self.ptr_record.delete()
|
|
@@ -621,7 +737,7 @@ class Record(NetBoxModel):
|
|
|
621
737
|
|
|
622
738
|
zone = self.zone
|
|
623
739
|
if zone.soa_serial_auto:
|
|
624
|
-
zone.update_serial()
|
|
740
|
+
zone.update_serial(save_zone_serial=save_zone_serial)
|
|
625
741
|
|
|
626
742
|
|
|
627
743
|
@register_search
|
netbox_dns/models/zone.py
CHANGED
|
@@ -249,6 +249,8 @@ class Zone(NetBoxModel):
|
|
|
249
249
|
null=True,
|
|
250
250
|
)
|
|
251
251
|
|
|
252
|
+
soa_serial_dirty = False
|
|
253
|
+
|
|
252
254
|
objects = ZoneManager()
|
|
253
255
|
|
|
254
256
|
clone_fields = [
|
|
@@ -470,11 +472,24 @@ class Zone(NetBoxModel):
|
|
|
470
472
|
|
|
471
473
|
return soa_serial
|
|
472
474
|
|
|
473
|
-
def update_serial(self):
|
|
475
|
+
def update_serial(self, save_zone_serial=True):
|
|
476
|
+
if not self.soa_serial_auto:
|
|
477
|
+
return
|
|
478
|
+
|
|
474
479
|
self.last_updated = datetime.now()
|
|
475
480
|
self.soa_serial = ceil(datetime.now().timestamp())
|
|
476
|
-
|
|
477
|
-
|
|
481
|
+
|
|
482
|
+
if save_zone_serial:
|
|
483
|
+
super().save(update_fields=["soa_serial", "last_updated"])
|
|
484
|
+
self.soa_serial_dirty = False
|
|
485
|
+
self.update_soa_record()
|
|
486
|
+
else:
|
|
487
|
+
self.soa_serial_dirty = True
|
|
488
|
+
|
|
489
|
+
def save_soa_serial(self):
|
|
490
|
+
if self.soa_serial_auto and self.soa_serial_dirty:
|
|
491
|
+
super().save(update_fields=["soa_serial", "last_updated"])
|
|
492
|
+
self.soa_serial_dirty = False
|
|
478
493
|
|
|
479
494
|
@property
|
|
480
495
|
def network_from_name(self):
|
|
@@ -503,28 +518,45 @@ class Zone(NetBoxModel):
|
|
|
503
518
|
if rfc2317_parent_zone is None:
|
|
504
519
|
self.rfc2317_parent_managed = False
|
|
505
520
|
self.rfc2317_parent_zone = None
|
|
506
|
-
self.save(
|
|
521
|
+
self.save(
|
|
522
|
+
update_fields=["rfc2317_parent_zone", "rfc2317_parent_managed"]
|
|
523
|
+
)
|
|
507
524
|
|
|
508
525
|
elif self.rfc2317_parent_zone != rfc2317_parent_zone:
|
|
509
526
|
self.rfc2317_parent_zone = rfc2317_parent_zone
|
|
510
|
-
self.save()
|
|
527
|
+
self.save(update_fields=["rfc2317_parent_zone"])
|
|
511
528
|
|
|
512
|
-
ptr_records = self.record_set.filter(
|
|
529
|
+
ptr_records = self.record_set.filter(
|
|
530
|
+
type=record.RecordTypeChoices.PTR
|
|
531
|
+
).prefetch_related("zone", "rfc2317_cname_record")
|
|
532
|
+
ptr_zones = {ptr_record.zone for ptr_record in ptr_records}
|
|
513
533
|
|
|
514
534
|
if self.rfc2317_parent_managed:
|
|
515
535
|
for ptr_record in ptr_records:
|
|
516
|
-
ptr_record.save()
|
|
536
|
+
ptr_record.save(save_zone_serial=False)
|
|
517
537
|
|
|
538
|
+
self.rfc2317_parent_zone.save_soa_serial()
|
|
539
|
+
self.rfc2317_parent_zone.update_soa_record()
|
|
518
540
|
else:
|
|
519
541
|
cname_records = {
|
|
520
542
|
ptr_record.rfc2317_cname_record
|
|
521
543
|
for ptr_record in ptr_records
|
|
522
544
|
if ptr_record.rfc2317_cname_record is not None
|
|
523
545
|
}
|
|
546
|
+
cname_zones = {cname_record.zone for cname_record in cname_records}
|
|
547
|
+
|
|
524
548
|
for ptr_record in ptr_records:
|
|
525
|
-
ptr_record.save(update_rfc2317_cname=False)
|
|
549
|
+
ptr_record.save(update_rfc2317_cname=False, save_zone_serial=False)
|
|
526
550
|
for cname_record in cname_records:
|
|
527
|
-
cname_record.delete()
|
|
551
|
+
cname_record.delete(save_zone_serial=False)
|
|
552
|
+
|
|
553
|
+
for cname_zone in cname_zones:
|
|
554
|
+
cname_zone.save_soa_serial()
|
|
555
|
+
cname_zone.update_soa_record()
|
|
556
|
+
|
|
557
|
+
for ptr_zone in ptr_zones:
|
|
558
|
+
ptr_zone.save_soa_serial()
|
|
559
|
+
ptr_zone.update_soa_record()
|
|
528
560
|
|
|
529
561
|
def clean(self, *args, **kwargs):
|
|
530
562
|
self.check_name_conflict()
|
|
@@ -643,7 +675,12 @@ class Zone(NetBoxModel):
|
|
|
643
675
|
)
|
|
644
676
|
|
|
645
677
|
for address_record in address_records:
|
|
646
|
-
address_record.save(
|
|
678
|
+
address_record.save(
|
|
679
|
+
update_fields=["ptr_record"], save_zone_serial=False
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
for zone in zones:
|
|
683
|
+
zone.save_soa_serial()
|
|
647
684
|
|
|
648
685
|
if self.arpa_network.version == 4:
|
|
649
686
|
rfc2317_child_zones = Zone.objects.filter(
|
|
@@ -674,9 +711,14 @@ class Zone(NetBoxModel):
|
|
|
674
711
|
|
|
675
712
|
for address_record in address_records:
|
|
676
713
|
address_record.save(
|
|
677
|
-
update_fields=["ptr_record"],
|
|
714
|
+
update_fields=["ptr_record"],
|
|
715
|
+
update_rfc2317_cname=False,
|
|
716
|
+
save_zone_serial=False,
|
|
678
717
|
)
|
|
679
718
|
|
|
719
|
+
for zone in zones:
|
|
720
|
+
zone.save_soa_serial()
|
|
721
|
+
|
|
680
722
|
self.update_rfc2317_parent_zone()
|
|
681
723
|
|
|
682
724
|
elif name_changed or view_changed or status_changed:
|
|
@@ -696,11 +738,14 @@ class Zone(NetBoxModel):
|
|
|
696
738
|
ip.dns_name = f'{ip.custom_field_data["ipaddress_dns_record_name"]}.{self.name}'
|
|
697
739
|
ip.save(update_fields=["dns_name"])
|
|
698
740
|
|
|
741
|
+
self.save_soa_serial()
|
|
699
742
|
self.update_soa_record()
|
|
700
743
|
|
|
701
744
|
def delete(self, *args, **kwargs):
|
|
702
745
|
with transaction.atomic():
|
|
703
|
-
address_records = self.record_set.filter(
|
|
746
|
+
address_records = self.record_set.filter(
|
|
747
|
+
ptr_record__isnull=False
|
|
748
|
+
).prefetch_related("ptr_record")
|
|
704
749
|
for address_record in address_records:
|
|
705
750
|
address_record.ptr_record.delete()
|
|
706
751
|
|
|
@@ -717,8 +762,13 @@ class Zone(NetBoxModel):
|
|
|
717
762
|
for ptr_record in ptr_records
|
|
718
763
|
if ptr_record.rfc2317_cname_record is not None
|
|
719
764
|
}
|
|
765
|
+
cname_zones = {cname_record.zone for cname_record in cname_records}
|
|
766
|
+
|
|
720
767
|
for cname_record in cname_records:
|
|
721
|
-
cname_record.delete()
|
|
768
|
+
cname_record.delete(save_zone_serial=False)
|
|
769
|
+
for cname_zone in cname_zones:
|
|
770
|
+
cname_zone.save_soa_serial()
|
|
771
|
+
cname_zone.update_soa_record()
|
|
722
772
|
|
|
723
773
|
rfc2317_child_zones = [
|
|
724
774
|
child_zone.pk for child_zone in self.rfc2317_child_zones.all()
|
|
@@ -735,11 +785,25 @@ class Zone(NetBoxModel):
|
|
|
735
785
|
|
|
736
786
|
super().delete(*args, **kwargs)
|
|
737
787
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
788
|
+
address_records = record.Record.objects.filter(
|
|
789
|
+
pk__in=update_records
|
|
790
|
+
).prefetch_related("zone")
|
|
791
|
+
|
|
792
|
+
for address_record in address_records:
|
|
793
|
+
address_record.save(save_zone_serial=False)
|
|
794
|
+
for address_zone in {address_record.zone for address_record in address_records}:
|
|
795
|
+
address_zone.save_soa_serial()
|
|
796
|
+
address_zone.update_soa_record()
|
|
797
|
+
|
|
798
|
+
rfc2317_child_zones = Zone.objects.filter(pk__in=rfc2317_child_zones)
|
|
799
|
+
if rfc2317_child_zones:
|
|
800
|
+
for child_zone in rfc2317_child_zones:
|
|
801
|
+
child_zone.update_rfc2317_parent_zone()
|
|
802
|
+
|
|
803
|
+
new_rfc2317_parent_zone = rfc2317_child_zones.first().rfc2317_parent_zone
|
|
804
|
+
if new_rfc2317_parent_zone is not None:
|
|
805
|
+
new_rfc2317_parent_zone.save_soa_serial()
|
|
806
|
+
new_rfc2317_parent_zone.update_soa_record()
|
|
743
807
|
|
|
744
808
|
|
|
745
809
|
@receiver(m2m_changed, sender=Zone.nameservers.through)
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
<h5 class="card-header">Contact Details</h5>
|
|
23
23
|
<div class="card-body">
|
|
24
24
|
<table class="table table-hover attr-table">
|
|
25
|
+
<tr>
|
|
26
|
+
<th scope="row">Address</th>
|
|
27
|
+
<td>{{ object.address }}</td>
|
|
28
|
+
</tr>
|
|
25
29
|
<tr>
|
|
26
30
|
<th scope="row">Referral URL</th>
|
|
27
31
|
<td><a href="{{ object.referral_url }}">{{ object.referral_url }}</a></td>
|
|
@@ -120,10 +120,17 @@
|
|
|
120
120
|
<th scope="row">Responsible</th>
|
|
121
121
|
<td>{{ object.soa_rname }}</td>
|
|
122
122
|
</tr>
|
|
123
|
+
{% if object.soa_serial_auto %}
|
|
124
|
+
<tr>
|
|
125
|
+
<th scope="row">Serial (auto-generated)</th>
|
|
126
|
+
<td>{{ object.soa_serial }}</td>
|
|
127
|
+
</tr>
|
|
128
|
+
{% else %}
|
|
123
129
|
<tr>
|
|
124
130
|
<th scope="row">Serial</th>
|
|
125
131
|
<td>{{ object.soa_serial }}</td>
|
|
126
132
|
</tr>
|
|
133
|
+
{% endif %}
|
|
127
134
|
<tr>
|
|
128
135
|
<th scope="row">Refresh</th>
|
|
129
136
|
<td>{{ object.soa_refresh }}</td>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: netbox-plugin-dns
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.5
|
|
4
4
|
Summary: NetBox DNS is a NetBox plugin for managing DNS data.
|
|
5
5
|
Home-page: https://github.com/peteeckel/netbox-plugin-dns
|
|
6
6
|
License: MIT
|
|
@@ -8,6 +8,7 @@ Keywords: netbox,netbox-plugin,dns
|
|
|
8
8
|
Author: Peter Eckel
|
|
9
9
|
Author-email: pete@netbox-dns.org
|
|
10
10
|
Requires-Python: >=3.8,<4.0
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
13
|
Classifier: Programming Language :: Python :: 3
|
|
13
14
|
Classifier: Programming Language :: Python :: 3.8
|
|
@@ -19,16 +20,15 @@ Requires-Dist: dnspython (>=2.2.1,<3.0.0)
|
|
|
19
20
|
Project-URL: Repository, https://github.com/peteeckel/netbox-plugin-dns
|
|
20
21
|
Description-Content-Type: text/markdown
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
<p align="center"><i>NetBox DNS is a NetBox plugin for managing DNS views, zones, name servers and records.</i></p>
|
|
23
|
+
# NetBox DNS
|
|
24
|
+
The NetBox DNS plugin enables NetBox to manage operational DNS data such as name servers, zones, records and views, as well as registration data for domains. It can automate tasks like creating PTR records, generating zone serial numbers, NS and SOA records, as well as validate names and values values for resource records to ensure zone data is consistent, current and conforming to the relevant RFCs.
|
|
25
25
|
|
|
26
26
|
<div align="center">
|
|
27
27
|
<a href="https://pypi.org/project/netbox-plugin-dns/"><img src="https://img.shields.io/pypi/v/netbox-plugin-dns" alt="PyPi"/></a>
|
|
28
|
-
<a href="https://github.com/peteeckel/netbox-plugin-dns/stargazers"><img src="https://img.shields.io/github/stars/peteeckel/netbox-plugin-dns" alt="Stars Badge"/></a>
|
|
29
|
-
<a href="https://github.com/peteeckel/netbox-plugin-dns/network/members"><img src="https://img.shields.io/github/forks/peteeckel/netbox-plugin-dns" alt="Forks Badge"/></a>
|
|
30
|
-
<a href="https://github.com/peteeckel/netbox-plugin-dns/pulls"><img src="https://img.shields.io/github/issues-pr/peteeckel/netbox-plugin-dns" alt="Pull Requests Badge"/></a>
|
|
28
|
+
<a href="https://github.com/peteeckel/netbox-plugin-dns/stargazers"><img src="https://img.shields.io/github/stars/peteeckel/netbox-plugin-dns?style=flat" alt="Stars Badge"/></a>
|
|
29
|
+
<a href="https://github.com/peteeckel/netbox-plugin-dns/network/members"><img src="https://img.shields.io/github/forks/peteeckel/netbox-plugin-dns?style=flat" alt="Forks Badge"/></a>
|
|
31
30
|
<a href="https://github.com/peteeckel/netbox-plugin-dns/issues"><img src="https://img.shields.io/github/issues/peteeckel/netbox-plugin-dns" alt="Issues Badge"/></a>
|
|
31
|
+
<a href="https://github.com/peteeckel/netbox-plugin-dns/pulls"><img src="https://img.shields.io/github/issues-pr/peteeckel/netbox-plugin-dns" alt="Pull Requests Badge"/></a>
|
|
32
32
|
<a href="https://github.com/peteeckel/netbox-plugin-dns/graphs/contributors"><img alt="GitHub contributors" src="https://img.shields.io/github/contributors/peteeckel/netbox-plugin-dns?color=2b9348"></a>
|
|
33
33
|
<a href="https://github.com/peteeckel/netbox-plugin-dns/blob/master/LICENSE"><img src="https://img.shields.io/github/license/peteeckel/netbox-plugin-dns?color=2b9348" alt="License Badge"/></a>
|
|
34
34
|
<a href="https://pepy.tech/project/netbox-plugin-dns"><img alt="Downloads" src="https://static.pepy.tech/badge/netbox-plugin-dns"></a>
|
|
@@ -40,10 +40,10 @@ Description-Content-Type: text/markdown
|
|
|
40
40
|
|
|
41
41
|
* Manage name servers, zones and records
|
|
42
42
|
* Automatically generate SOA and NS records for zones
|
|
43
|
-
* Automatically create and update PTR records for IPv4 and IPv6 records
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
* Automatically create and update PTR records for IPv4 and IPv6 address records
|
|
44
|
+
* Organize DNS zones in views for split horizon DNS and multi-site deployments
|
|
45
|
+
* Manage domain registrar and registrant information for domains related to zones
|
|
46
|
+
* Manage RFC2317 reverse zones for IPv4 prefixes with a network mask length longer than 24 bits
|
|
47
47
|
|
|
48
48
|
NetBox DNS is using the standardized NetBox plugin interface, so it also takes advantage of the NetBox tagging and change log features.
|
|
49
49
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
netbox_dns/__init__.py,sha256=
|
|
1
|
+
netbox_dns/__init__.py,sha256=Wnz89UxRISvgUOkm-cZI50tMo6taJh14iZnSb1Wx0L4,2818
|
|
2
2
|
netbox_dns/api/nested_serializers.py,sha256=XB7bcCjVMPYrumJWgRicj06PukQ2UCBjdr84AIUJuVQ,3291
|
|
3
|
-
netbox_dns/api/serializers.py,sha256=
|
|
3
|
+
netbox_dns/api/serializers.py,sha256=H5Vm1O6C4SsxHVzdooYiu5ak3ykxXo-L1mT6ISWVRV8,8183
|
|
4
4
|
netbox_dns/api/urls.py,sha256=R9VmmWtdrjvr35i5d_SfZK2lGn6JzmPuWEKTQlZ8MJo,575
|
|
5
5
|
netbox_dns/api/views.py,sha256=DjovvTfS4F2Fq2Ahea6f4LBJiWr01ajk-wSZHNTya5I,3527
|
|
6
6
|
netbox_dns/apps.py,sha256=JCW5eS-AQBUubDJve1DjP-IRFKTFGQh1NLGWzJpC5MI,151
|
|
@@ -12,16 +12,16 @@ netbox_dns/filters/__init__.py,sha256=Aw8HrCTjaJfu5JSwJsQRHfOUz4zKwAmZNByT9q6BrF
|
|
|
12
12
|
netbox_dns/filters/contact.py,sha256=_onZ6G2KKgfvm9Emg_kng2RPETRMfbTyIR8Tvs9d2YM,1027
|
|
13
13
|
netbox_dns/filters/nameserver.py,sha256=sDKsrluSmUZ0aTw_wagYJAh1g5fKzyzHXbJu6DaK1b8,522
|
|
14
14
|
netbox_dns/filters/record.py,sha256=DH1x4bNkBAN_gVNklAjorcgHoJmH_AXEf1sBNvJS6Kc,1691
|
|
15
|
-
netbox_dns/filters/registrar.py,sha256=
|
|
15
|
+
netbox_dns/filters/registrar.py,sha256=8UXJXUb0XmkPyPQ2oACAhzhmZtAmvM2c4hTWMDLuBEo,911
|
|
16
16
|
netbox_dns/filters/view.py,sha256=Sji4DKy0VKk8BLEdk8xCe8su3rUBtXeJUsUAee0IsOs,497
|
|
17
17
|
netbox_dns/filters/zone.py,sha256=gNKTLll0nvdkzjEVl5c4O1hncU13IFVKn61iXThLYJA,3556
|
|
18
18
|
netbox_dns/forms/__init__.py,sha256=Aw8HrCTjaJfu5JSwJsQRHfOUz4zKwAmZNByT9q6BrFU,136
|
|
19
19
|
netbox_dns/forms/contact.py,sha256=Z8llYOpcGns8ZerOLsldpY836pfjO7427rmAZ4T8Kyg,4492
|
|
20
20
|
netbox_dns/forms/nameserver.py,sha256=LUYV_tna667flgPdQevDFniMdXZUYRUG8iqCx7HKdxQ,2027
|
|
21
21
|
netbox_dns/forms/record.py,sha256=TAQ-rZ55lmWE_piogiE5TwTv1v4r5T2yZpNT8K7GrPU,6171
|
|
22
|
-
netbox_dns/forms/registrar.py,sha256=
|
|
22
|
+
netbox_dns/forms/registrar.py,sha256=Vkw8cafXQRDHf7K7OFPn62R-_BzjNOofnhLmL2Hw7mg,2636
|
|
23
23
|
netbox_dns/forms/view.py,sha256=KEWlUo8-oXP_QsqT5fW_UK-ZoX9g-f4CqRnJ_P6LHco,1627
|
|
24
|
-
netbox_dns/forms/zone.py,sha256=
|
|
24
|
+
netbox_dns/forms/zone.py,sha256=Y9KfeSCzFrJU1LxQjxPcLANu3NEcaHjvxnyMqgna_FY,21702
|
|
25
25
|
netbox_dns/graphql/__init__.py,sha256=v3lLvVoP-JQbEZ1NY49u1TNqvanF-4TqOtjHXrbsTvU,811
|
|
26
26
|
netbox_dns/graphql/contact.py,sha256=2iyuvCxG09CLDUMhan5vR3uFZxCVzKNZBrotr_zoUVY,497
|
|
27
27
|
netbox_dns/graphql/nameserver.py,sha256=mlQw1Po_Ax_fjyyXVBetyxlFLrCqmptYDgOspZvYtP4,527
|
|
@@ -31,6 +31,7 @@ netbox_dns/graphql/schema.py,sha256=D_dDusogaI55tmGx_dr1owsgzXS5fd2S-kPZ7xcXxs8,
|
|
|
31
31
|
netbox_dns/graphql/view.py,sha256=S_61hYlQCtPQen1lI1UQs38UBWKQTaWfUxzlbpO07zA,467
|
|
32
32
|
netbox_dns/graphql/zone.py,sha256=QDBxocezhLSHBGDV4RJnmarBfOsiUTeE9KzBGJ3gJi8,467
|
|
33
33
|
netbox_dns/management/commands/cleanup_database.py,sha256=eggyMZrRg--cXDQJ-boofHboG1gJTs8j-oldhn6EuCo,6050
|
|
34
|
+
netbox_dns/management/commands/cleanup_rrset_ttl.py,sha256=gCvwH6hGw32YJtcy_pEWIP29PSRMW23-qzB8SHEdixQ,2077
|
|
34
35
|
netbox_dns/management/commands/setup_coupling.py,sha256=Yn1nffPR7fBgB6WWBdDqdnp3k8z1QK8k6qi9xbx4U6Y,4580
|
|
35
36
|
netbox_dns/management/commands/update_soa.py,sha256=qvlApMngTVpauj0CU0yeOy9r3lxxDciKorMxFsyvQhs,661
|
|
36
37
|
netbox_dns/migrations/0001_initial.py,sha256=R9FbIQ7nO1ROb12NL8YQDkFQuP1r6-TtMcPwg4rwjus,4153
|
|
@@ -66,10 +67,10 @@ netbox_dns/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
|
66
67
|
netbox_dns/models/__init__.py,sha256=Q7UIEe2vGh18AZN4er6CykciwXPQGgUq0L-9718wZqU,182
|
|
67
68
|
netbox_dns/models/contact.py,sha256=Mzj4SR3fczOE96etWjObJElk0RVQetNuXZVtm8sS1h8,2849
|
|
68
69
|
netbox_dns/models/nameserver.py,sha256=SjKUbMRNE3TSDzmxbKFR9b4AfYPS0UPj0QeO7XpwNRk,2941
|
|
69
|
-
netbox_dns/models/record.py,sha256=
|
|
70
|
+
netbox_dns/models/record.py,sha256=nOKjaoVuyMVIfwNw_V4hYYd71fcE4UyXThU983KrXaY,23629
|
|
70
71
|
netbox_dns/models/registrar.py,sha256=ByKHeqH5KfswqOLjya8DZExJ1omSKFHMfCjIIYfnwTo,1416
|
|
71
72
|
netbox_dns/models/view.py,sha256=ljs3Q2xQR63ZOSyja5H7DEdFbm7MX2ZjlR6uNVrAsVo,920
|
|
72
|
-
netbox_dns/models/zone.py,sha256=
|
|
73
|
+
netbox_dns/models/zone.py,sha256=Ek7Jui3AldNHVAHowbQhC47QoXv0IgkhLzFziN14UUI,26333
|
|
73
74
|
netbox_dns/navigation.py,sha256=IutEr_TcPgDGzqTT1ZzV4IUABLSOFU9v364BfpCqbro,4587
|
|
74
75
|
netbox_dns/signals/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
76
|
netbox_dns/signals/ipam_coupling.py,sha256=xbb37_77ZqtgT3mKXZp18QRduqZuiAuYGPk8R9d7SVc,5727
|
|
@@ -86,7 +87,7 @@ netbox_dns/templates/netbox_dns/nameserver.html,sha256=3AJVbsuhKg4Jy74rlvwrGSHd_
|
|
|
86
87
|
netbox_dns/templates/netbox_dns/record/managed.html,sha256=G6LPG1koUGuzUiwYdv1okdVa4sKaofiQegDBnsFL0kA,89
|
|
87
88
|
netbox_dns/templates/netbox_dns/record/related.html,sha256=Aqor8uGcuHQTHjlX-Xmni2Yp4N7lOBrMOqQiszrQOC0,742
|
|
88
89
|
netbox_dns/templates/netbox_dns/record.html,sha256=1XOp9Rf7KiV736RKGh7A8LAYkrfI7veG5SsEhaeMghw,6613
|
|
89
|
-
netbox_dns/templates/netbox_dns/registrar.html,sha256=
|
|
90
|
+
netbox_dns/templates/netbox_dns/registrar.html,sha256=rSShbH68nP0r8EUHn0-TZOsUj6pg7hmfvM7h2tqouUA,2130
|
|
90
91
|
netbox_dns/templates/netbox_dns/related_dns_objects.html,sha256=KSzlnw1cStrJa3poKkwrt_ycIH0oH0STWIHRNy3ks4g,806
|
|
91
92
|
netbox_dns/templates/netbox_dns/view.html,sha256=_lDjd2xY3upfGpNpemXXMzgsaKZlX3-PzPPAdYkIjvs,1350
|
|
92
93
|
netbox_dns/templates/netbox_dns/zone/base.html,sha256=pucf_b7iGg4hCXqwIbR0_WtEQdeH2LQtTCRTSoeBhFc,460
|
|
@@ -95,7 +96,7 @@ netbox_dns/templates/netbox_dns/zone/managed_record.html,sha256=5P85eJuQOB7omih2
|
|
|
95
96
|
netbox_dns/templates/netbox_dns/zone/record.html,sha256=1oIRGXOZAjwmTMkTgArfKyVrmL54Sh_IN7IAF3qYEKM,2218
|
|
96
97
|
netbox_dns/templates/netbox_dns/zone/registration.html,sha256=3R5uqLXZxIJkp9_LVnTTgTV61mITfDPDDNofV7s4d1k,1283
|
|
97
98
|
netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html,sha256=kxIrhn0gghb4l1eZhpsICdfkSYegqSXR9zFIWiZLypA,527
|
|
98
|
-
netbox_dns/templates/netbox_dns/zone.html,sha256=
|
|
99
|
+
netbox_dns/templates/netbox_dns/zone.html,sha256=_lQhr00_V8ThadlTuTm5zPkcvyjYQxxYGHQsfTOgDCs,7187
|
|
99
100
|
netbox_dns/urls.py,sha256=NxqvnRxLM6VwUBTY6KA8u-PRjNklmBai7gy6NXc-1xo,9172
|
|
100
101
|
netbox_dns/utilities/__init__.py,sha256=8DqDx-99kejykwaIt_29W5KgY8RvWBOk6526vrf22UQ,1967
|
|
101
102
|
netbox_dns/utilities/ipam_coupling.py,sha256=LhdFafF4OAOU8rgROOqY5Dt7XDT_SUZP2JuIqCQYVqw,3573
|
|
@@ -109,7 +110,7 @@ netbox_dns/views/record.py,sha256=2xzZnCWmCZIyEVjQfYo0rByhBNItPxNFiehOwDl8U6w,25
|
|
|
109
110
|
netbox_dns/views/registrar.py,sha256=aznSKt1L5tILMLGgcZiBR7u7B8rNl-jM1B2-N0fTeK8,2072
|
|
110
111
|
netbox_dns/views/view.py,sha256=uUvtlNEh5MYoEALvWWaCOqj_Zj8dpGOL2PUyg-UPfEA,1895
|
|
111
112
|
netbox_dns/views/zone.py,sha256=SyttTAgrPPzf1jIT1B4RexCLdXYjSmPIZsefO_zog1Q,4587
|
|
112
|
-
netbox_plugin_dns-0.22.
|
|
113
|
-
netbox_plugin_dns-0.22.
|
|
114
|
-
netbox_plugin_dns-0.22.
|
|
115
|
-
netbox_plugin_dns-0.22.
|
|
113
|
+
netbox_plugin_dns-0.22.5.dist-info/LICENSE,sha256=tziMJKpkMbySr09L6bIwsu7Ca9ICoqpMO3yAXgEMQA4,1076
|
|
114
|
+
netbox_plugin_dns-0.22.5.dist-info/METADATA,sha256=U6WLJ-pstL29t54fKW1LAJMkq8r-rtSR8AtutZqxnHg,4572
|
|
115
|
+
netbox_plugin_dns-0.22.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
116
|
+
netbox_plugin_dns-0.22.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|