netbox-plugin-dns 1.0.0__py3-none-any.whl → 1.0b2__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 -3
- netbox_dns/api/serializers_/view.py +1 -6
- netbox_dns/fields/network.py +21 -20
- netbox_dns/fields/rfc2317.py +2 -2
- netbox_dns/filtersets/view.py +1 -1
- netbox_dns/filtersets/zone.py +4 -4
- netbox_dns/forms/record.py +2 -30
- netbox_dns/forms/view.py +3 -6
- netbox_dns/forms/zone.py +101 -70
- netbox_dns/graphql/types.py +4 -1
- netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +2 -4
- netbox_dns/models/nameserver.py +1 -3
- netbox_dns/models/record.py +23 -24
- netbox_dns/models/view.py +0 -53
- netbox_dns/models/zone.py +46 -63
- netbox_dns/signals/ipam_coupling.py +2 -1
- netbox_dns/tables/view.py +2 -9
- netbox_dns/template_content.py +1 -1
- netbox_dns/templates/netbox_dns/record.html +1 -1
- netbox_dns/templates/netbox_dns/view.html +0 -4
- netbox_dns/templates/netbox_dns/zone.html +4 -2
- netbox_dns/urls.py +297 -0
- netbox_dns/views/record.py +18 -10
- {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b2.dist-info}/METADATA +14 -16
- {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b2.dist-info}/RECORD +27 -36
- netbox_dns/migrations/0003_default_view.py +0 -15
- netbox_dns/migrations/0004_create_and_assign_default_view.py +0 -26
- netbox_dns/migrations/0005_alter_zone_view_not_null.py +0 -18
- netbox_dns/urls/__init__.py +0 -17
- netbox_dns/urls/contact.py +0 -51
- netbox_dns/urls/nameserver.py +0 -69
- netbox_dns/urls/record.py +0 -41
- netbox_dns/urls/registrar.py +0 -63
- netbox_dns/urls/view.py +0 -39
- netbox_dns/urls/zone.py +0 -57
- {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b2.dist-info}/LICENSE +0 -0
- {netbox_plugin_dns-1.0.0.dist-info → netbox_plugin_dns-1.0b2.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
|
|
3
|
+
__version__ = "1.0-beta2"
|
|
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
|
|
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
|
-
"
|
|
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", "
|
|
29
|
+
brief_fields = ("id", "url", "display", "name", "description")
|
netbox_dns/fields/network.py
CHANGED
|
@@ -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,
|
|
13
|
-
lhs, lhs_params = self.process_lhs(
|
|
14
|
-
rhs, rhs_params = self.process_rhs(
|
|
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
|
|
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,
|
|
23
|
-
lhs, lhs_params = self.process_lhs(
|
|
24
|
-
rhs, rhs_params = self.process_rhs(
|
|
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
|
|
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,
|
|
33
|
-
lhs, lhs_params = self.process_lhs(
|
|
34
|
-
rhs, rhs_params = self.process_rhs(
|
|
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
|
|
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,
|
|
43
|
-
lhs, lhs_params = self.process_lhs(
|
|
44
|
-
rhs, rhs_params = self.process_rhs(
|
|
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
|
|
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,
|
|
53
|
-
lhs, lhs_params = self.process_lhs(
|
|
54
|
-
rhs, rhs_params = self.process_rhs(
|
|
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
|
|
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
|
|
netbox_dns/fields/rfc2317.py
CHANGED
|
@@ -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
|
-
|
|
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")
|
netbox_dns/filtersets/view.py
CHANGED
|
@@ -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", "
|
|
12
|
+
fields = ("id", "name", "description")
|
|
13
13
|
|
|
14
14
|
def search(self, queryset, name, value):
|
|
15
15
|
if not value.strip():
|
netbox_dns/filtersets/zone.py
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
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
|
|
68
|
+
label="SOA MNname",
|
|
69
69
|
)
|
|
70
70
|
arpa_network = MultiValueCharFilter(
|
|
71
71
|
method="filter_arpa_network",
|
netbox_dns/forms/record.py
CHANGED
|
@@ -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
|
|
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", "
|
|
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", "
|
|
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", "
|
|
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
|
|
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
|
-
|
|
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")
|
|
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
|
|
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
|
netbox_dns/graphql/types.py
CHANGED
|
@@ -36,7 +36,10 @@ class NetBoxDNSZoneType(NetBoxObjectType):
|
|
|
36
36
|
name: str
|
|
37
37
|
status: str
|
|
38
38
|
active: bool
|
|
39
|
-
view:
|
|
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")
|
|
@@ -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
|
-
|
|
51
|
+
fqdn = dns_name.from_text(record.name, origin=zone)
|
|
54
52
|
|
|
55
|
-
record.fqdn =
|
|
53
|
+
record.fqdn = fqdn.to_text()
|
|
56
54
|
|
|
57
55
|
record.save()
|
|
58
56
|
|
netbox_dns/models/nameserver.py
CHANGED
|
@@ -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
|
|
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
|
|