netbox-plugin-dns 1.0.4__py3-none-any.whl → 1.0.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 +1 -1
- netbox_dns/api/nested_serializers.py +46 -1
- netbox_dns/api/serializers.py +2 -0
- netbox_dns/api/serializers_/contact.py +3 -0
- netbox_dns/api/serializers_/nameserver.py +4 -1
- netbox_dns/api/serializers_/record.py +5 -4
- netbox_dns/api/serializers_/record_template.py +57 -0
- netbox_dns/api/serializers_/registrar.py +3 -0
- netbox_dns/api/serializers_/view.py +3 -0
- netbox_dns/api/serializers_/zone.py +30 -6
- netbox_dns/api/serializers_/zone_template.py +129 -0
- netbox_dns/api/urls.py +4 -0
- netbox_dns/api/views.py +41 -1
- netbox_dns/choices/__init__.py +2 -0
- netbox_dns/choices/record.py +49 -0
- netbox_dns/choices/zone.py +20 -0
- netbox_dns/fields/address.py +6 -0
- netbox_dns/fields/network.py +3 -0
- netbox_dns/fields/rfc2317.py +3 -0
- netbox_dns/filtersets/__init__.py +3 -0
- netbox_dns/filtersets/contact.py +3 -0
- netbox_dns/filtersets/nameserver.py +3 -0
- netbox_dns/filtersets/record.py +5 -1
- netbox_dns/filtersets/record_template.py +54 -0
- netbox_dns/filtersets/registrar.py +3 -0
- netbox_dns/filtersets/view.py +3 -0
- netbox_dns/filtersets/zone.py +5 -8
- netbox_dns/filtersets/zone_template.py +116 -0
- netbox_dns/forms/__init__.py +2 -0
- netbox_dns/forms/contact.py +8 -0
- netbox_dns/forms/nameserver.py +8 -0
- netbox_dns/forms/record.py +25 -11
- netbox_dns/forms/record_template.py +220 -0
- netbox_dns/forms/registrar.py +8 -0
- netbox_dns/forms/view.py +10 -0
- netbox_dns/forms/zone.py +109 -36
- netbox_dns/forms/zone_template.py +298 -0
- netbox_dns/graphql/__init__.py +4 -0
- netbox_dns/graphql/filters.py +24 -1
- netbox_dns/graphql/schema.py +34 -1
- netbox_dns/graphql/types.py +70 -1
- netbox_dns/management/commands/cleanup_database.py +2 -6
- netbox_dns/management/commands/cleanup_rrset_ttl.py +2 -4
- netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +1 -2
- netbox_dns/migrations/0006_templating.py +172 -0
- netbox_dns/migrations/0021_record_ip_address.py +1 -1
- netbox_dns/mixins/object_modification.py +3 -0
- netbox_dns/models/__init__.py +7 -0
- netbox_dns/models/contact.py +6 -0
- netbox_dns/models/nameserver.py +8 -1
- netbox_dns/models/record.py +10 -122
- netbox_dns/models/record_template.py +180 -0
- netbox_dns/models/registrar.py +6 -0
- netbox_dns/models/view.py +7 -1
- netbox_dns/models/zone.py +57 -66
- netbox_dns/models/zone_template.py +149 -0
- netbox_dns/navigation.py +47 -0
- netbox_dns/tables/__init__.py +2 -0
- netbox_dns/tables/contact.py +3 -0
- netbox_dns/tables/nameserver.py +3 -2
- netbox_dns/tables/record.py +7 -3
- netbox_dns/tables/record_template.py +91 -0
- netbox_dns/tables/registrar.py +3 -0
- netbox_dns/tables/view.py +3 -0
- netbox_dns/tables/zone.py +3 -2
- netbox_dns/tables/zone_template.py +70 -0
- netbox_dns/template_content.py +2 -8
- netbox_dns/templates/netbox_dns/recordtemplate.html +84 -0
- netbox_dns/templates/netbox_dns/zonetemplate.html +86 -0
- netbox_dns/urls/__init__.py +4 -0
- netbox_dns/urls/record_template.py +65 -0
- netbox_dns/urls/zone_template.py +57 -0
- netbox_dns/utilities/ipam_coupling.py +2 -1
- netbox_dns/validators/__init__.py +1 -0
- netbox_dns/validators/dns_name.py +14 -9
- netbox_dns/validators/dns_value.py +83 -0
- netbox_dns/validators/rfc2317.py +7 -0
- netbox_dns/views/__init__.py +2 -0
- netbox_dns/views/contact.py +11 -0
- netbox_dns/views/nameserver.py +12 -0
- netbox_dns/views/record.py +14 -1
- netbox_dns/views/record_template.py +83 -0
- netbox_dns/views/registrar.py +12 -0
- netbox_dns/views/view.py +12 -0
- netbox_dns/views/zone.py +16 -0
- netbox_dns/views/zone_template.py +73 -0
- {netbox_plugin_dns-1.0.4.dist-info → netbox_plugin_dns-1.0.5.dist-info}/METADATA +2 -1
- netbox_plugin_dns-1.0.5.dist-info/RECORD +136 -0
- netbox_plugin_dns-1.0.4.dist-info/RECORD +0 -115
- {netbox_plugin_dns-1.0.4.dist-info → netbox_plugin_dns-1.0.5.dist-info}/LICENSE +0 -0
- {netbox_plugin_dns-1.0.4.dist-info → netbox_plugin_dns-1.0.5.dist-info}/WHEEL +0 -0
netbox_dns/graphql/types.py
CHANGED
|
@@ -6,7 +6,16 @@ import strawberry_django
|
|
|
6
6
|
from netbox.graphql.types import NetBoxObjectType
|
|
7
7
|
from netbox.graphql.scalars import BigInt
|
|
8
8
|
|
|
9
|
-
from netbox_dns.models import
|
|
9
|
+
from netbox_dns.models import (
|
|
10
|
+
NameServer,
|
|
11
|
+
View,
|
|
12
|
+
Zone,
|
|
13
|
+
Record,
|
|
14
|
+
Contact,
|
|
15
|
+
Registrar,
|
|
16
|
+
ZoneTemplate,
|
|
17
|
+
RecordTemplate,
|
|
18
|
+
)
|
|
10
19
|
from .filters import (
|
|
11
20
|
NetBoxDNSNameServerFilter,
|
|
12
21
|
NetBoxDNSViewFilter,
|
|
@@ -14,6 +23,8 @@ from .filters import (
|
|
|
14
23
|
NetBoxDNSRecordFilter,
|
|
15
24
|
NetBoxDNSContactFilter,
|
|
16
25
|
NetBoxDNSRegistrarFilter,
|
|
26
|
+
NetBoxDNSZoneTemplateFilter,
|
|
27
|
+
NetBoxDNSRecordTemplateFilter,
|
|
17
28
|
)
|
|
18
29
|
|
|
19
30
|
|
|
@@ -140,3 +151,61 @@ class NetBoxDNSRegistrarType(NetBoxObjectType):
|
|
|
140
151
|
address: str
|
|
141
152
|
abuse_email: str
|
|
142
153
|
abuse_phone: str
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@strawberry_django.type(
|
|
157
|
+
ZoneTemplate, fields="__all__", filters=NetBoxDNSZoneTemplateFilter
|
|
158
|
+
)
|
|
159
|
+
class NetBoxDNSZoneTemplateType(NetBoxObjectType):
|
|
160
|
+
name: str
|
|
161
|
+
nameservers: List[
|
|
162
|
+
Annotated[
|
|
163
|
+
"NetBoxDNSNameServerType", strawberry.lazy("netbox_dns.graphql.types")
|
|
164
|
+
]
|
|
165
|
+
]
|
|
166
|
+
record_templates: List[
|
|
167
|
+
Annotated[
|
|
168
|
+
"NetBoxDNSRecordTemplateType", strawberry.lazy("netbox_dns.graphql.types")
|
|
169
|
+
]
|
|
170
|
+
]
|
|
171
|
+
description: str | None
|
|
172
|
+
tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
|
|
173
|
+
registrar: (
|
|
174
|
+
Annotated["NetBoxDNSRegistrarType", strawberry.lazy("netbox_dns.graphql.types")]
|
|
175
|
+
| None
|
|
176
|
+
)
|
|
177
|
+
registrant: (
|
|
178
|
+
Annotated["NetBoxDNSContactType", strawberry.lazy("netbox_dns.graphql.types")]
|
|
179
|
+
| None
|
|
180
|
+
)
|
|
181
|
+
admin_c: (
|
|
182
|
+
Annotated["NetBoxDNSContactType", strawberry.lazy("netbox_dns.graphql.types")]
|
|
183
|
+
| None
|
|
184
|
+
)
|
|
185
|
+
tech_c: (
|
|
186
|
+
Annotated["NetBoxDNSContactType", strawberry.lazy("netbox_dns.graphql.types")]
|
|
187
|
+
| None
|
|
188
|
+
)
|
|
189
|
+
billing_c: (
|
|
190
|
+
Annotated["NetBoxDNSContactType", strawberry.lazy("netbox_dns.graphql.types")]
|
|
191
|
+
| None
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@strawberry_django.type(
|
|
196
|
+
RecordTemplate, fields="__all__", filters=NetBoxDNSRecordTemplateFilter
|
|
197
|
+
)
|
|
198
|
+
class NetBoxDNSRecordTemplateType(NetBoxObjectType):
|
|
199
|
+
name: str
|
|
200
|
+
record_name: str
|
|
201
|
+
type: str
|
|
202
|
+
value: str
|
|
203
|
+
ttl: BigInt | None
|
|
204
|
+
disable_ptr: bool
|
|
205
|
+
description: str | None
|
|
206
|
+
tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
|
|
207
|
+
zone_templates: List[
|
|
208
|
+
Annotated[
|
|
209
|
+
"NetBoxDNSZoneTemplateType", strawberry.lazy("netbox_dns.graphql.types")
|
|
210
|
+
]
|
|
211
|
+
]
|
|
@@ -2,12 +2,8 @@ from netaddr import IPAddress, IPNetwork, AddrFormatError
|
|
|
2
2
|
|
|
3
3
|
from django.core.management.base import BaseCommand
|
|
4
4
|
|
|
5
|
-
from netbox_dns.models import
|
|
6
|
-
|
|
7
|
-
ZoneStatusChoices,
|
|
8
|
-
Record,
|
|
9
|
-
RecordTypeChoices,
|
|
10
|
-
)
|
|
5
|
+
from netbox_dns.models import Zone, Record
|
|
6
|
+
from netbox_dns.choices import ZoneStatusChoices, RecordTypeChoices
|
|
11
7
|
|
|
12
8
|
|
|
13
9
|
def zone_rename_passive_status_to_parked(verbose=False):
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
from django.core.management.base import BaseCommand
|
|
2
2
|
from django.db.models import Max, Min
|
|
3
3
|
|
|
4
|
-
from netbox_dns.models import
|
|
5
|
-
|
|
6
|
-
RecordTypeChoices,
|
|
7
|
-
)
|
|
4
|
+
from netbox_dns.models import Record
|
|
5
|
+
from netbox_dns.choices import RecordTypeChoices
|
|
8
6
|
|
|
9
7
|
|
|
10
8
|
class Command(BaseCommand):
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Generated by Django 5.0.7 on 2024-07-12 11:38
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
import taggit.managers
|
|
5
|
+
import utilities.json
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
("extras", "0115_convert_dashboard_widgets"),
|
|
13
|
+
("netbox_dns", "0005_alter_zone_view_not_null"),
|
|
14
|
+
("tenancy", "0015_contactassignment_rename_content_type"),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
operations = [
|
|
18
|
+
migrations.CreateModel(
|
|
19
|
+
name="RecordTemplate",
|
|
20
|
+
fields=[
|
|
21
|
+
(
|
|
22
|
+
"id",
|
|
23
|
+
models.BigAutoField(
|
|
24
|
+
auto_created=True, primary_key=True, serialize=False
|
|
25
|
+
),
|
|
26
|
+
),
|
|
27
|
+
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
|
28
|
+
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
|
29
|
+
(
|
|
30
|
+
"custom_field_data",
|
|
31
|
+
models.JSONField(
|
|
32
|
+
blank=True,
|
|
33
|
+
default=dict,
|
|
34
|
+
encoder=utilities.json.CustomFieldJSONEncoder,
|
|
35
|
+
),
|
|
36
|
+
),
|
|
37
|
+
("name", models.CharField(max_length=200, unique=True)),
|
|
38
|
+
("record_name", models.CharField(max_length=255)),
|
|
39
|
+
("description", models.CharField(blank=True, max_length=200)),
|
|
40
|
+
("type", models.CharField()),
|
|
41
|
+
("value", models.CharField(max_length=65535)),
|
|
42
|
+
("status", models.CharField(default="active")),
|
|
43
|
+
("ttl", models.PositiveIntegerField(blank=True, null=True)),
|
|
44
|
+
("disable_ptr", models.BooleanField(default=False)),
|
|
45
|
+
(
|
|
46
|
+
"tags",
|
|
47
|
+
taggit.managers.TaggableManager(
|
|
48
|
+
through="extras.TaggedItem", to="extras.Tag"
|
|
49
|
+
),
|
|
50
|
+
),
|
|
51
|
+
(
|
|
52
|
+
"tenant",
|
|
53
|
+
models.ForeignKey(
|
|
54
|
+
blank=True,
|
|
55
|
+
null=True,
|
|
56
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
57
|
+
related_name="+",
|
|
58
|
+
to="tenancy.tenant",
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
],
|
|
62
|
+
options={
|
|
63
|
+
"ordering": ["name"],
|
|
64
|
+
},
|
|
65
|
+
),
|
|
66
|
+
migrations.CreateModel(
|
|
67
|
+
name="ZoneTemplate",
|
|
68
|
+
fields=[
|
|
69
|
+
(
|
|
70
|
+
"id",
|
|
71
|
+
models.BigAutoField(
|
|
72
|
+
auto_created=True, primary_key=True, serialize=False
|
|
73
|
+
),
|
|
74
|
+
),
|
|
75
|
+
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
|
76
|
+
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
|
77
|
+
(
|
|
78
|
+
"custom_field_data",
|
|
79
|
+
models.JSONField(
|
|
80
|
+
blank=True,
|
|
81
|
+
default=dict,
|
|
82
|
+
encoder=utilities.json.CustomFieldJSONEncoder,
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
("name", models.CharField(max_length=200, unique=True)),
|
|
86
|
+
("description", models.CharField(blank=True, max_length=200)),
|
|
87
|
+
(
|
|
88
|
+
"admin_c",
|
|
89
|
+
models.ForeignKey(
|
|
90
|
+
blank=True,
|
|
91
|
+
null=True,
|
|
92
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
93
|
+
related_name="+",
|
|
94
|
+
to="netbox_dns.contact",
|
|
95
|
+
),
|
|
96
|
+
),
|
|
97
|
+
(
|
|
98
|
+
"billing_c",
|
|
99
|
+
models.ForeignKey(
|
|
100
|
+
blank=True,
|
|
101
|
+
null=True,
|
|
102
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
103
|
+
related_name="+",
|
|
104
|
+
to="netbox_dns.contact",
|
|
105
|
+
),
|
|
106
|
+
),
|
|
107
|
+
(
|
|
108
|
+
"nameservers",
|
|
109
|
+
models.ManyToManyField(
|
|
110
|
+
blank=True, related_name="+", to="netbox_dns.nameserver"
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
(
|
|
114
|
+
"record_templates",
|
|
115
|
+
models.ManyToManyField(
|
|
116
|
+
blank=True,
|
|
117
|
+
related_name="zone_templates",
|
|
118
|
+
to="netbox_dns.recordtemplate",
|
|
119
|
+
),
|
|
120
|
+
),
|
|
121
|
+
(
|
|
122
|
+
"registrant",
|
|
123
|
+
models.ForeignKey(
|
|
124
|
+
blank=True,
|
|
125
|
+
null=True,
|
|
126
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
127
|
+
related_name="+",
|
|
128
|
+
to="netbox_dns.contact",
|
|
129
|
+
),
|
|
130
|
+
),
|
|
131
|
+
(
|
|
132
|
+
"registrar",
|
|
133
|
+
models.ForeignKey(
|
|
134
|
+
blank=True,
|
|
135
|
+
null=True,
|
|
136
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
137
|
+
related_name="+",
|
|
138
|
+
to="netbox_dns.registrar",
|
|
139
|
+
),
|
|
140
|
+
),
|
|
141
|
+
(
|
|
142
|
+
"tags",
|
|
143
|
+
taggit.managers.TaggableManager(
|
|
144
|
+
through="extras.TaggedItem", to="extras.Tag"
|
|
145
|
+
),
|
|
146
|
+
),
|
|
147
|
+
(
|
|
148
|
+
"tech_c",
|
|
149
|
+
models.ForeignKey(
|
|
150
|
+
blank=True,
|
|
151
|
+
null=True,
|
|
152
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
153
|
+
related_name="+",
|
|
154
|
+
to="netbox_dns.contact",
|
|
155
|
+
),
|
|
156
|
+
),
|
|
157
|
+
(
|
|
158
|
+
"tenant",
|
|
159
|
+
models.ForeignKey(
|
|
160
|
+
blank=True,
|
|
161
|
+
null=True,
|
|
162
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
163
|
+
related_name="+",
|
|
164
|
+
to="tenancy.tenant",
|
|
165
|
+
),
|
|
166
|
+
),
|
|
167
|
+
],
|
|
168
|
+
options={
|
|
169
|
+
"ordering": ["name"],
|
|
170
|
+
},
|
|
171
|
+
),
|
|
172
|
+
]
|
|
@@ -5,7 +5,7 @@ import django.db.models.deletion
|
|
|
5
5
|
from django.db import migrations, models
|
|
6
6
|
|
|
7
7
|
import netbox_dns.fields.address
|
|
8
|
-
from netbox_dns.
|
|
8
|
+
from netbox_dns.choices import RecordTypeChoices
|
|
9
9
|
from netbox_dns.utilities import arpa_to_prefix
|
|
10
10
|
|
|
11
11
|
|
netbox_dns/models/__init__.py
CHANGED
|
@@ -4,5 +4,12 @@ from .record import *
|
|
|
4
4
|
from .view import *
|
|
5
5
|
from .contact import *
|
|
6
6
|
from .registrar import *
|
|
7
|
+
from .zone_template import *
|
|
8
|
+
from .record_template import *
|
|
9
|
+
|
|
10
|
+
# +
|
|
11
|
+
# Backwards compatibility fix, will be removed in version 1.1
|
|
12
|
+
# -
|
|
13
|
+
from netbox_dns.choices import *
|
|
7
14
|
|
|
8
15
|
from netbox_dns.signals import ipam_coupling
|
netbox_dns/models/contact.py
CHANGED
|
@@ -7,6 +7,12 @@ from netbox.search import SearchIndex, register_search
|
|
|
7
7
|
from taggit.managers import TaggableManager
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
__ALL__ = (
|
|
11
|
+
"Contact",
|
|
12
|
+
"ContactIndex",
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
10
16
|
class Contact(NetBoxModel):
|
|
11
17
|
# +
|
|
12
18
|
# Data fields according to https://www.icann.org/resources/pages/rdds-labeling-policy-2017-02-01-en
|
netbox_dns/models/nameserver.py
CHANGED
|
@@ -13,10 +13,17 @@ from netbox_dns.utilities import (
|
|
|
13
13
|
normalize_name,
|
|
14
14
|
NameFormatError,
|
|
15
15
|
)
|
|
16
|
+
from netbox_dns.choices import RecordTypeChoices
|
|
16
17
|
from netbox_dns.validators import validate_fqdn
|
|
17
18
|
from netbox_dns.mixins import ObjectModificationMixin
|
|
18
19
|
|
|
19
|
-
from .record import Record
|
|
20
|
+
from .record import Record
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__ALL__ = (
|
|
24
|
+
"NameServer",
|
|
25
|
+
"NameServerIndex",
|
|
26
|
+
)
|
|
20
27
|
|
|
21
28
|
|
|
22
29
|
class NameServer(ObjectModificationMixin, NetBoxModel):
|
netbox_dns/models/record.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import ipaddress
|
|
2
2
|
|
|
3
3
|
import dns
|
|
4
|
-
from dns import rdata, rdatatype, rdataclass
|
|
5
4
|
from dns import name as dns_name
|
|
6
5
|
|
|
7
6
|
from django.core.exceptions import ValidationError
|
|
@@ -13,24 +12,22 @@ from netbox.models import NetBoxModel
|
|
|
13
12
|
from netbox.search import SearchIndex, register_search
|
|
14
13
|
from netbox.plugins.utils import get_plugin_config
|
|
15
14
|
from utilities.querysets import RestrictedQuerySet
|
|
16
|
-
from utilities.choices import ChoiceSet
|
|
17
15
|
|
|
18
16
|
from netbox_dns.fields import AddressField
|
|
19
|
-
from netbox_dns.utilities import
|
|
20
|
-
|
|
21
|
-
name_to_unicode,
|
|
22
|
-
)
|
|
23
|
-
from netbox_dns.validators import (
|
|
24
|
-
validate_fqdn,
|
|
25
|
-
validate_generic_name,
|
|
26
|
-
validate_domain_name,
|
|
27
|
-
)
|
|
17
|
+
from netbox_dns.utilities import arpa_to_prefix, name_to_unicode
|
|
18
|
+
from netbox_dns.validators import validate_generic_name, validate_record_value
|
|
28
19
|
from netbox_dns.mixins import ObjectModificationMixin
|
|
20
|
+
from netbox_dns.choices import RecordTypeChoices, RecordStatusChoices
|
|
29
21
|
|
|
30
22
|
# +
|
|
31
23
|
# This is a hack designed to break cyclic imports between Record and Zone
|
|
32
24
|
# -
|
|
33
|
-
|
|
25
|
+
from netbox_dns.models import zone
|
|
26
|
+
|
|
27
|
+
__ALL__ = (
|
|
28
|
+
"Record",
|
|
29
|
+
"RecordIndex",
|
|
30
|
+
)
|
|
34
31
|
|
|
35
32
|
|
|
36
33
|
def min_ttl(*ttl_list):
|
|
@@ -64,45 +61,6 @@ class RecordManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
|
64
61
|
)
|
|
65
62
|
|
|
66
63
|
|
|
67
|
-
def initialize_choice_names(cls):
|
|
68
|
-
for choice in cls.CHOICES:
|
|
69
|
-
setattr(cls, choice[0], choice[0])
|
|
70
|
-
return cls
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
@initialize_choice_names
|
|
74
|
-
class RecordTypeChoices(ChoiceSet):
|
|
75
|
-
CHOICES = [
|
|
76
|
-
(rdtype.name, rdtype.name)
|
|
77
|
-
for rdtype in sorted(rdatatype.RdataType, key=lambda a: a.name)
|
|
78
|
-
if not rdatatype.is_metatype(rdtype)
|
|
79
|
-
]
|
|
80
|
-
SINGLETONS = [
|
|
81
|
-
rdtype.name for rdtype in rdatatype.RdataType if rdatatype.is_singleton(rdtype)
|
|
82
|
-
]
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
@initialize_choice_names
|
|
86
|
-
class RecordClassChoices(ChoiceSet):
|
|
87
|
-
CHOICES = [
|
|
88
|
-
(rdclass.name, rdclass.name)
|
|
89
|
-
for rdclass in sorted(rdataclass.RdataClass)
|
|
90
|
-
if not rdataclass.is_metaclass(rdclass)
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class RecordStatusChoices(ChoiceSet):
|
|
95
|
-
key = "Record.status"
|
|
96
|
-
|
|
97
|
-
STATUS_ACTIVE = "active"
|
|
98
|
-
STATUS_INACTIVE = "inactive"
|
|
99
|
-
|
|
100
|
-
CHOICES = [
|
|
101
|
-
(STATUS_ACTIVE, "Active", "blue"),
|
|
102
|
-
(STATUS_INACTIVE, "Inactive", "red"),
|
|
103
|
-
]
|
|
104
|
-
|
|
105
|
-
|
|
106
64
|
class Record(ObjectModificationMixin, NetBoxModel):
|
|
107
65
|
ACTIVE_STATUS_LIST = (RecordStatusChoices.STATUS_ACTIVE,)
|
|
108
66
|
|
|
@@ -513,78 +471,8 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
513
471
|
) from None
|
|
514
472
|
|
|
515
473
|
def validate_value(self):
|
|
516
|
-
def _validate_idn(name):
|
|
517
|
-
try:
|
|
518
|
-
name.to_unicode()
|
|
519
|
-
except dns_name.IDNAException as exc:
|
|
520
|
-
raise ValidationError(
|
|
521
|
-
f"{name.to_text()} is not a valid IDN: {exc}."
|
|
522
|
-
) from None
|
|
523
|
-
|
|
524
|
-
try:
|
|
525
|
-
rr = rdata.from_text(RecordClassChoices.IN, self.type, self.value)
|
|
526
|
-
except dns.exception.SyntaxError as exc:
|
|
527
|
-
raise ValidationError(
|
|
528
|
-
{
|
|
529
|
-
"value": f"Record value {self.value} is not a valid value for a {self.type} record: {exc}."
|
|
530
|
-
}
|
|
531
|
-
) from None
|
|
532
|
-
|
|
533
474
|
try:
|
|
534
|
-
|
|
535
|
-
case RecordTypeChoices.CNAME:
|
|
536
|
-
_validate_idn(rr.target)
|
|
537
|
-
validate_domain_name(
|
|
538
|
-
rr.target.to_text(),
|
|
539
|
-
always_tolerant=True,
|
|
540
|
-
allow_empty_label=True,
|
|
541
|
-
)
|
|
542
|
-
|
|
543
|
-
case (
|
|
544
|
-
RecordTypeChoices.NS
|
|
545
|
-
| RecordTypeChoices.HTTPS
|
|
546
|
-
| RecordTypeChoices.SRV
|
|
547
|
-
| RecordTypeChoices.SVCB
|
|
548
|
-
):
|
|
549
|
-
_validate_idn(rr.target)
|
|
550
|
-
validate_domain_name(rr.target.to_text(), always_tolerant=True)
|
|
551
|
-
|
|
552
|
-
case RecordTypeChoices.DNAME:
|
|
553
|
-
_validate_idn(rr.target)
|
|
554
|
-
validate_domain_name(
|
|
555
|
-
rr.target.to_text(), always_tolerant=True, zone_name=True
|
|
556
|
-
)
|
|
557
|
-
|
|
558
|
-
case RecordTypeChoices.PTR | RecordTypeChoices.NSAP_PTR:
|
|
559
|
-
_validate_idn(rr.target)
|
|
560
|
-
validate_fqdn(rr.target.to_text(), always_tolerant=True)
|
|
561
|
-
|
|
562
|
-
case RecordTypeChoices.MX | RecordTypeChoices.RT | RecordTypeChoices.KX:
|
|
563
|
-
_validate_idn(rr.exchange)
|
|
564
|
-
validate_domain_name(rr.exchange.to_text(), always_tolerant=True)
|
|
565
|
-
|
|
566
|
-
case RecordTypeChoices.NSEC:
|
|
567
|
-
_validate_idn(rr.next)
|
|
568
|
-
validate_domain_name(rr.next.to_text(), always_tolerant=True)
|
|
569
|
-
|
|
570
|
-
case RecordTypeChoices.RP:
|
|
571
|
-
_validate_idn(rr.mbox)
|
|
572
|
-
validate_domain_name(rr.mbox.to_text(), always_tolerant=True)
|
|
573
|
-
_validate_idn(rr.txt)
|
|
574
|
-
validate_domain_name(rr.txt.to_text(), always_tolerant=True)
|
|
575
|
-
|
|
576
|
-
case RecordTypeChoices.NAPTR:
|
|
577
|
-
_validate_idn(rr.replacement)
|
|
578
|
-
validate_generic_name(
|
|
579
|
-
rr.replacement.to_text(), always_tolerant=True
|
|
580
|
-
)
|
|
581
|
-
|
|
582
|
-
case RecordTypeChoices.PX:
|
|
583
|
-
_validate_idn(rr.map822)
|
|
584
|
-
validate_domain_name(rr.map822.to_text(), always_tolerant=True)
|
|
585
|
-
_validate_idn(rr.mapx400)
|
|
586
|
-
validate_domain_name(rr.mapx400.to_text(), always_tolerant=True)
|
|
587
|
-
|
|
475
|
+
validate_record_value(self.type, self.value)
|
|
588
476
|
except ValidationError as exc:
|
|
589
477
|
raise ValidationError({"value": exc}) from None
|
|
590
478
|
|