netbox-plugin-dns 1.0.0__py3-none-any.whl → 1.0b1__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 (39) hide show
  1. netbox_dns/__init__.py +3 -3
  2. netbox_dns/api/serializers_/view.py +1 -6
  3. netbox_dns/api/serializers_/zone.py +11 -0
  4. netbox_dns/fields/network.py +21 -20
  5. netbox_dns/fields/rfc2317.py +2 -2
  6. netbox_dns/filtersets/view.py +1 -1
  7. netbox_dns/filtersets/zone.py +4 -4
  8. netbox_dns/forms/record.py +2 -30
  9. netbox_dns/forms/view.py +3 -6
  10. netbox_dns/forms/zone.py +101 -70
  11. netbox_dns/graphql/types.py +4 -1
  12. netbox_dns/management/commands/cleanup_rrset_ttl.py +1 -1
  13. netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +2 -4
  14. netbox_dns/models/nameserver.py +1 -3
  15. netbox_dns/models/record.py +24 -26
  16. netbox_dns/models/view.py +0 -53
  17. netbox_dns/models/zone.py +46 -63
  18. netbox_dns/signals/ipam_coupling.py +2 -1
  19. netbox_dns/tables/view.py +2 -9
  20. netbox_dns/template_content.py +1 -1
  21. netbox_dns/templates/netbox_dns/record.html +1 -1
  22. netbox_dns/templates/netbox_dns/view.html +0 -4
  23. netbox_dns/templates/netbox_dns/zone.html +4 -2
  24. netbox_dns/urls.py +297 -0
  25. netbox_dns/views/record.py +24 -9
  26. {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b1.dist-info}/METADATA +13 -29
  27. {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b1.dist-info}/RECORD +29 -38
  28. netbox_dns/migrations/0003_default_view.py +0 -15
  29. netbox_dns/migrations/0004_create_and_assign_default_view.py +0 -26
  30. netbox_dns/migrations/0005_alter_zone_view_not_null.py +0 -18
  31. netbox_dns/urls/__init__.py +0 -17
  32. netbox_dns/urls/contact.py +0 -51
  33. netbox_dns/urls/nameserver.py +0 -69
  34. netbox_dns/urls/record.py +0 -41
  35. netbox_dns/urls/registrar.py +0 -63
  36. netbox_dns/urls/view.py +0 -39
  37. netbox_dns/urls/zone.py +0 -57
  38. {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b1.dist-info}/LICENSE +0 -0
  39. {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b1.dist-info}/WHEEL +0 -0
netbox_dns/__init__.py CHANGED
@@ -1,20 +1,20 @@
1
1
  from netbox.plugins import PluginConfig
2
2
 
3
- __version__ = "1.0.0"
3
+ __version__ = "1.0-beta1"
4
4
 
5
5
 
6
6
  class DNSConfig(PluginConfig):
7
7
  name = "netbox_dns"
8
8
  verbose_name = "NetBox DNS"
9
9
  description = "NetBox plugin for DNS data"
10
- min_version = "4.0.0"
10
+ min_version = "4.0-beta1"
11
11
  version = __version__
12
12
  author = "Peter Eckel"
13
13
  author_email = "pete@netbox-dns.org"
14
14
  required_settings = []
15
15
  default_settings = {
16
16
  "zone_default_ttl": 86400,
17
- "zone_soa_ttl": 86400,
17
+ "zone_soa_serial_auto": True,
18
18
  "zone_soa_serial": 1,
19
19
  "zone_soa_refresh": 43200,
20
20
  "zone_soa_retry": 7200,
@@ -10,10 +10,6 @@ class ViewSerializer(NetBoxModelSerializer):
10
10
  url = serializers.HyperlinkedIdentityField(
11
11
  view_name="plugins-api:netbox_dns-api:view-detail"
12
12
  )
13
- default_view = serializers.BooleanField(
14
- read_only=True,
15
- )
16
-
17
13
  tenant = TenantSerializer(nested=True, required=False, allow_null=True)
18
14
 
19
15
  class Meta:
@@ -23,7 +19,6 @@ class ViewSerializer(NetBoxModelSerializer):
23
19
  "url",
24
20
  "display",
25
21
  "name",
26
- "default_view",
27
22
  "tags",
28
23
  "description",
29
24
  "created",
@@ -31,4 +26,4 @@ class ViewSerializer(NetBoxModelSerializer):
31
26
  "custom_fields",
32
27
  "tenant",
33
28
  )
34
- brief_fields = ("id", "url", "display", "name", "default_view", "description")
29
+ brief_fields = ("id", "url", "display", "name", "description")
@@ -13,6 +13,17 @@ from netbox_dns.models import Zone
13
13
 
14
14
 
15
15
  class ZoneSerializer(NetBoxModelSerializer):
16
+ # +
17
+ # This is a hack to avoid the exception raised by the UniqueTogetherValidator
18
+ # after NetBox commit https://github.com/netbox-community/netbox/commit/78e284c
19
+ #
20
+ # See https://github.com/netbox-community/netbox/issues/15351 for details.
21
+ # -
22
+ def __init__(self, *args, **kwargs):
23
+ super().__init__(*args, **kwargs)
24
+ if self.nested:
25
+ self.validators = []
26
+
16
27
  url = serializers.HyperlinkedIdentityField(
17
28
  view_name="plugins-api:netbox_dns-api:zone-detail"
18
29
  )
@@ -9,51 +9,51 @@ from netaddr import AddrFormatError, IPNetwork
9
9
  class NetContains(Lookup):
10
10
  lookup_name = "net_contains"
11
11
 
12
- def as_sql(self, compiler, connection):
13
- lhs, lhs_params = self.process_lhs(compiler, connection)
14
- rhs, rhs_params = self.process_rhs(compiler, connection)
12
+ def as_sql(self, qn, connection):
13
+ lhs, lhs_params = self.process_lhs(qn, connection)
14
+ rhs, rhs_params = self.process_rhs(qn, connection)
15
15
  params = lhs_params + rhs_params
16
- return f"{lhs} >> {rhs}", params
16
+ return "%s >> %s" % (lhs, rhs), params
17
17
 
18
18
 
19
19
  class NetContainsOrEquals(Lookup):
20
20
  lookup_name = "net_contains_or_equals"
21
21
 
22
- def as_sql(self, compiler, connection):
23
- lhs, lhs_params = self.process_lhs(compiler, connection)
24
- rhs, rhs_params = self.process_rhs(compiler, connection)
22
+ def as_sql(self, qn, connection):
23
+ lhs, lhs_params = self.process_lhs(qn, connection)
24
+ rhs, rhs_params = self.process_rhs(qn, connection)
25
25
  params = lhs_params + rhs_params
26
- return f"{lhs} >>= {rhs}", params
26
+ return "%s >>= %s" % (lhs, rhs), params
27
27
 
28
28
 
29
29
  class NetContained(Lookup):
30
30
  lookup_name = "net_contained"
31
31
 
32
- def as_sql(self, compiler, connection):
33
- lhs, lhs_params = self.process_lhs(compiler, connection)
34
- rhs, rhs_params = self.process_rhs(compiler, connection)
32
+ def as_sql(self, qn, connection):
33
+ lhs, lhs_params = self.process_lhs(qn, connection)
34
+ rhs, rhs_params = self.process_rhs(qn, connection)
35
35
  params = lhs_params + rhs_params
36
- return f"{lhs} << {rhs}", params
36
+ return "%s << %s" % (lhs, rhs), params
37
37
 
38
38
 
39
39
  class NetContainedOrEqual(Lookup):
40
40
  lookup_name = "net_contained_or_equal"
41
41
 
42
- def as_sql(self, compiler, connection):
43
- lhs, lhs_params = self.process_lhs(compiler, connection)
44
- rhs, rhs_params = self.process_rhs(compiler, connection)
42
+ def as_sql(self, qn, connection):
43
+ lhs, lhs_params = self.process_lhs(qn, connection)
44
+ rhs, rhs_params = self.process_rhs(qn, connection)
45
45
  params = lhs_params + rhs_params
46
- return f"{lhs} <<= {rhs}", params
46
+ return "%s <<= %s" % (lhs, rhs), params
47
47
 
48
48
 
49
49
  class NetOverlap(Lookup):
50
50
  lookup_name = "net_overlap"
51
51
 
52
- def as_sql(self, compiler, connection):
53
- lhs, lhs_params = self.process_lhs(compiler, connection)
54
- rhs, rhs_params = self.process_rhs(compiler, connection)
52
+ def as_sql(self, qn, connection):
53
+ lhs, lhs_params = self.process_lhs(qn, connection)
54
+ rhs, rhs_params = self.process_rhs(qn, connection)
55
55
  params = lhs_params + rhs_params
56
- return f"{lhs} && {rhs}", params
56
+ return "%s && %s" % (lhs, rhs), params
57
57
 
58
58
 
59
59
  class NetworkFormField(forms.Field):
@@ -118,6 +118,7 @@ class NetMaskLength(Transform):
118
118
  function = "MASKLEN"
119
119
  lookup_name = "net_mask_length"
120
120
 
121
+ @property
121
122
  def output_field(self):
122
123
  return IntegerField()
123
124
 
@@ -18,8 +18,8 @@ class RFC2317NetworkFormField(forms.Field):
18
18
  if isinstance(value, IPNetwork):
19
19
  if value.version == 4 and value.prefixlen > 24:
20
20
  return value
21
-
22
- raise ValidationError(INVALID_RFC2317)
21
+ else:
22
+ raise ValidationError(INVALID_RFC2317)
23
23
 
24
24
  if len(value.split("/")) != 2:
25
25
  raise ValidationError("Please specify the prefix length")
@@ -9,7 +9,7 @@ from netbox_dns.models import View
9
9
  class ViewFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
10
10
  class Meta:
11
11
  model = View
12
- fields = ("id", "name", "default_view", "description")
12
+ fields = ("id", "name", "description")
13
13
 
14
14
  def search(self, queryset, name, value):
15
15
  if not value.strip():
@@ -31,14 +31,14 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
31
31
  to_field_name="name",
32
32
  label="View",
33
33
  )
34
- # DEPRECATED: Remove in 1.1
34
+ # DEPRECATED: Remove in 1.0
35
35
  name_server_id = django_filters.ModelMultipleChoiceFilter(
36
36
  queryset=NameServer.objects.all(),
37
37
  field_name="nameservers",
38
38
  to_field_name="id",
39
39
  label="Nameserver IDs",
40
40
  )
41
- # DEPRECATED: Remove in 1.1
41
+ # DEPRECATED: Remove in 1.0
42
42
  name_server = django_filters.ModelMultipleChoiceFilter(
43
43
  queryset=NameServer.objects.all(),
44
44
  field_name="nameservers__name",
@@ -59,13 +59,13 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
59
59
  )
60
60
  soa_mname_id = django_filters.ModelMultipleChoiceFilter(
61
61
  queryset=NameServer.objects.all(),
62
- label="SOA MName ID",
62
+ label="SOA MNname ID",
63
63
  )
64
64
  soa_mname = django_filters.ModelMultipleChoiceFilter(
65
65
  queryset=NameServer.objects.all(),
66
66
  field_name="soa_mname__name",
67
67
  to_field_name="name",
68
- label="SOA MName",
68
+ label="SOA MNname",
69
69
  )
70
70
  arpa_network = MultiValueCharFilter(
71
71
  method="filter_arpa_network",
@@ -28,30 +28,10 @@ class RecordForm(TenancyForm, NetBoxModelForm):
28
28
  def __init__(self, *args, **kwargs):
29
29
  super().__init__(*args, **kwargs)
30
30
 
31
- initial_zone_id = self.initial.get("zone")
32
- if initial_zone_id is not None:
33
- self.initial["view"] = Zone.objects.get(pk=initial_zone_id).view
34
- else:
35
- self.initial["view"] = View.get_default_view()
36
-
37
31
  initial_name = self.initial.get("name")
38
32
  if initial_name:
39
33
  self.initial["name"] = name_to_unicode(initial_name)
40
34
 
41
- view = DynamicModelChoiceField(
42
- queryset=View.objects.all(),
43
- required=False,
44
- label="View",
45
- )
46
- zone = DynamicModelChoiceField(
47
- queryset=Zone.objects.all(),
48
- required=True,
49
- query_params={
50
- "view_id": "$view",
51
- },
52
- label="Zone",
53
- )
54
-
55
35
  disable_ptr = forms.BooleanField(
56
36
  label="Disable PTR",
57
37
  required=False,
@@ -64,7 +44,6 @@ class RecordForm(TenancyForm, NetBoxModelForm):
64
44
  fieldsets = (
65
45
  FieldSet(
66
46
  "name",
67
- "view",
68
47
  "zone",
69
48
  "type",
70
49
  "value",
@@ -105,7 +84,6 @@ class RecordFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
105
84
  "fqdn",
106
85
  "type",
107
86
  "value",
108
- "disable_ptr",
109
87
  "status",
110
88
  "description",
111
89
  name="Attributes",
@@ -127,10 +105,6 @@ class RecordFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
127
105
  value = forms.CharField(
128
106
  required=False,
129
107
  )
130
- disable_ptr = forms.NullBooleanField(
131
- required=False,
132
- label="Disable PTR",
133
- )
134
108
  status = forms.MultipleChoiceField(
135
109
  choices=RecordStatusChoices,
136
110
  required=False,
@@ -157,12 +131,10 @@ class RecordImportForm(NetBoxModelImportForm):
157
131
  except forms.ValidationError:
158
132
  pass
159
133
 
160
- if view is not None:
134
+ if view:
161
135
  self.fields["zone"].queryset = Zone.objects.filter(view=view)
162
136
  else:
163
- self.fields["zone"].queryset = Zone.objects.filter(
164
- view=View.get_default_view()
165
- )
137
+ self.fields["zone"].queryset = Zone.objects.filter(view__isnull=True)
166
138
 
167
139
  zone = CSVModelChoiceField(
168
140
  queryset=Zone.objects.all(),
netbox_dns/forms/view.py CHANGED
@@ -20,29 +20,26 @@ from netbox_dns.models import View
20
20
 
21
21
  class ViewForm(TenancyForm, NetBoxModelForm):
22
22
  fieldsets = (
23
- FieldSet("name", "default_view", "description", "tags", name="View"),
23
+ FieldSet("name", "description", "tags", name="View"),
24
24
  FieldSet("tenant_group", "tenant", name="Tenancy"),
25
25
  )
26
26
 
27
27
  class Meta:
28
28
  model = View
29
- fields = ("name", "default_view", "description", "tags", "tenant")
29
+ fields = ("name", "description", "tags", "tenant")
30
30
 
31
31
 
32
32
  class ViewFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
33
33
  model = View
34
34
  fieldsets = (
35
35
  FieldSet("q", "filter_id", "tag"),
36
- FieldSet("name", "default_view", "description", name="Attributes"),
36
+ FieldSet("name", "description", name="Attributes"),
37
37
  FieldSet("tenant_group_id", "tenant_id", name="Tenancy"),
38
38
  )
39
39
 
40
40
  name = forms.CharField(
41
41
  required=False,
42
42
  )
43
- default_view = forms.NullBooleanField(
44
- required=False,
45
- )
46
43
  description = forms.CharField(
47
44
  required=False,
48
45
  )
netbox_dns/forms/zone.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from django import forms
2
2
  from django.conf import settings
3
+ from django.core.exceptions import ValidationError
3
4
  from django.core.validators import MinValueValidator, MaxValueValidator
4
5
  from django.urls import reverse_lazy
5
6
 
@@ -55,7 +56,7 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
55
56
  )
56
57
  soa_rname = forms.CharField(
57
58
  required=True,
58
- label="SOA RName",
59
+ label="SOA Responsible",
59
60
  help_text="Mailbox of the zone's administrator",
60
61
  )
61
62
  soa_serial_auto = forms.BooleanField(
@@ -146,16 +147,19 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
146
147
  )
147
148
 
148
149
  def __init__(self, *args, **kwargs):
150
+ """Override the __init__ method in order to provide the initial value for the default fields"""
149
151
  super().__init__(*args, **kwargs)
150
152
 
151
153
  initial_name = self.initial.get("name")
152
154
  if initial_name:
153
155
  self.initial["name"] = name_to_unicode(initial_name)
154
156
 
155
- if self.initial.get("view") is None:
156
- self.initial["view"] = View.get_default_view()
157
-
158
157
  defaults = settings.PLUGINS_CONFIG.get("netbox_dns")
158
+
159
+ def _initialize(initial, setting):
160
+ if initial.get(setting, None) in (None, ""):
161
+ initial[setting] = defaults.get(f"zone_{setting}", None)
162
+
159
163
  for setting in (
160
164
  "default_ttl",
161
165
  "soa_ttl",
@@ -166,17 +170,16 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
166
170
  "soa_expire",
167
171
  "soa_minimum",
168
172
  ):
169
- if self.initial.get(setting) in (None, ""):
170
- self.initial[setting] = defaults.get(f"zone_{setting}")
173
+ _initialize(self.initial, setting)
171
174
 
172
- if self.initial.get("soa_ttl") is None:
173
- self.initial["soa_ttl"] = self.initial.get("default_ttl")
175
+ if self.initial.get("soa_ttl", None) is None:
176
+ self.initial["soa_ttl"] = self.initial.get("default_ttl", None)
174
177
 
175
178
  if self.initial.get("soa_serial_auto"):
176
179
  self.initial["soa_serial"] = None
177
180
 
178
- if self.initial.get("soa_mname") is None:
179
- default_soa_mname = defaults.get("zone_soa_mname")
181
+ if self.initial.get("soa_mname", None) in (None, ""):
182
+ default_soa_mname = defaults.get("zone_soa_mname", None)
180
183
  if default_soa_mname is not None:
181
184
  try:
182
185
  self.initial["soa_mname"] = NameServer.objects.get(
@@ -242,18 +245,6 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
242
245
  FieldSet(
243
246
  "view_id", "status", "name", "nameservers", "description", name="Attributes"
244
247
  ),
245
- FieldSet(
246
- "soa_mname_id",
247
- "soa_rname",
248
- "soa_serial_auto",
249
- name="SOA",
250
- ),
251
- FieldSet(
252
- "rfc2317_prefix",
253
- "rfc2317_parent_managed",
254
- "rfc2317_parent_zone_id",
255
- name="RFC2317",
256
- ),
257
248
  FieldSet(
258
249
  "registrar_id",
259
250
  "registry_domain_id",
@@ -285,32 +276,6 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
285
276
  description = forms.CharField(
286
277
  required=False,
287
278
  )
288
- soa_mname_id = DynamicModelMultipleChoiceField(
289
- queryset=NameServer.objects.all(),
290
- label="MName",
291
- required=False,
292
- )
293
- soa_rname = forms.CharField(
294
- required=False,
295
- label="RName",
296
- )
297
- soa_serial_auto = forms.NullBooleanField(
298
- required=False,
299
- label="Generate Serial",
300
- )
301
- rfc2317_prefix = RFC2317NetworkFormField(
302
- required=False,
303
- label="Prefix",
304
- )
305
- rfc2317_parent_managed = forms.NullBooleanField(
306
- required=False,
307
- label="Parent Managed",
308
- )
309
- rfc2317_parent_zone_id = DynamicModelMultipleChoiceField(
310
- queryset=Zone.objects.all(),
311
- required=False,
312
- label="Parent Zone",
313
- )
314
279
  registrar_id = DynamicModelMultipleChoiceField(
315
280
  queryset=Registrar.objects.all(),
316
281
  required=False,
@@ -474,6 +439,87 @@ class ZoneImportForm(NetBoxModelImportForm):
474
439
  help_text="Assigned tenant",
475
440
  )
476
441
 
442
+ def _get_default_value(self, field):
443
+ _default_values = settings.PLUGINS_CONFIG.get("netbox_dns", {})
444
+ if _default_values.get("zone_soa_ttl", None) is None:
445
+ _default_values["zone_soa_ttl"] = _default_values.get(
446
+ "zone_default_ttl", None
447
+ )
448
+
449
+ return _default_values.get(f"zone_{field}", None)
450
+
451
+ def _clean_field_with_defaults(self, field):
452
+ if self.cleaned_data[field]:
453
+ value = self.cleaned_data[field]
454
+ else:
455
+ value = self._get_default_value(field)
456
+
457
+ if value is None:
458
+ raise ValidationError(f"{field} not set and no default value available")
459
+
460
+ return value
461
+
462
+ def clean_default_ttl(self):
463
+ return self._clean_field_with_defaults("default_ttl")
464
+
465
+ def clean_soa_ttl(self):
466
+ return self._clean_field_with_defaults("soa_ttl")
467
+
468
+ def clean_soa_mname(self):
469
+ soa_mname = self._clean_field_with_defaults("soa_mname")
470
+ if isinstance(soa_mname, str):
471
+ try:
472
+ soa_mname = NameServer.objects.get(name=soa_mname)
473
+ except NameServer.DoesNotExist:
474
+ raise ValidationError(f"Default name server {soa_mname} does not exist")
475
+
476
+ return soa_mname
477
+
478
+ def clean_soa_rname(self):
479
+ return self._clean_field_with_defaults("soa_rname")
480
+
481
+ def clean_soa_refresh(self):
482
+ return self._clean_field_with_defaults("soa_refresh")
483
+
484
+ def clean_soa_retry(self):
485
+ return self._clean_field_with_defaults("soa_retry")
486
+
487
+ def clean_soa_expire(self):
488
+ return self._clean_field_with_defaults("soa_expire")
489
+
490
+ def clean_soa_minimum(self):
491
+ return self._clean_field_with_defaults("soa_minimum")
492
+
493
+ def clean(self, *args, **kwargs):
494
+ super().clean(*args, **kwargs)
495
+
496
+ soa_serial_auto = self.cleaned_data.get("soa_serial_auto")
497
+ soa_serial = self.cleaned_data.get("soa_serial")
498
+
499
+ if soa_serial is None:
500
+ soa_serial = self._get_default_value("soa_serial")
501
+
502
+ if soa_serial_auto is None:
503
+ if self._get_default_value("soa_serial_auto") is not None:
504
+ soa_serial_auto = self._get_default_value("soa_serial_auto")
505
+
506
+ elif soa_serial is not None:
507
+ soa_serial_auto = False
508
+
509
+ else:
510
+ raise ValidationError(
511
+ "SOA Serial Auto not set and no default value and SOA Serial available"
512
+ )
513
+
514
+ if "soa_serial_auto" in self.cleaned_data:
515
+ self.cleaned_data["soa_serial_auto"] = soa_serial_auto
516
+
517
+ if "soa_serial" in self.cleaned_data:
518
+ if soa_serial_auto:
519
+ self.cleaned_data["soa_serial"] = None
520
+ else:
521
+ self.cleaned_data["soa_serial"] = soa_serial
522
+
477
523
  class Meta:
478
524
  model = Zone
479
525
 
@@ -505,27 +551,6 @@ class ZoneImportForm(NetBoxModelImportForm):
505
551
  "tags",
506
552
  )
507
553
 
508
- def clean_view(self):
509
- view = self.cleaned_data.get("view")
510
- if view is None:
511
- return View.get_default_view()
512
-
513
- return view
514
-
515
- def clean_nameservers(self):
516
- nameservers = self.cleaned_data.get("nameservers")
517
- zone_defaults = settings.PLUGINS_CONFIG.get("netbox_dns")
518
-
519
- if (
520
- self.data.get("nameservers") is None
521
- and zone_defaults.get("zone_nameservers") is not None
522
- ):
523
- nameservers = NameServer.objects.filter(
524
- name__in=zone_defaults.get("zone_nameservers")
525
- )
526
-
527
- return nameservers
528
-
529
554
 
530
555
  class ZoneBulkEditForm(NetBoxModelBulkEditForm):
531
556
  view = DynamicModelChoiceField(
@@ -567,7 +592,7 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
567
592
  )
568
593
  soa_rname = forms.CharField(
569
594
  required=False,
570
- label="SOA RName",
595
+ label="SOA Responsible",
571
596
  )
572
597
  soa_serial_auto = forms.NullBooleanField(
573
598
  required=False,
@@ -704,6 +729,7 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
704
729
  )
705
730
 
706
731
  nullable_fields = (
732
+ "view",
707
733
  "description",
708
734
  "rfc2317_prefix",
709
735
  "registrar",
@@ -713,3 +739,8 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
713
739
  "tech_c",
714
740
  "billing_c",
715
741
  )
742
+
743
+ def clean(self):
744
+ cleaned_data = super().clean()
745
+ if cleaned_data.get("soa_serial_auto"):
746
+ cleaned_data["soa_serial"] = None
@@ -36,7 +36,10 @@ class NetBoxDNSZoneType(NetBoxObjectType):
36
36
  name: str
37
37
  status: str
38
38
  active: bool
39
- view: Annotated["NetBoxDNSViewType", strawberry.lazy("netbox_dns.graphql.types")]
39
+ view: (
40
+ Annotated["NetBoxDNSViewType", strawberry.lazy("netbox_dns.graphql.types")]
41
+ | None
42
+ )
40
43
  nameservers: (
41
44
  Annotated[
42
45
  "NetBoxDNSNameServerType", strawberry.lazy("netbox_dns.graphql.types")
@@ -32,7 +32,7 @@ class Command(BaseCommand):
32
32
  ttl_records = (
33
33
  Record.objects.filter(ttl__isnull=False)
34
34
  .exclude(type=RecordTypeChoices.SOA)
35
- .exclude(type=RecordTypeChoices.PTR, managed=True)
35
+ .exclude(type=RecordTypeChoices.PTR, maanged=True)
36
36
  )
37
37
  for record in ttl_records:
38
38
  records = Record.objects.filter(
@@ -1,7 +1,5 @@
1
1
  # Generated by Django 5.0.1 on 2024-02-12 14:49
2
2
 
3
- from dns import name as dns_name
4
-
5
3
  import django.core.validators
6
4
  import django.db.models.deletion
7
5
  import netbox_dns.fields.address
@@ -50,9 +48,9 @@ def update_record_fqdn(apps, schema_editor):
50
48
 
51
49
  for record in Record.objects.filter(fqdn__isnull=True):
52
50
  zone = dns_name.from_text(record.zone.name, origin=dns_name.root)
53
- _fqdn = dns_name.from_text(record.name, origin=zone)
51
+ fqdn = dns_name.from_text(record.name, origin=zone)
54
52
 
55
- record.fqdn = _fqdn.to_text()
53
+ record.fqdn = fqdn.to_text()
56
54
 
57
55
  record.save()
58
56
 
@@ -55,7 +55,7 @@ class NameServer(NetBoxModel):
55
55
  def get_absolute_url(self):
56
56
  return reverse("plugins:netbox_dns:nameserver", kwargs={"pk": self.pk})
57
57
 
58
- def clean(self, *args, **kwargs):
58
+ def clean(self):
59
59
  try:
60
60
  self.name = normalize_name(self.name)
61
61
  except NameFormatError as exc:
@@ -74,8 +74,6 @@ class NameServer(NetBoxModel):
74
74
  }
75
75
  ) from None
76
76
 
77
- super().clean(*args, **kwargs)
78
-
79
77
  def save(self, *args, **kwargs):
80
78
  self.full_clean()
81
79