netbox-plugin-dns 0.18.10__py3-none-any.whl → 0.19.0__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 CHANGED
@@ -1,6 +1,6 @@
1
1
  from extras.plugins import PluginConfig
2
2
 
3
- __version__ = "0.18.10"
3
+ __version__ = "0.19.0"
4
4
 
5
5
 
6
6
  class DNSConfig(PluginConfig):
@@ -1,6 +1,7 @@
1
1
  from rest_framework import serializers
2
2
 
3
3
  from netbox.api.serializers import NetBoxModelSerializer
4
+ from tenancy.api.nested_serializers import NestedTenantSerializer
4
5
 
5
6
  from netbox_dns.api.nested_serializers import (
6
7
  NestedViewSerializer,
@@ -15,6 +16,7 @@ class ViewSerializer(NetBoxModelSerializer):
15
16
  url = serializers.HyperlinkedIdentityField(
16
17
  view_name="plugins-api:netbox_dns-api:view-detail"
17
18
  )
19
+ tenant = NestedTenantSerializer(required=False, allow_null=True)
18
20
 
19
21
  class Meta:
20
22
  model = View
@@ -28,6 +30,7 @@ class ViewSerializer(NetBoxModelSerializer):
28
30
  "created",
29
31
  "last_updated",
30
32
  "custom_fields",
33
+ "tenant",
31
34
  )
32
35
 
33
36
 
@@ -56,6 +59,7 @@ class ZoneSerializer(NetBoxModelSerializer):
56
59
  read_only=True,
57
60
  allow_null=True,
58
61
  )
62
+ tenant = NestedTenantSerializer(required=False, allow_null=True)
59
63
 
60
64
  def create(self, validated_data):
61
65
  nameservers = validated_data.pop("nameservers", None)
@@ -103,6 +107,7 @@ class ZoneSerializer(NetBoxModelSerializer):
103
107
  "soa_minimum",
104
108
  "active",
105
109
  "custom_fields",
110
+ "tenant",
106
111
  )
107
112
 
108
113
 
@@ -117,6 +122,7 @@ class NameServerSerializer(NetBoxModelSerializer):
117
122
  default=None,
118
123
  help_text="Zones served by the authoritative nameserver",
119
124
  )
125
+ tenant = NestedTenantSerializer(required=False, allow_null=True)
120
126
 
121
127
  class Meta:
122
128
  model = NameServer
@@ -131,6 +137,7 @@ class NameServerSerializer(NetBoxModelSerializer):
131
137
  "created",
132
138
  "last_updated",
133
139
  "custom_fields",
140
+ "tenant",
134
141
  )
135
142
 
136
143
 
@@ -161,6 +168,7 @@ class RecordSerializer(NetBoxModelSerializer):
161
168
  required=False,
162
169
  read_only=True,
163
170
  )
171
+ tenant = NestedTenantSerializer(required=False, allow_null=True)
164
172
 
165
173
  class Meta:
166
174
  model = Record
@@ -184,4 +192,5 @@ class RecordSerializer(NetBoxModelSerializer):
184
192
  "address_record",
185
193
  "active",
186
194
  "custom_fields",
195
+ "tenant",
187
196
  )
netbox_dns/api/views.py CHANGED
@@ -33,8 +33,13 @@ class ViewViewSet(NetBoxModelViewSet):
33
33
 
34
34
 
35
35
  class ZoneViewSet(NetBoxModelViewSet):
36
- queryset = Zone.objects.all().prefetch_related(
37
- "view", "nameservers", "tags", "soa_mname", "record_set"
36
+ queryset = Zone.objects.prefetch_related(
37
+ "view",
38
+ "nameservers",
39
+ "tags",
40
+ "soa_mname",
41
+ "record_set",
42
+ "tenant",
38
43
  )
39
44
  serializer_class = ZoneSerializer
40
45
  filterset_class = ZoneFilter
@@ -55,7 +60,7 @@ class ZoneViewSet(NetBoxModelViewSet):
55
60
 
56
61
 
57
62
  class NameServerViewSet(NetBoxModelViewSet):
58
- queryset = NameServer.objects.all().prefetch_related("zones")
63
+ queryset = NameServer.objects.prefetch_related("zones", "tenant")
59
64
  serializer_class = NameServerSerializer
60
65
  filterset_class = NameServerFilter
61
66
 
@@ -67,7 +72,7 @@ class NameServerViewSet(NetBoxModelViewSet):
67
72
 
68
73
 
69
74
  class RecordViewSet(NetBoxModelViewSet):
70
- queryset = Record.objects.all().prefetch_related("zone", "zone__view")
75
+ queryset = Record.objects.all().prefetch_related("zone", "zone__view", "tenant")
71
76
  serializer_class = RecordSerializer
72
77
  filterset_class = RecordFilter
73
78
 
@@ -2,21 +2,17 @@ import django_filters
2
2
  from django.db.models import Q
3
3
 
4
4
  from netbox.filtersets import NetBoxModelFilterSet
5
+ from tenancy.filtersets import TenancyFilterSet
5
6
 
6
7
  from netbox_dns.models import NameServer
7
8
 
8
9
 
9
- class NameServerFilter(NetBoxModelFilterSet):
10
- """Filter capabilities for NameServer instances."""
11
-
12
- name = django_filters.CharFilter()
13
-
10
+ class NameServerFilter(TenancyFilterSet, NetBoxModelFilterSet):
14
11
  class Meta:
15
12
  model = NameServer
16
- fields = ("id", "name")
13
+ fields = ("id", "name", "tenant")
17
14
 
18
15
  def search(self, queryset, name, value):
19
- """Perform the filtered search."""
20
16
  if not value.strip():
21
17
  return queryset
22
18
  qs_filter = Q(name__icontains=value)
@@ -2,11 +2,12 @@ import django_filters
2
2
  from django.db.models import Q
3
3
 
4
4
  from netbox.filtersets import NetBoxModelFilterSet
5
+ from tenancy.filtersets import TenancyFilterSet
5
6
 
6
7
  from netbox_dns.models import View, Zone, Record, RecordTypeChoices
7
8
 
8
9
 
9
- class RecordFilter(NetBoxModelFilterSet):
10
+ class RecordFilter(TenancyFilterSet, NetBoxModelFilterSet):
10
11
  """Filter capabilities for Record instances."""
11
12
 
12
13
  type = django_filters.MultipleChoiceFilter(
@@ -38,7 +39,7 @@ class RecordFilter(NetBoxModelFilterSet):
38
39
 
39
40
  class Meta:
40
41
  model = Record
41
- fields = ("id", "type", "name", "value", "status", "zone", "managed")
42
+ fields = ("id", "type", "name", "value", "status", "zone", "managed", "tenant")
42
43
 
43
44
  def search(self, queryset, name, value):
44
45
  """Perform the filtered search."""
@@ -2,21 +2,17 @@ import django_filters
2
2
  from django.db.models import Q
3
3
 
4
4
  from netbox.filtersets import NetBoxModelFilterSet
5
+ from tenancy.filtersets import TenancyFilterSet
5
6
 
6
7
  from netbox_dns.models import View
7
8
 
8
9
 
9
- class ViewFilter(NetBoxModelFilterSet):
10
- """Filter capabilities for View instances."""
11
-
12
- name = django_filters.CharFilter()
13
-
10
+ class ViewFilter(NetBoxModelFilterSet, TenancyFilterSet):
14
11
  class Meta:
15
12
  model = View
16
- fields = ("id", "name")
13
+ fields = ("id", "name", "tenant")
17
14
 
18
15
  def search(self, queryset, name, value):
19
- """Perform the filtered search."""
20
16
  if not value.strip():
21
17
  return queryset
22
18
  qs_filter = Q(name__icontains=value)
@@ -2,13 +2,12 @@ import django_filters
2
2
  from django.db.models import Q
3
3
 
4
4
  from netbox.filtersets import NetBoxModelFilterSet
5
+ from tenancy.filtersets import TenancyFilterSet
5
6
 
6
7
  from netbox_dns.models import View, Zone, ZoneStatusChoices
7
8
 
8
9
 
9
- class ZoneFilter(NetBoxModelFilterSet):
10
- """Filter capabilities for Zone instances."""
11
-
10
+ class ZoneFilter(TenancyFilterSet, NetBoxModelFilterSet):
12
11
  status = django_filters.ChoiceFilter(
13
12
  choices=ZoneStatusChoices,
14
13
  )
@@ -28,7 +27,7 @@ class ZoneFilter(NetBoxModelFilterSet):
28
27
 
29
28
  class Meta:
30
29
  model = Zone
31
- fields = ("id", "name", "view", "status", "nameservers", "active")
30
+ fields = ("id", "name", "view", "status", "nameservers", "active", "tenant")
32
31
 
33
32
  def search(self, queryset, name, value):
34
33
  """Perform the filtered search."""
@@ -7,15 +7,19 @@ from netbox.forms import (
7
7
  NetBoxModelForm,
8
8
  )
9
9
 
10
- from utilities.forms.fields import TagFilterField
10
+ from utilities.forms.fields import (
11
+ TagFilterField,
12
+ CSVModelChoiceField,
13
+ DynamicModelChoiceField,
14
+ )
15
+ from tenancy.models import Tenant
16
+ from tenancy.forms import TenancyForm, TenancyFilterForm
11
17
 
12
18
  from netbox_dns.models import NameServer
13
19
  from netbox_dns.utilities import name_to_unicode
14
20
 
15
21
 
16
- class NameServerForm(NetBoxModelForm):
17
- """Form for creating a new NameServer object."""
18
-
22
+ class NameServerForm(TenancyForm, NetBoxModelForm):
19
23
  def __init__(self, *args, **kwargs):
20
24
  super().__init__(*args, **kwargs)
21
25
 
@@ -23,14 +27,17 @@ class NameServerForm(NetBoxModelForm):
23
27
  if initial_name:
24
28
  self.initial["name"] = name_to_unicode(initial_name)
25
29
 
30
+ fieldsets = (
31
+ ("Nameserver", ("name", "description", "tags")),
32
+ ("Tenancy", ("tenant_group", "tenant")),
33
+ )
34
+
26
35
  class Meta:
27
36
  model = NameServer
28
- fields = ("name", "description", "tags")
29
-
37
+ fields = ("name", "description", "tags", "tenant")
30
38
 
31
- class NameServerFilterForm(NetBoxModelFilterSetForm):
32
- """Form for filtering NameServer instances."""
33
39
 
40
+ class NameServerFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
34
41
  model = NameServer
35
42
 
36
43
  name = forms.CharField(
@@ -39,18 +46,36 @@ class NameServerFilterForm(NetBoxModelFilterSetForm):
39
46
  )
40
47
  tag = TagFilterField(NameServer)
41
48
 
49
+ fieldsets = (
50
+ (None, ("q", "filter_id", "tag")),
51
+ ("Attributes", ("name",)),
52
+ ("Tenant", ("tenant_group_id", "tenant_id")),
53
+ )
54
+
42
55
 
43
56
  class NameServerImportForm(NetBoxModelImportForm):
57
+ tenant = CSVModelChoiceField(
58
+ queryset=Tenant.objects.all(),
59
+ to_field_name="name",
60
+ required=False,
61
+ help_text="Assigned tenant",
62
+ )
63
+
44
64
  class Meta:
45
65
  model = NameServer
46
66
 
47
- fields = ("name", "description")
67
+ fields = (
68
+ "name",
69
+ "description",
70
+ "tenant",
71
+ )
48
72
 
49
73
 
50
74
  class NameServerBulkEditForm(NetBoxModelBulkEditForm):
51
75
  model = NameServer
52
76
 
53
77
  description = forms.CharField(max_length=200, required=False)
78
+ tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
54
79
 
55
80
  class Meta:
56
- nullable_fields = ("description",)
81
+ nullable_fields = ("description", "tenant")
@@ -16,14 +16,14 @@ from utilities.forms.fields import (
16
16
  )
17
17
  from utilities.forms.widgets import BulkEditNullBooleanSelect, APISelect
18
18
  from utilities.forms import add_blank_choice
19
+ from tenancy.models import Tenant
20
+ from tenancy.forms import TenancyForm, TenancyFilterForm
19
21
 
20
22
  from netbox_dns.models import View, Zone, Record, RecordTypeChoices, RecordStatusChoices
21
23
  from netbox_dns.utilities import name_to_unicode
22
24
 
23
25
 
24
- class RecordForm(NetBoxModelForm):
25
- """Form for creating a new Record object."""
26
-
26
+ class RecordForm(TenancyForm, NetBoxModelForm):
27
27
  def __init__(self, *args, **kwargs):
28
28
  super().__init__(*args, **kwargs)
29
29
 
@@ -40,6 +40,24 @@ class RecordForm(NetBoxModelForm):
40
40
  label="TTL",
41
41
  )
42
42
 
43
+ fieldsets = (
44
+ (
45
+ "Record",
46
+ (
47
+ "name",
48
+ "zone",
49
+ "type",
50
+ "value",
51
+ "status",
52
+ "ttl",
53
+ "disable_ptr",
54
+ "description",
55
+ "tags",
56
+ ),
57
+ ),
58
+ ("Tenancy", ("tenant_group", "tenant")),
59
+ )
60
+
43
61
  class Meta:
44
62
  model = Record
45
63
 
@@ -53,13 +71,17 @@ class RecordForm(NetBoxModelForm):
53
71
  "disable_ptr",
54
72
  "description",
55
73
  "tags",
74
+ "tenant",
56
75
  )
57
76
 
58
77
 
59
- class RecordFilterForm(NetBoxModelFilterSetForm):
60
- """Form for filtering Record instances."""
61
-
78
+ class RecordFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
62
79
  model = Record
80
+ fieldsets = (
81
+ (None, ("q", "filter_id", "tag")),
82
+ ("Attributes", ("view_id", "zone_id", "name", "value", "status")),
83
+ ("Tenant", ("tenant_group_id", "tenant_id")),
84
+ )
63
85
 
64
86
  type = forms.MultipleChoiceField(
65
87
  choices=add_blank_choice(RecordTypeChoices),
@@ -137,6 +159,12 @@ class RecordImportForm(NetBoxModelImportForm):
137
159
  label="Disable PTR",
138
160
  help_text="Disable generation of a PTR record",
139
161
  )
162
+ tenant = CSVModelChoiceField(
163
+ queryset=Tenant.objects.all(),
164
+ to_field_name="name",
165
+ required=False,
166
+ help_text="Assigned tenant",
167
+ )
140
168
 
141
169
  def is_valid(self):
142
170
  try:
@@ -158,6 +186,7 @@ class RecordImportForm(NetBoxModelImportForm):
158
186
  "ttl",
159
187
  "disable_ptr",
160
188
  "description",
189
+ "tenant",
161
190
  )
162
191
 
163
192
 
@@ -191,11 +220,21 @@ class RecordBulkEditForm(NetBoxModelBulkEditForm):
191
220
  required=False, widget=BulkEditNullBooleanSelect(), label="Disable PTR"
192
221
  )
193
222
  description = forms.CharField(max_length=200, required=False)
223
+ tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
194
224
 
195
225
  fieldsets = (
196
226
  (
197
227
  None,
198
- ("zone", "type", "value", "status", "ttl", "disable_ptr", "description"),
228
+ (
229
+ "zone",
230
+ "type",
231
+ "value",
232
+ "status",
233
+ "ttl",
234
+ "disable_ptr",
235
+ "description",
236
+ "tenant",
237
+ ),
199
238
  ),
200
239
  )
201
- nullable_fields = ("description", "ttl")
240
+ nullable_fields = ("description", "ttl", "tenant")
netbox_dns/forms/view.py CHANGED
@@ -6,21 +6,35 @@ from netbox.forms import (
6
6
  NetBoxModelImportForm,
7
7
  NetBoxModelForm,
8
8
  )
9
- from utilities.forms.fields import TagFilterField
9
+ from utilities.forms.fields import (
10
+ TagFilterField,
11
+ CSVModelChoiceField,
12
+ DynamicModelChoiceField,
13
+ )
14
+ from tenancy.models import Tenant
15
+ from tenancy.forms import TenancyForm, TenancyFilterForm
10
16
 
11
17
  from netbox_dns.models import View
12
18
 
13
19
 
14
- class ViewForm(NetBoxModelForm):
15
- """Form for creating a new View object."""
20
+ class ViewForm(TenancyForm, NetBoxModelForm):
21
+ fieldsets = (
22
+ ("View", ("name", "description", "tags")),
23
+ ("Tenancy", ("tenant_group", "tenant")),
24
+ )
16
25
 
17
26
  class Meta:
18
27
  model = View
19
- fields = ("name", "description", "tags")
28
+ fields = ("name", "description", "tags", "tenant")
20
29
 
21
30
 
22
- class ViewFilterForm(NetBoxModelFilterSetForm):
23
- """Form for filtering View instances."""
31
+ class ViewFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
32
+ model = View
33
+ fieldsets = (
34
+ (None, ("q", "filter_id", "tag")),
35
+ ("Attributes", ("name",)),
36
+ ("Tenant", ("tenant_group_id", "tenant_id")),
37
+ )
24
38
 
25
39
  name = forms.CharField(
26
40
  required=False,
@@ -28,19 +42,25 @@ class ViewFilterForm(NetBoxModelFilterSetForm):
28
42
  )
29
43
  tag = TagFilterField(View)
30
44
 
31
- model = View
32
-
33
45
 
34
46
  class ViewImportForm(NetBoxModelImportForm):
47
+ tenant = CSVModelChoiceField(
48
+ queryset=Tenant.objects.all(),
49
+ to_field_name="name",
50
+ required=False,
51
+ help_text="Assigned tenant",
52
+ )
53
+
35
54
  class Meta:
36
55
  model = View
37
- fields = ("name", "description")
56
+ fields = ("name", "description", "tenant")
38
57
 
39
58
 
40
59
  class ViewBulkEditForm(NetBoxModelBulkEditForm):
41
60
  model = View
42
61
 
43
62
  description = forms.CharField(max_length=200, required=False)
63
+ tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
44
64
 
45
65
  class Meta:
46
- nullable_fields = ["description"]
66
+ nullable_fields = ("description", "tenant")
netbox_dns/forms/zone.py CHANGED
@@ -19,14 +19,14 @@ from utilities.forms.fields import (
19
19
  )
20
20
  from utilities.forms.widgets import BulkEditNullBooleanSelect, APISelect
21
21
  from utilities.forms import add_blank_choice
22
+ from tenancy.models import Tenant
23
+ from tenancy.forms import TenancyForm, TenancyFilterForm
22
24
 
23
25
  from netbox_dns.models import View, Zone, ZoneStatusChoices, NameServer
24
26
  from netbox_dns.utilities import name_to_unicode
25
27
 
26
28
 
27
- class ZoneForm(NetBoxModelForm):
28
- """Form for creating a new Zone object."""
29
-
29
+ class ZoneForm(TenancyForm, NetBoxModelForm):
30
30
  nameservers = DynamicModelMultipleChoiceField(
31
31
  queryset=NameServer.objects.all(),
32
32
  required=False,
@@ -110,6 +110,7 @@ class ZoneForm(NetBoxModelForm):
110
110
  ),
111
111
  ),
112
112
  ("Tags", ("tags",)),
113
+ ("Tenancy", ("tenant_group", "tenant")),
113
114
  )
114
115
 
115
116
  def __init__(self, *args, **kwargs):
@@ -188,6 +189,7 @@ class ZoneForm(NetBoxModelForm):
188
189
  "soa_retry",
189
190
  "soa_expire",
190
191
  "soa_minimum",
192
+ "tenant",
191
193
  )
192
194
  help_texts = {
193
195
  "view": "View the zone belongs to",
@@ -195,10 +197,13 @@ class ZoneForm(NetBoxModelForm):
195
197
  }
196
198
 
197
199
 
198
- class ZoneFilterForm(NetBoxModelFilterSetForm):
199
- """Form for filtering Zone instances."""
200
-
200
+ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
201
201
  model = Zone
202
+ fieldsets = (
203
+ (None, ("q", "filter_id", "tag")),
204
+ ("Attributes", ("view_id", "status", "name", "nameservers")),
205
+ ("Tenant", ("tenant_group_id", "tenant_id")),
206
+ )
202
207
 
203
208
  view_id = DynamicModelMultipleChoiceField(
204
209
  queryset=View.objects.all(),
@@ -280,6 +285,12 @@ class ZoneImportForm(NetBoxModelImportForm):
280
285
  required=False,
281
286
  help_text="Minimum TTL for negative results, e.g. NXRRSET",
282
287
  )
288
+ tenant = CSVModelChoiceField(
289
+ queryset=Tenant.objects.all(),
290
+ required=False,
291
+ to_field_name="name",
292
+ help_text="Assigned tenant",
293
+ )
283
294
 
284
295
  def _get_default_value(self, field):
285
296
  _default_values = settings.PLUGINS_CONFIG.get("netbox_dns", {})
@@ -370,6 +381,7 @@ class ZoneImportForm(NetBoxModelImportForm):
370
381
  "soa_retry",
371
382
  "soa_expire",
372
383
  "soa_minimum",
384
+ "tenant",
373
385
  )
374
386
 
375
387
 
@@ -445,6 +457,7 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
445
457
  label="SOA Minimum TTL",
446
458
  validators=[MinValueValidator(1)],
447
459
  )
460
+ tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
448
461
 
449
462
  model = Zone
450
463
 
@@ -457,6 +470,7 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
457
470
  "nameservers",
458
471
  "default_ttl",
459
472
  "description",
473
+ "tenant",
460
474
  ),
461
475
  ),
462
476
  (
@@ -0,0 +1,58 @@
1
+ # Generated by Django 4.2.4 on 2023-09-17 15:12
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("tenancy", "0011_contactassignment_tags"),
10
+ ("netbox_dns", "0023_alter_record_value"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name="nameserver",
16
+ name="tenant",
17
+ field=models.ForeignKey(
18
+ blank=True,
19
+ null=True,
20
+ on_delete=django.db.models.deletion.PROTECT,
21
+ related_name="netbox_dns_nameservers",
22
+ to="tenancy.tenant",
23
+ ),
24
+ ),
25
+ migrations.AddField(
26
+ model_name="record",
27
+ name="tenant",
28
+ field=models.ForeignKey(
29
+ blank=True,
30
+ null=True,
31
+ on_delete=django.db.models.deletion.PROTECT,
32
+ related_name="netbox_dns_records",
33
+ to="tenancy.tenant",
34
+ ),
35
+ ),
36
+ migrations.AddField(
37
+ model_name="view",
38
+ name="tenant",
39
+ field=models.ForeignKey(
40
+ blank=True,
41
+ null=True,
42
+ on_delete=django.db.models.deletion.PROTECT,
43
+ related_name="netbox_dns_views",
44
+ to="tenancy.tenant",
45
+ ),
46
+ ),
47
+ migrations.AddField(
48
+ model_name="zone",
49
+ name="tenant",
50
+ field=models.ForeignKey(
51
+ blank=True,
52
+ null=True,
53
+ on_delete=django.db.models.deletion.PROTECT,
54
+ related_name="netbox_dns_zones",
55
+ to="tenancy.tenant",
56
+ ),
57
+ ),
58
+ ]
netbox_dns/models.py CHANGED
@@ -7,6 +7,7 @@ import dns
7
7
  from dns import rdata, rdatatype, rdataclass
8
8
  from dns import name as dns_name
9
9
  from dns.rdtypes.ANY import SOA
10
+ from dns.exception import DNSException
10
11
 
11
12
  from netaddr import IPNetwork, AddrFormatError, IPAddress
12
13
 
@@ -55,6 +56,13 @@ class NameServer(NetBoxModel):
55
56
  max_length=200,
56
57
  blank=True,
57
58
  )
59
+ tenant = models.ForeignKey(
60
+ to="tenancy.Tenant",
61
+ on_delete=models.PROTECT,
62
+ related_name="netbox_dns_nameservers",
63
+ blank=True,
64
+ null=True,
65
+ )
58
66
 
59
67
  clone_fields = ["name", "description"]
60
68
 
@@ -259,6 +267,13 @@ class Zone(NetBoxModel):
259
267
  blank=True,
260
268
  null=True,
261
269
  )
270
+ tenant = models.ForeignKey(
271
+ to="tenancy.Tenant",
272
+ on_delete=models.PROTECT,
273
+ related_name="netbox_dns_zones",
274
+ blank=True,
275
+ null=True,
276
+ )
262
277
 
263
278
  objects = ZoneManager()
264
279
 
@@ -484,6 +499,16 @@ class Zone(NetBoxModel):
484
499
  }
485
500
  ) from None
486
501
 
502
+ try:
503
+ soa_rname = dns_name.from_text(self.soa_rname, origin=dns_name.root)
504
+ validate_fqdn(self.soa_rname)
505
+ except (DNSException, ValidationError) as exc:
506
+ raise ValidationError(
507
+ {
508
+ "soa_rname": exc,
509
+ }
510
+ ) from None
511
+
487
512
  if self.soa_serial is None and not self.soa_serial_auto:
488
513
  raise ValidationError(
489
514
  {
@@ -691,6 +716,13 @@ class Record(NetBoxModel):
691
716
  max_length=200,
692
717
  blank=True,
693
718
  )
719
+ tenant = models.ForeignKey(
720
+ to="tenancy.Tenant",
721
+ on_delete=models.PROTECT,
722
+ related_name="netbox_dns_records",
723
+ blank=True,
724
+ null=True,
725
+ )
694
726
  ip_address = AddressField(
695
727
  verbose_name="Related IP Address",
696
728
  help_text="IP address related to an address (A/AAAA) or PTR record",
@@ -1013,6 +1045,13 @@ class View(NetBoxModel):
1013
1045
  max_length=200,
1014
1046
  blank=True,
1015
1047
  )
1048
+ tenant = models.ForeignKey(
1049
+ to="tenancy.Tenant",
1050
+ on_delete=models.PROTECT,
1051
+ related_name="netbox_dns_views",
1052
+ blank=True,
1053
+ null=True,
1054
+ )
1016
1055
 
1017
1056
  clone_fields = ["name", "description"]
1018
1057
 
@@ -1,11 +1,12 @@
1
1
  import django_tables2 as tables
2
2
 
3
3
  from netbox.tables import NetBoxTable, TagColumn
4
+ from tenancy.tables import TenancyColumnsMixin
4
5
 
5
6
  from netbox_dns.models import NameServer
6
7
 
7
8
 
8
- class NameServerTable(NetBoxTable):
9
+ class NameServerTable(TenancyColumnsMixin, NetBoxTable):
9
10
  """Table for displaying NameServer objects."""
10
11
 
11
12
  name = tables.Column(
@@ -25,6 +26,8 @@ class NameServerTable(NetBoxTable):
25
26
  "name",
26
27
  "description",
27
28
  "tags",
29
+ "tenant",
30
+ "tenant_group",
28
31
  )
29
32
  default_columns = (
30
33
  "pk",
@@ -7,14 +7,13 @@ from netbox.tables import (
7
7
  TagColumn,
8
8
  ActionsColumn,
9
9
  )
10
+ from tenancy.tables import TenancyColumnsMixin
10
11
 
11
12
  from netbox_dns.models import Record
12
13
  from netbox_dns.utilities import value_to_unicode
13
14
 
14
15
 
15
- class RecordBaseTable(NetBoxTable):
16
- """Base class for tables displaying Records"""
17
-
16
+ class RecordBaseTable(TenancyColumnsMixin, NetBoxTable):
18
17
  zone = tables.Column(
19
18
  linkify=True,
20
19
  )
@@ -45,8 +44,6 @@ class RecordBaseTable(NetBoxTable):
45
44
 
46
45
 
47
46
  class RecordTable(RecordBaseTable):
48
- """Table for displaying Record objects."""
49
-
50
47
  pk = ToggleColumn()
51
48
  status = ChoiceFieldColumn()
52
49
  disable_ptr = tables.BooleanColumn(
@@ -76,6 +73,8 @@ class RecordTable(RecordBaseTable):
76
73
  "tags",
77
74
  "active",
78
75
  "description",
76
+ "tenant",
77
+ "tenant_group",
79
78
  )
80
79
  default_columns = (
81
80
  "zone",
@@ -89,8 +88,6 @@ class RecordTable(RecordBaseTable):
89
88
 
90
89
 
91
90
  class ManagedRecordTable(RecordBaseTable):
92
- """Table for displaying managed Record objects."""
93
-
94
91
  address_record = tables.Column(
95
92
  verbose_name="Address Record",
96
93
  linkify=True,
netbox_dns/tables/view.py CHANGED
@@ -1,15 +1,17 @@
1
1
  import django_tables2 as tables
2
2
 
3
3
  from netbox.tables import NetBoxTable
4
+ from tenancy.tables import TenancyColumnsMixin
5
+
4
6
  from netbox_dns.models import View
5
7
 
6
8
 
7
- class ViewTable(NetBoxTable):
9
+ class ViewTable(TenancyColumnsMixin, NetBoxTable):
8
10
  name = tables.Column(
9
11
  linkify=True,
10
12
  )
11
13
 
12
14
  class Meta(NetBoxTable.Meta):
13
15
  model = View
14
- fields = ("name", "description")
16
+ fields = ("name", "description", "tenant", "tenant_group")
15
17
  default_columns = ("name",)
netbox_dns/tables/zone.py CHANGED
@@ -6,13 +6,12 @@ from netbox.tables import (
6
6
  TagColumn,
7
7
  ActionsColumn,
8
8
  )
9
+ from tenancy.tables import TenancyColumnsMixin
9
10
 
10
11
  from netbox_dns.models import Zone
11
12
 
12
13
 
13
- class ZoneTable(NetBoxTable):
14
- """Table for displaying Zone objects."""
15
-
14
+ class ZoneTable(TenancyColumnsMixin, NetBoxTable):
16
15
  name = tables.Column(
17
16
  linkify=True,
18
17
  )
@@ -46,6 +45,8 @@ class ZoneTable(NetBoxTable):
46
45
  "soa_mname",
47
46
  "soa_rname",
48
47
  "soa_serial",
48
+ "tenant",
49
+ "tenant_group",
49
50
  )
50
51
  default_columns = (
51
52
  "pk",
@@ -17,6 +17,15 @@
17
17
  <td>{{ unicode_name }}</td>
18
18
  </tr>
19
19
  {% endif %}
20
+ <tr>
21
+ <th scope="row">Tenant</th>
22
+ <td>
23
+ {% if object.tenant.group %}
24
+ {{ object.tenant.group|linkify }} /
25
+ {% endif %}
26
+ {{ object.tenant|linkify|placeholder }}
27
+ </td>
28
+ </tr>
20
29
  <tr>
21
30
  <th scope="row">Description</th>
22
31
  <td>{{ object.description }}</td>
@@ -53,6 +53,17 @@
53
53
  <td><a href="{% url 'plugins:netbox_dns:zone_records' pk=object.zone.pk %}">{{ object.zone }}</a></td>
54
54
  {% endif %}
55
55
  </tr>
56
+ {% if not object.managed %}
57
+ <tr>
58
+ <th scope="row">Tenant</th>
59
+ <td>
60
+ {% if object.tenant.group %}
61
+ {{ object.tenant.group|linkify }} /
62
+ {% endif %}
63
+ {{ object.tenant|linkify|placeholder }}
64
+ </td>
65
+ </tr>
66
+ {% endif %}
56
67
  <tr>
57
68
  <th scope="row">Type</th>
58
69
  <td>{{ object.type }}</td>
@@ -11,6 +11,15 @@
11
11
  <th scope="row">Name</th>
12
12
  <td>{{ object.name }}</td>
13
13
  </tr>
14
+ <tr>
15
+ <th scope="row">Tenant</th>
16
+ <td>
17
+ {% if object.tenant.group %}
18
+ {{ object.tenant.group|linkify }} /
19
+ {% endif %}
20
+ {{ object.tenant|linkify|placeholder }}
21
+ </td>
22
+ </tr>
14
23
  <tr>
15
24
  <th scope="row">Description</th>
16
25
  <td>{{ object.description }}</td>
@@ -32,6 +32,15 @@
32
32
  </td>
33
33
  </tr>
34
34
  {% endif %}
35
+ <tr>
36
+ <th scope="row">Tenant</th>
37
+ <td>
38
+ {% if object.tenant.group %}
39
+ {{ object.tenant.group|linkify }} /
40
+ {% endif %}
41
+ {{ object.tenant|linkify|placeholder }}
42
+ </td>
43
+ </tr>
35
44
  <tr>
36
45
  <th scope="row">Status</th>
37
46
  <td>{{ object.status }}</td>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-plugin-dns
3
- Version: 0.18.10
3
+ Version: 0.19.0
4
4
  Summary: NetBox DNS is a NetBox plugin for managing DNS data.
5
5
  Home-page: https://github.com/peteeckel/netbox-plugin-dns
6
6
  License: MIT
@@ -44,7 +44,7 @@ NetBox DNS is using the standardized NetBox plugin interface, so it also takes a
44
44
 
45
45
  ## Requirements
46
46
 
47
- * NetBox 3.5 or higher
47
+ * NetBox 3.5.8 or higher
48
48
  * Python 3.8 or higher
49
49
 
50
50
  ## Installation & Configuration
@@ -1,22 +1,22 @@
1
- netbox_dns/__init__.py,sha256=MVfxylLb5iqpMmCI8_Q2mGUZHG3yQH29eU4lmsQ4AIM,999
1
+ netbox_dns/__init__.py,sha256=dhXfZywLmXW9vMvHwmYqZMX74hz6J_VC8PB8Aru9tV8,998
2
2
  netbox_dns/api/nested_serializers.py,sha256=L2LX0HuqKIjFxH7U7HD6ytg58LVat8ElRu7qTxgsKaE,2001
3
- netbox_dns/api/serializers.py,sha256=d6X5pbsbEHGuer2WLvXUR5LXxrqTQXAjJkON0JTFDRw,4630
3
+ netbox_dns/api/serializers.py,sha256=2zQyUtze2YMrkrSQQ7QbuWMJLzd1hevFxdKY9h7PVGY,5060
4
4
  netbox_dns/api/urls.py,sha256=ZeJtiqrxEbw5Efeb4HWpb3rp9TDTHK8hwKvquYQ7RzM,441
5
- netbox_dns/api/views.py,sha256=RNGEpW_WhXuX-xU5FWFi41dFn-kHJTu-tqLJ-VoJN_8,3015
5
+ netbox_dns/api/views.py,sha256=rF-9g3JbWRHCqcWlF1Oteqk7TNSDVf641TjAh8dsEtU,3074
6
6
  netbox_dns/apps.py,sha256=JCW5eS-AQBUubDJve1DjP-IRFKTFGQh1NLGWzJpC5MI,151
7
7
  netbox_dns/fields/__init__.py,sha256=KQxDL1BPIAUk5nBPtRyuZgRVHNDb8UrpG9KPIVq99VU,46
8
8
  netbox_dns/fields/address.py,sha256=hvZfYga6WrF-bi7rOl76aNAIVsdPAuIBf3b4d9-jejY,1530
9
9
  netbox_dns/fields/network.py,sha256=Pcd0kmtZI68-sVtMScpxtfUUbBuD2187JVHBQZV5TZE,3023
10
10
  netbox_dns/filters/__init__.py,sha256=deqMJWAXtLukzoBMpk6DCRUK8nTuYYlVvEDYVidOa54,88
11
- netbox_dns/filters/nameserver.py,sha256=XUcyv_iYJk50mJvazBXRiWf7t9N6ly37uAili1rTjcg,601
12
- netbox_dns/filters/record.py,sha256=EdIJ4eVYc0o_f2sl3ytmkrwFxupiE_UzXz916X0uXF0,1615
13
- netbox_dns/filters/view.py,sha256=327tKxOhUXvbRASFVJlaOiANwza4W_VsyL-JzMjMkHw,577
14
- netbox_dns/filters/zone.py,sha256=mRGF4xbAe9HBjWT8LrwRbBJu17QjYw7Nys9fdSgsy0Q,1185
11
+ netbox_dns/filters/nameserver.py,sha256=IdeECQ8r-wanEI1o3UYivti3fcsoLpkK6R2HWOWnOU8,537
12
+ netbox_dns/filters/record.py,sha256=DH1x4bNkBAN_gVNklAjorcgHoJmH_AXEf1sBNvJS6Kc,1691
13
+ netbox_dns/filters/view.py,sha256=QzCFZU0d2JoAIks7zh0Cs94n4oNHu2uVG3JQzKPcpFE,519
14
+ netbox_dns/filters/zone.py,sha256=1QOlnO-gy_7ofZ-Nyp896FvYxQN9TlnpMlNpYKx7RVY,1210
15
15
  netbox_dns/forms/__init__.py,sha256=deqMJWAXtLukzoBMpk6DCRUK8nTuYYlVvEDYVidOa54,88
16
- netbox_dns/forms/nameserver.py,sha256=E348ByczUWhvF_52Deov0wc0tNt5HuS5nDzadZkxYHI,1308
17
- netbox_dns/forms/record.py,sha256=hjlf0N3A-oPXFzK20rferVvhDIk-FOWeWjdlkYGA8v0,5083
18
- netbox_dns/forms/view.py,sha256=rqctM0fw_SFbJBmRmSj0qyMgk8uR4aRJEgSXztudP9U,961
19
- netbox_dns/forms/zone.py,sha256=d8evnvlnidQetFAvmX1GTvjwtGlegh9YbcQXwJVdxiI,14198
16
+ netbox_dns/forms/nameserver.py,sha256=fgvME0-pHWPlnqx2BMkPckNhT0RXR52YLMQPuArpiyE,2007
17
+ netbox_dns/forms/record.py,sha256=07Yrz-0JEbFistM0hcOVvK8TBM1EocdE7fCMmdRRJvk,6143
18
+ netbox_dns/forms/view.py,sha256=Hr5yRx2lJAVcCdw0miYYE2kVop5ldjpbmWB69FgHvpc,1619
19
+ netbox_dns/forms/zone.py,sha256=6GJ1ZMWaqttRQBmeSAfJq8nUpu5Ym2lD3gMPgJRxQao,14791
20
20
  netbox_dns/graphql/__init__.py,sha256=eBGy2jQHU03EDyO2Mhj7DXlJRCo9IGloWUyCoZL609g,604
21
21
  netbox_dns/graphql/nameserver.py,sha256=mlQw1Po_Ax_fjyyXVBetyxlFLrCqmptYDgOspZvYtP4,527
22
22
  netbox_dns/graphql/record.py,sha256=r_dtqRAid7wN_XgWTCR6XuKSAnSTz0z7hKUXcFt4AjU,487
@@ -49,26 +49,27 @@ netbox_dns/migrations/0020_netbox_3_4.py,sha256=GwnmlYdnWgLwt2-H7hOr0Zm4-s28aDpe
49
49
  netbox_dns/migrations/0021_record_ip_address.py,sha256=Vs_0an8q0ya-JKYXjYPCut2uSUpLHIOHlqw0Y9ccp8Q,3304
50
50
  netbox_dns/migrations/0022_search.py,sha256=2S6wnH3TC2cMqCKrs0chnNnbWJDc9-MQO79kGSovoA4,891
51
51
  netbox_dns/migrations/0023_alter_record_value.py,sha256=4_4v8YZzU8_jadJqIUUjH6SIhNTeALWhclozTqYDmv0,378
52
+ netbox_dns/migrations/0024_tenancy.py,sha256=EmvBPNYe06h2lnaOLW55lN_vggN1W28VYdCljSOZmh8,1744
52
53
  netbox_dns/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
- netbox_dns/models.py,sha256=Ms65CC6X_1aen5Y7MmuXCqKZNRv7JilAdCRfEXlJ0Tk,29193
54
+ netbox_dns/models.py,sha256=9W7KeblPq4aLQ42VCwZQKArzPWC-tL4NhJWXk3PqpYs,30289
54
55
  netbox_dns/navigation.py,sha256=qwXl66Y2NKbV38ygijX9atQnHinfWbYtc1q6VaKLGP0,3158
55
56
  netbox_dns/tables/__init__.py,sha256=deqMJWAXtLukzoBMpk6DCRUK8nTuYYlVvEDYVidOa54,88
56
- netbox_dns/tables/nameserver.py,sha256=hkHtsrm20yAEbVh40tCETd_i_ThaRX8MSruAT6_5mcw,701
57
- netbox_dns/tables/record.py,sha256=MLE2cKc7OIJZuogTPmskfeqBTwOa8vzmHEXavqknmzU,3064
58
- netbox_dns/tables/view.py,sha256=JO6CDb5cUMppE5hObZ18-fEBxmPQGYA-xCxLcZ2vBa8,325
59
- netbox_dns/tables/zone.py,sha256=ywlePsymsK8jXVzc_zeAG6pQUyBS__9DDEvULRwsHXI,1660
57
+ netbox_dns/tables/nameserver.py,sha256=7Ap0px5gAHtgk5XFMpZCHccy9N-v8UKy19GP7fdWuPc,819
58
+ netbox_dns/tables/record.py,sha256=TINCEboqJPg6lm9NMs4G9tbA5o1K5KzQsWvxtEJJGdM,3026
59
+ netbox_dns/tables/view.py,sha256=gv6owrzcQ6G_Ue_xyWeO_k-oo9A81FeVQX-jlT84KFM,420
60
+ netbox_dns/tables/zone.py,sha256=QWdU--WVM9ccz-J4g_zbfLYI96AFbr4osnFbzNu8j5M,1732
60
61
  netbox_dns/template_content.py,sha256=bSqK2PGtWd5PXPtbMF3w9m3HMqHvsNZRjZ6wsZohWWA,2012
61
- netbox_dns/templates/netbox_dns/nameserver.html,sha256=QLBtDfMgF7IjYxPfxcZikXzo63pMHsVOj6QOzZh20Xk,1192
62
+ netbox_dns/templates/netbox_dns/nameserver.html,sha256=3AJVbsuhKg4Jy74rlvwrGSHd_IoDRdLT_XuK4EH3Djg,1623
62
63
  netbox_dns/templates/netbox_dns/record/managed.html,sha256=G6LPG1koUGuzUiwYdv1okdVa4sKaofiQegDBnsFL0kA,89
63
64
  netbox_dns/templates/netbox_dns/record/related.html,sha256=UhW0rwLrJdC1KqctthxdzKNlu0KFziNgaSphzqErM1M,378
64
- netbox_dns/templates/netbox_dns/record.html,sha256=QKcJq76csJkbJBJE-yvU_X3SFmtrvCV3wvCsRobffcA,4136
65
- netbox_dns/templates/netbox_dns/view.html,sha256=rVFUPjS76TXfUfSysEK45yh8IB6xmgWIzFSwoBFbaC8,919
65
+ netbox_dns/templates/netbox_dns/record.html,sha256=ukPI5RVmiIlJD42DW2Xa8BRU2_T5L4dY8b64mOGieMc,4611
66
+ netbox_dns/templates/netbox_dns/view.html,sha256=_lDjd2xY3upfGpNpemXXMzgsaKZlX3-PzPPAdYkIjvs,1350
66
67
  netbox_dns/templates/netbox_dns/zone/base.html,sha256=pucf_b7iGg4hCXqwIbR0_WtEQdeH2LQtTCRTSoeBhFc,460
67
68
  netbox_dns/templates/netbox_dns/zone/child.html,sha256=Y9dOUA8MPxuPqbbYV0KEZvLw1JIvfvOxbAVSv1c1l-k,2171
68
69
  netbox_dns/templates/netbox_dns/zone/managed_record.html,sha256=5P85eJuQOB7omih2vUXexRGjt4UF6McOM8f4D7QQbEw,524
69
70
  netbox_dns/templates/netbox_dns/zone/record.html,sha256=1oIRGXOZAjwmTMkTgArfKyVrmL54Sh_IN7IAF3qYEKM,2218
70
71
  netbox_dns/templates/netbox_dns/zone/related.html,sha256=1rOKq3RQ4ATsgmF5BUgTnPIr6KxFk9UDCnEe22Wi52I,215
71
- netbox_dns/templates/netbox_dns/zone.html,sha256=mKv_kyy8Mzn_pD83gUh33Zgc7pZ5LaXFO2BHBg1knlY,5480
72
+ netbox_dns/templates/netbox_dns/zone.html,sha256=9RzlmINR5MjfK32PkDf0rzQk1ZGq9GCADTIaR3geSlc,5875
72
73
  netbox_dns/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
74
  netbox_dns/templatetags/view_helpers.py,sha256=M7ND-gQhPTey_4wlhalthucqKJf8UjjP4LGuHMw3j-c,271
74
75
  netbox_dns/urls.py,sha256=OtgPuajiRiCgF1ho7djIXX5xp30QVMgZuMVj7VWsiW0,5202
@@ -79,7 +80,7 @@ netbox_dns/views/nameserver.py,sha256=6r6OtRstj04NLoNxidNAFJXkUlp-TIx4fHnuSp3ENa
79
80
  netbox_dns/views/record.py,sha256=eT-M-rqhCrcmhpEyKOnQ8SWnxAVUgams5e86nVL9uc0,2554
80
81
  netbox_dns/views/view.py,sha256=eRFqMjPLPRjagtnPlBrw8G20MNlSykvdAhXoX1bHEFw,1895
81
82
  netbox_dns/views/zone.py,sha256=M5SXKwctdRKhdE4m7aBltfvc1ogZ7wwbW_91SYaUctw,3600
82
- netbox_plugin_dns-0.18.10.dist-info/LICENSE,sha256=tziMJKpkMbySr09L6bIwsu7Ca9ICoqpMO3yAXgEMQA4,1076
83
- netbox_plugin_dns-0.18.10.dist-info/METADATA,sha256=uMsz0i31-eK8u2xe-WrMfJr291QCiNuHlUkjDLqFphc,3879
84
- netbox_plugin_dns-0.18.10.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
85
- netbox_plugin_dns-0.18.10.dist-info/RECORD,,
83
+ netbox_plugin_dns-0.19.0.dist-info/LICENSE,sha256=tziMJKpkMbySr09L6bIwsu7Ca9ICoqpMO3yAXgEMQA4,1076
84
+ netbox_plugin_dns-0.19.0.dist-info/METADATA,sha256=D-5_bQsxB9eGmHRO6j67AF0KhhAMKhS9WGsR9yWY2Fo,3880
85
+ netbox_plugin_dns-0.19.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
86
+ netbox_plugin_dns-0.19.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.6.1
2
+ Generator: poetry-core 1.7.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any