netbox-plugin-dns 1.2.7b3__py3-none-any.whl → 1.2.9__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (45) hide show
  1. netbox_dns/__init__.py +56 -29
  2. netbox_dns/api/field_serializers.py +25 -0
  3. netbox_dns/api/serializers_/dnssec_key_template.py +2 -0
  4. netbox_dns/api/serializers_/dnssec_policy.py +13 -0
  5. netbox_dns/api/serializers_/record.py +2 -0
  6. netbox_dns/api/serializers_/record_template.py +2 -0
  7. netbox_dns/api/serializers_/zone.py +11 -1
  8. netbox_dns/choices/dnssec_key_template.py +2 -2
  9. netbox_dns/choices/dnssec_policy.py +2 -2
  10. netbox_dns/choices/record.py +66 -19
  11. netbox_dns/choices/utilities.py +4 -26
  12. netbox_dns/choices/zone.py +96 -1
  13. netbox_dns/fields/timeperiod.py +6 -12
  14. netbox_dns/filtersets/dnssec_key_template.py +2 -2
  15. netbox_dns/filtersets/dnssec_policy.py +7 -6
  16. netbox_dns/filtersets/zone.py +25 -2
  17. netbox_dns/filtersets/zone_template.py +2 -2
  18. netbox_dns/forms/dnssec_key_template.py +3 -2
  19. netbox_dns/forms/dnssec_policy.py +39 -37
  20. netbox_dns/forms/nameserver.py +2 -0
  21. netbox_dns/forms/record_template.py +1 -0
  22. netbox_dns/forms/zone.py +99 -15
  23. netbox_dns/forms/zone_template.py +9 -0
  24. netbox_dns/graphql/types.py +1 -0
  25. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  26. netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
  27. netbox_dns/migrations/0018_zone_domain_status_zone_expiration_date.py +23 -0
  28. netbox_dns/migrations/0019_dnssecpolicy_parental_agents.py +25 -0
  29. netbox_dns/migrations/0020_remove_dnssecpolicy_parental_agents_and_more.py +29 -0
  30. netbox_dns/models/record.py +4 -1
  31. netbox_dns/models/zone.py +74 -4
  32. netbox_dns/models/zone_template.py +1 -1
  33. netbox_dns/tables/zone.py +6 -1
  34. netbox_dns/template_content.py +2 -1
  35. netbox_dns/templates/netbox_dns/zone/registration.html +19 -0
  36. netbox_dns/templates/netbox_dns/zone.html +10 -0
  37. netbox_dns/urls.py +7 -0
  38. netbox_dns/utilities/conversions.py +13 -0
  39. netbox_dns/validators/dns_value.py +3 -0
  40. netbox_dns/views/zone.py +11 -1
  41. {netbox_plugin_dns-1.2.7b3.dist-info → netbox_plugin_dns-1.2.9.dist-info}/METADATA +4 -3
  42. {netbox_plugin_dns-1.2.7b3.dist-info → netbox_plugin_dns-1.2.9.dist-info}/RECORD +45 -41
  43. {netbox_plugin_dns-1.2.7b3.dist-info → netbox_plugin_dns-1.2.9.dist-info}/WHEEL +1 -1
  44. {netbox_plugin_dns-1.2.7b3.dist-info → netbox_plugin_dns-1.2.9.dist-info/licenses}/LICENSE +0 -0
  45. {netbox_plugin_dns-1.2.7b3.dist-info → netbox_plugin_dns-1.2.9.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  import netaddr
2
+ from netaddr.core import AddrFormatError
2
3
 
3
4
  import django_filters
4
5
  from django.db.models import Q
@@ -16,7 +17,7 @@ from netbox_dns.models import (
16
17
  NameServer,
17
18
  DNSSECPolicy,
18
19
  )
19
- from netbox_dns.choices import ZoneStatusChoices
20
+ from netbox_dns.choices import ZoneStatusChoices, ZoneEPPStatusChoices
20
21
 
21
22
 
22
23
  __all__ = ("ZoneFilterSet",)
@@ -68,6 +69,10 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
68
69
  to_field_name="name",
69
70
  label=_("DNSSEC Policy"),
70
71
  )
72
+ parental_agents = MultiValueCharFilter(
73
+ method="filter_parental_agents",
74
+ label=_("Parental Agents"),
75
+ )
71
76
  rfc2317_prefix = MultiValueCharFilter(
72
77
  method="filter_rfc2317_prefix",
73
78
  label=_("RFC2317 Prefix"),
@@ -86,7 +91,7 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
86
91
  )
87
92
  registrar_id = django_filters.ModelMultipleChoiceFilter(
88
93
  queryset=Registrar.objects.all(),
89
- label="Registrar ID",
94
+ label=_("Registrar ID"),
90
95
  )
91
96
  registrar = django_filters.ModelMultipleChoiceFilter(
92
97
  queryset=Registrar.objects.all(),
@@ -94,6 +99,10 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
94
99
  to_field_name="name",
95
100
  label=_("Registrar"),
96
101
  )
102
+ expiration_date = django_filters.DateFromToRangeFilter()
103
+ domain_status = django_filters.MultipleChoiceFilter(
104
+ choices=ZoneEPPStatusChoices,
105
+ )
97
106
  registrant_id = django_filters.ModelMultipleChoiceFilter(
98
107
  queryset=RegistrationContact.objects.all(),
99
108
  label=_("Registrant ID"),
@@ -160,8 +169,22 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
160
169
  "rfc2317_parent_managed",
161
170
  "inline_signing",
162
171
  "registry_domain_id",
172
+ "domain_status",
163
173
  )
164
174
 
175
+ def filter_parental_agents(self, queryset, name, value):
176
+ if not value:
177
+ return queryset
178
+
179
+ query_values = []
180
+ for v in value:
181
+ try:
182
+ query_values.append(str(netaddr.IPAddress(v)))
183
+ except (AddrFormatError, ValueError):
184
+ pass
185
+
186
+ return queryset.filter(parental_agents__overlap=query_values)
187
+
165
188
  def filter_arpa_network(self, queryset, name, value):
166
189
  if not value:
167
190
  return queryset
@@ -48,13 +48,13 @@ class ZoneTemplateFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
48
48
  queryset=NameServer.objects.all(),
49
49
  field_name="soa_mname",
50
50
  to_field_name="id",
51
- label=_("SOA MNAME ID"),
51
+ label=_("SOA MName ID"),
52
52
  )
53
53
  soa_mname = django_filters.ModelMultipleChoiceFilter(
54
54
  queryset=NameServer.objects.all(),
55
55
  field_name="soa_mname__name",
56
56
  to_field_name="name",
57
- label=_("SOA MNAME"),
57
+ label=_("SOA MName"),
58
58
  )
59
59
  dnssec_policy_id = django_filters.ModelMultipleChoiceFilter(
60
60
  queryset=DNSSECPolicy.objects.all(),
@@ -68,7 +68,7 @@ class DNSSECKeyTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
68
68
  fieldsets = (
69
69
  FieldSet("q", "filter_id", "tag"),
70
70
  FieldSet("name", "description", name=_("Attributes")),
71
- FieldSet("policies_id", name=_("Policies")),
71
+ FieldSet("policiy_id", name=_("Policies")),
72
72
  FieldSet("type", "lifetime", "algorithm", "key_size", name=_("Key Properties")),
73
73
  FieldSet("tenant_group_id", "tenant_id", name=_("Tenancy")),
74
74
  )
@@ -79,9 +79,10 @@ class DNSSECKeyTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
79
79
  description = forms.CharField(
80
80
  required=False,
81
81
  )
82
- policies_id = DynamicModelMultipleChoiceField(
82
+ policy_id = DynamicModelMultipleChoiceField(
83
83
  queryset=DNSSECPolicy.objects.all(),
84
84
  required=False,
85
+ null_option=_("None"),
85
86
  label=_("Policies"),
86
87
  )
87
88
  type = forms.MultipleChoiceField(
@@ -85,37 +85,6 @@ class DNSSECPolicyForm(TenancyForm, NetBoxModelForm):
85
85
  help_text=_("Select CSK or KSK/ZSK templates for signing"),
86
86
  quick_add=QUICK_ADD,
87
87
  )
88
-
89
- class Meta:
90
- model = DNSSECPolicy
91
- fields = (
92
- "name",
93
- "description",
94
- "status",
95
- "key_templates",
96
- "dnskey_ttl",
97
- "purge_keys",
98
- "publish_safety",
99
- "retire_safety",
100
- "signatures_jitter",
101
- "signatures_refresh",
102
- "signatures_validity",
103
- "signatures_validity_dnskey",
104
- "max_zone_ttl",
105
- "zone_propagation_delay",
106
- "create_cdnskey",
107
- "cds_digest_types",
108
- "parent_ds_ttl",
109
- "parent_propagation_delay",
110
- "use_nsec3",
111
- "nsec3_iterations",
112
- "nsec3_opt_out",
113
- "nsec3_salt_size",
114
- "tenant_group",
115
- "tenant",
116
- "tags",
117
- )
118
-
119
88
  dnskey_ttl = TimePeriodField(
120
89
  required=False,
121
90
  label=_("DNSKEY TTL"),
@@ -177,6 +146,36 @@ class DNSSECPolicyForm(TenancyForm, NetBoxModelForm):
177
146
  placeholder=DNSSECPolicy.get_fallback_setting("parent_propagation_delay"),
178
147
  )
179
148
 
149
+ class Meta:
150
+ model = DNSSECPolicy
151
+ fields = (
152
+ "name",
153
+ "description",
154
+ "status",
155
+ "key_templates",
156
+ "dnskey_ttl",
157
+ "purge_keys",
158
+ "publish_safety",
159
+ "retire_safety",
160
+ "signatures_jitter",
161
+ "signatures_refresh",
162
+ "signatures_validity",
163
+ "signatures_validity_dnskey",
164
+ "max_zone_ttl",
165
+ "zone_propagation_delay",
166
+ "create_cdnskey",
167
+ "cds_digest_types",
168
+ "parent_ds_ttl",
169
+ "parent_propagation_delay",
170
+ "use_nsec3",
171
+ "nsec3_iterations",
172
+ "nsec3_opt_out",
173
+ "nsec3_salt_size",
174
+ "tenant_group",
175
+ "tenant",
176
+ "tags",
177
+ )
178
+
180
179
 
181
180
  class DNSSECPolicyFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
182
181
  model = DNSSECPolicy
@@ -186,12 +185,12 @@ class DNSSECPolicyFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
186
185
  "name",
187
186
  "description",
188
187
  "status",
189
- "key_templates_id",
188
+ "key_template_id",
190
189
  name=_("Attributes"),
191
190
  ),
192
191
  FieldSet(
193
- "zones_id",
194
- "zone_templates_id",
192
+ "zone_id",
193
+ "zone_template_id",
195
194
  name=_("Assignments"),
196
195
  ),
197
196
  FieldSet(
@@ -236,19 +235,22 @@ class DNSSECPolicyFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
236
235
  required=False,
237
236
  label=_("Status"),
238
237
  )
239
- key_templates_id = DynamicModelMultipleChoiceField(
238
+ key_template_id = DynamicModelMultipleChoiceField(
240
239
  queryset=DNSSECKeyTemplate.objects.all(),
241
240
  required=False,
241
+ null_option=_("None"),
242
242
  label=_("Key Templates"),
243
243
  )
244
- zones_id = DynamicModelMultipleChoiceField(
244
+ zone_id = DynamicModelMultipleChoiceField(
245
245
  queryset=Zone.objects.all(),
246
246
  required=False,
247
+ null_option=_("None"),
247
248
  label=_("Zones"),
248
249
  )
249
- zone_templates_id = DynamicModelMultipleChoiceField(
250
+ zone_template_id = DynamicModelMultipleChoiceField(
250
251
  queryset=ZoneTemplate.objects.all(),
251
252
  required=False,
253
+ null_option=_("None"),
252
254
  label=_("Zone Templates"),
253
255
  )
254
256
  dnskey_ttl = TimePeriodField(
@@ -64,11 +64,13 @@ class NameServerFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
64
64
  zone_id = DynamicModelMultipleChoiceField(
65
65
  queryset=Zone.objects.all(),
66
66
  required=False,
67
+ null_option=_("None"),
67
68
  label=_("Zones"),
68
69
  )
69
70
  soa_zone_id = DynamicModelMultipleChoiceField(
70
71
  queryset=Zone.objects.all(),
71
72
  required=False,
73
+ null_option=_("None"),
72
74
  label=_("SOA Zones"),
73
75
  )
74
76
  description = forms.CharField(
@@ -146,6 +146,7 @@ class RecordTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
146
146
  zone_template_id = DynamicModelMultipleChoiceField(
147
147
  queryset=ZoneTemplate.objects.all(),
148
148
  required=False,
149
+ null_option=_("None"),
149
150
  label=_("Zone Templates"),
150
151
  )
151
152
  tag = TagFilterField(RecordTemplate)
netbox_dns/forms/zone.py CHANGED
@@ -5,6 +5,7 @@ from django.db import transaction
5
5
  from django.conf import settings
6
6
  from django.core.validators import MinValueValidator, MaxValueValidator
7
7
  from django.core.exceptions import ValidationError
8
+ from django.contrib.postgres.forms import SimpleArrayField
8
9
  from django.utils.translation import gettext_lazy as _
9
10
 
10
11
  from netbox.forms import (
@@ -23,7 +24,7 @@ from utilities.forms.fields import (
23
24
  DynamicModelChoiceField,
24
25
  )
25
26
  from utilities.release import load_release_data
26
- from utilities.forms.widgets import BulkEditNullBooleanSelect
27
+ from utilities.forms.widgets import BulkEditNullBooleanSelect, DatePicker
27
28
  from utilities.forms.rendering import FieldSet
28
29
  from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, add_blank_choice
29
30
  from tenancy.models import Tenant, TenantGroup
@@ -38,7 +39,7 @@ from netbox_dns.models import (
38
39
  ZoneTemplate,
39
40
  DNSSECPolicy,
40
41
  )
41
- from netbox_dns.choices import ZoneStatusChoices
42
+ from netbox_dns.choices import ZoneStatusChoices, ZoneEPPStatusChoices
42
43
  from netbox_dns.utilities import name_to_unicode, network_to_reverse
43
44
  from netbox_dns.fields import RFC2317NetworkFormField, TimePeriodField
44
45
  from netbox_dns.validators import validate_ipv4, validate_prefix, validate_rfc2317
@@ -59,10 +60,21 @@ class RollbackTransaction(Exception):
59
60
 
60
61
 
61
62
  class ZoneTemplateUpdateMixin:
63
+ def _check_soa_mname(self):
64
+ if (
65
+ self.cleaned_data.get("soa_mname") is None
66
+ and "soa_mname" in self.fields.keys()
67
+ ):
68
+ self.add_error(
69
+ "soa_mname",
70
+ _("soa_mname not set and no template or default value defined"),
71
+ )
72
+
62
73
  def clean(self, *args, **kwargs):
63
74
  super().clean(*args, **kwargs)
64
75
 
65
76
  if (template := self.cleaned_data.get("template")) is None:
77
+ self._check_soa_mname()
66
78
  return
67
79
 
68
80
  if not self.cleaned_data.get("nameservers") and template.nameservers.all():
@@ -77,11 +89,7 @@ class ZoneTemplateUpdateMixin:
77
89
  ) not in (None, ""):
78
90
  self.cleaned_data[field] = getattr(template, field)
79
91
 
80
- if self.cleaned_data.get("soa_mname") is None:
81
- self.add_error(
82
- "soa_mname",
83
- _("soa_mname not set and no template or default value defined"),
84
- )
92
+ self._check_soa_mname()
85
93
 
86
94
  if self.errors:
87
95
  return
@@ -235,6 +243,12 @@ class ZoneForm(ZoneTemplateUpdateMixin, TenancyForm, NetBoxModelForm):
235
243
  label=_("SOA Serial"),
236
244
  )
237
245
 
246
+ parental_agents = SimpleArrayField(
247
+ required=False,
248
+ base_field=forms.GenericIPAddressField(),
249
+ label=_("Parental Agents"),
250
+ )
251
+
238
252
  rfc2317_prefix = RFC2317NetworkFormField(
239
253
  required=False,
240
254
  validators=[validate_ipv4, validate_prefix, validate_rfc2317],
@@ -275,6 +289,7 @@ class ZoneForm(ZoneTemplateUpdateMixin, TenancyForm, NetBoxModelForm):
275
289
  FieldSet(
276
290
  "dnssec_policy",
277
291
  "inline_signing",
292
+ "parental_agents",
278
293
  name=_("DNSSEC"),
279
294
  ),
280
295
  FieldSet(
@@ -285,6 +300,8 @@ class ZoneForm(ZoneTemplateUpdateMixin, TenancyForm, NetBoxModelForm):
285
300
  FieldSet(
286
301
  "registrar",
287
302
  "registry_domain_id",
303
+ "expiration_date",
304
+ "domain_status",
288
305
  "registrant",
289
306
  "admin_c",
290
307
  "tech_c",
@@ -377,8 +394,11 @@ class ZoneForm(ZoneTemplateUpdateMixin, TenancyForm, NetBoxModelForm):
377
394
  "rfc2317_parent_managed",
378
395
  "dnssec_policy",
379
396
  "inline_signing",
397
+ "parental_agents",
380
398
  "registrar",
381
399
  "registry_domain_id",
400
+ "expiration_date",
401
+ "domain_status",
382
402
  "registrant",
383
403
  "admin_c",
384
404
  "tech_c",
@@ -387,8 +407,8 @@ class ZoneForm(ZoneTemplateUpdateMixin, TenancyForm, NetBoxModelForm):
387
407
  "tenant",
388
408
  "tags",
389
409
  )
390
- help_texts = {
391
- "soa_mname": _("Primary nameserver for the zone"),
410
+ widgets = {
411
+ "expiration_date": DatePicker,
392
412
  }
393
413
 
394
414
 
@@ -412,8 +432,9 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
412
432
  name=_("SOA"),
413
433
  ),
414
434
  FieldSet(
415
- "dnssec_policy",
435
+ "dnssec_policy_id",
416
436
  "inline_signing",
437
+ "parental_agents",
417
438
  name=_("DNSSEC"),
418
439
  ),
419
440
  FieldSet(
@@ -425,6 +446,9 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
425
446
  FieldSet(
426
447
  "registrar_id",
427
448
  "registry_domain_id",
449
+ "expiration_date_before",
450
+ "expiration_date_after",
451
+ "domain_status",
428
452
  "registrant_id",
429
453
  "admin_c_id",
430
454
  "tech_c_id",
@@ -451,6 +475,7 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
451
475
  nameserver_id = DynamicModelMultipleChoiceField(
452
476
  queryset=NameServer.objects.all(),
453
477
  required=False,
478
+ null_option=_("None"),
454
479
  label=_("Nameservers"),
455
480
  )
456
481
  active = forms.NullBooleanField(
@@ -488,40 +513,71 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
488
513
  rfc2317_parent_zone_id = DynamicModelMultipleChoiceField(
489
514
  queryset=Zone.objects.all(),
490
515
  required=False,
516
+ null_option=_("None"),
491
517
  label=_("Parent Zone"),
492
518
  )
493
- registrar_id = DynamicModelMultipleChoiceField(
494
- queryset=Registrar.objects.all(),
495
- required=False,
496
- label=_("Registrar"),
497
- )
498
519
  dnssec_policy_id = DynamicModelMultipleChoiceField(
499
520
  queryset=DNSSECPolicy.objects.all(),
500
521
  required=False,
522
+ null_option=_("None"),
501
523
  label=_("DNSSEC Policy"),
502
524
  )
525
+ inline_signing = forms.NullBooleanField(
526
+ required=False,
527
+ widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
528
+ label=_("Use Inline Signing"),
529
+ )
530
+ parental_agents = forms.GenericIPAddressField(
531
+ required=False,
532
+ label=_("Parental Agent"),
533
+ )
534
+ registrar_id = DynamicModelMultipleChoiceField(
535
+ queryset=Registrar.objects.all(),
536
+ required=False,
537
+ null_option=_("None"),
538
+ label=_("Registrar"),
539
+ )
503
540
  registry_domain_id = forms.CharField(
504
541
  required=False,
505
542
  label=_("Registry Domain ID"),
506
543
  )
544
+ expiration_date_after = forms.DateField(
545
+ required=False,
546
+ label=_("Expiration Date after"),
547
+ widget=DatePicker,
548
+ )
549
+ expiration_date_before = forms.DateField(
550
+ required=False,
551
+ label=_("Expiration Date before"),
552
+ widget=DatePicker,
553
+ )
554
+ domain_status = forms.MultipleChoiceField(
555
+ choices=ZoneEPPStatusChoices,
556
+ required=False,
557
+ label=_("Domain Status"),
558
+ )
507
559
  registrant_id = DynamicModelMultipleChoiceField(
508
560
  queryset=RegistrationContact.objects.all(),
509
561
  required=False,
562
+ null_option=_("None"),
510
563
  label=_("Registrant"),
511
564
  )
512
565
  admin_c_id = DynamicModelMultipleChoiceField(
513
566
  queryset=RegistrationContact.objects.all(),
514
567
  required=False,
568
+ null_option=_("None"),
515
569
  label=_("Administrative Contact"),
516
570
  )
517
571
  tech_c_id = DynamicModelMultipleChoiceField(
518
572
  queryset=RegistrationContact.objects.all(),
519
573
  required=False,
574
+ null_option=_("None"),
520
575
  label=_("Technical Contact"),
521
576
  )
522
577
  billing_c_id = DynamicModelMultipleChoiceField(
523
578
  queryset=RegistrationContact.objects.all(),
524
579
  required=False,
580
+ null_option=_("None"),
525
581
  label=_("Billing Contact"),
526
582
  )
527
583
  tag = TagFilterField(Zone)
@@ -638,6 +694,11 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
638
694
  required=False,
639
695
  label=_("Registry Domain ID"),
640
696
  )
697
+ domain_status = CSVChoiceField(
698
+ choices=ZoneEPPStatusChoices,
699
+ required=False,
700
+ label=_("Domain Status"),
701
+ )
641
702
  registrant = CSVModelChoiceField(
642
703
  queryset=RegistrationContact.objects.all(),
643
704
  required=False,
@@ -709,10 +770,13 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
709
770
  "soa_minimum",
710
771
  "dnssec_policy",
711
772
  "inline_signing",
773
+ "parental_agents",
712
774
  "rfc2317_prefix",
713
775
  "rfc2317_parent_managed",
714
776
  "registrar",
715
777
  "registry_domain_id",
778
+ "expiration_date",
779
+ "domain_status",
716
780
  "registrant",
717
781
  "admin_c",
718
782
  "tech_c",
@@ -837,6 +901,11 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
837
901
  widget=BulkEditNullBooleanSelect(),
838
902
  label=_("Use Inline Signing"),
839
903
  )
904
+ parental_agents = SimpleArrayField(
905
+ required=False,
906
+ base_field=forms.GenericIPAddressField(),
907
+ label=_("Parental Agents"),
908
+ )
840
909
  registrar = DynamicModelChoiceField(
841
910
  queryset=Registrar.objects.all(),
842
911
  required=False,
@@ -846,6 +915,16 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
846
915
  required=False,
847
916
  label=_("Registry Domain ID"),
848
917
  )
918
+ expiration_date = forms.DateField(
919
+ required=False,
920
+ label=_("Expiration Date"),
921
+ widget=DatePicker,
922
+ )
923
+ domain_status = forms.ChoiceField(
924
+ choices=add_blank_choice(ZoneEPPStatusChoices),
925
+ required=False,
926
+ label=_("Domain Status"),
927
+ )
849
928
  registrant = DynamicModelChoiceField(
850
929
  queryset=RegistrationContact.objects.all(),
851
930
  required=False,
@@ -903,6 +982,7 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
903
982
  FieldSet(
904
983
  "dnssec_policy",
905
984
  "inline_signing",
985
+ "parental_agents",
906
986
  name=_("DNSSEC"),
907
987
  ),
908
988
  FieldSet(
@@ -913,6 +993,8 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
913
993
  FieldSet(
914
994
  "registrar",
915
995
  "registry_domain_id",
996
+ "expiration_date",
997
+ "domain_status",
916
998
  "registrant",
917
999
  "admin_c",
918
1000
  "tech_c",
@@ -927,6 +1009,8 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
927
1009
  "nameservers",
928
1010
  "rfc2317_prefix",
929
1011
  "registrar",
1012
+ "expiration_date",
1013
+ "domain_status",
930
1014
  "registry_domain_id",
931
1015
  "registrant",
932
1016
  "admin_c",
@@ -127,11 +127,13 @@ class ZoneTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
127
127
  nameserver_id = DynamicModelMultipleChoiceField(
128
128
  queryset=NameServer.objects.all(),
129
129
  required=False,
130
+ null_option=_("None"),
130
131
  label=_("Nameservers"),
131
132
  )
132
133
  soa_mname_id = DynamicModelMultipleChoiceField(
133
134
  queryset=NameServer.objects.all(),
134
135
  required=False,
136
+ null_option=_("None"),
135
137
  label=_("MName"),
136
138
  )
137
139
  soa_rname = forms.CharField(
@@ -141,6 +143,7 @@ class ZoneTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
141
143
  record_template_id = DynamicModelMultipleChoiceField(
142
144
  queryset=RecordTemplate.objects.all(),
143
145
  required=False,
146
+ null_option=_("None"),
144
147
  label=_("Record Templates"),
145
148
  )
146
149
  description = forms.CharField(
@@ -149,31 +152,37 @@ class ZoneTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
149
152
  dnssec_policy_id = DynamicModelMultipleChoiceField(
150
153
  queryset=DNSSECPolicy.objects.all(),
151
154
  required=False,
155
+ null_option=_("None"),
152
156
  label=_("DNSSEC Policy ID"),
153
157
  )
154
158
  registrar_id = DynamicModelMultipleChoiceField(
155
159
  queryset=Registrar.objects.all(),
156
160
  required=False,
161
+ null_option=_("None"),
157
162
  label=_("Registrar"),
158
163
  )
159
164
  registrant_id = DynamicModelMultipleChoiceField(
160
165
  queryset=RegistrationContact.objects.all(),
161
166
  required=False,
167
+ null_option=_("None"),
162
168
  label=_("Registrant"),
163
169
  )
164
170
  admin_c_id = DynamicModelMultipleChoiceField(
165
171
  queryset=RegistrationContact.objects.all(),
166
172
  required=False,
173
+ null_option=_("None"),
167
174
  label=_("Administrative Contact"),
168
175
  )
169
176
  tech_c_id = DynamicModelMultipleChoiceField(
170
177
  queryset=RegistrationContact.objects.all(),
171
178
  required=False,
179
+ null_option=_("None"),
172
180
  label=_("Technical Contact"),
173
181
  )
174
182
  billing_c_id = DynamicModelMultipleChoiceField(
175
183
  queryset=RegistrationContact.objects.all(),
176
184
  required=False,
185
+ null_option=_("None"),
177
186
  label=_("Billing Contact"),
178
187
  )
179
188
  tag = TagFilterField(ZoneTemplate)
@@ -90,6 +90,7 @@ class NetBoxDNSZoneType(NetBoxObjectType):
90
90
  | None
91
91
  )
92
92
  inline_signing: bool
93
+ parental_agents: List[str]
93
94
  registrar: (
94
95
  Annotated["NetBoxDNSRegistrarType", strawberry.lazy("netbox_dns.graphql.types")]
95
96
  | None
Binary file
Binary file
@@ -0,0 +1,23 @@
1
+ # Generated by Django 5.1.7 on 2025-04-03 13:43
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("netbox_dns", "0017_dnssec_policy_zone_zone_template"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name="zone",
15
+ name="domain_status",
16
+ field=models.CharField(blank=True, max_length=50, null=True),
17
+ ),
18
+ migrations.AddField(
19
+ model_name="zone",
20
+ name="expiration_date",
21
+ field=models.DateField(blank=True, null=True),
22
+ ),
23
+ ]
@@ -0,0 +1,25 @@
1
+ # Generated by Django 5.2 on 2025-04-22 18:05
2
+
3
+ import django.contrib.postgres.fields
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("netbox_dns", "0018_zone_domain_status_zone_expiration_date"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name="dnssecpolicy",
16
+ name="parental_agents",
17
+ field=django.contrib.postgres.fields.ArrayField(
18
+ base_field=models.GenericIPAddressField(),
19
+ blank=True,
20
+ default=list,
21
+ null=True,
22
+ size=None,
23
+ ),
24
+ ),
25
+ ]