netbox-plugin-dns 0.22.9__py3-none-any.whl → 1.0.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.

Files changed (115) hide show
  1. netbox_dns/__init__.py +4 -15
  2. netbox_dns/api/nested_serializers.py +4 -60
  3. netbox_dns/api/serializers.py +8 -314
  4. netbox_dns/api/serializers_/__init__.py +0 -0
  5. netbox_dns/api/serializers_/contact.py +37 -0
  6. netbox_dns/api/serializers_/nameserver.py +39 -0
  7. netbox_dns/api/serializers_/record.py +90 -0
  8. netbox_dns/api/serializers_/registrar.py +31 -0
  9. netbox_dns/api/serializers_/view.py +34 -0
  10. netbox_dns/api/serializers_/zone.py +159 -0
  11. netbox_dns/api/views.py +13 -13
  12. netbox_dns/fields/network.py +21 -22
  13. netbox_dns/fields/rfc2317.py +3 -3
  14. netbox_dns/{filters → filtersets}/contact.py +2 -1
  15. netbox_dns/filtersets/nameserver.py +37 -0
  16. netbox_dns/{filters → filtersets}/record.py +51 -6
  17. netbox_dns/{filters → filtersets}/registrar.py +2 -1
  18. netbox_dns/{filters → filtersets}/view.py +2 -2
  19. netbox_dns/filtersets/zone.py +205 -0
  20. netbox_dns/forms/contact.py +61 -33
  21. netbox_dns/forms/nameserver.py +21 -8
  22. netbox_dns/forms/record.py +65 -38
  23. netbox_dns/forms/registrar.py +45 -15
  24. netbox_dns/forms/view.py +23 -9
  25. netbox_dns/forms/zone.py +182 -188
  26. netbox_dns/graphql/__init__.py +17 -27
  27. netbox_dns/graphql/filters.py +49 -0
  28. netbox_dns/graphql/schema.py +66 -7
  29. netbox_dns/graphql/types.py +143 -0
  30. netbox_dns/management/commands/cleanup_database.py +0 -4
  31. netbox_dns/management/commands/cleanup_rrset_ttl.py +2 -4
  32. netbox_dns/management/commands/setup_coupling.py +15 -15
  33. netbox_dns/management/commands/update_soa.py +1 -1
  34. netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py +0 -27
  35. netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +558 -0
  36. netbox_dns/migrations/{0013_add_nameserver_zone_record_description.py → 0002_contact_description_registrar_description.py} +4 -9
  37. netbox_dns/migrations/0003_default_view.py +15 -0
  38. netbox_dns/migrations/0004_create_and_assign_default_view.py +26 -0
  39. netbox_dns/migrations/0005_alter_zone_view_not_null.py +18 -0
  40. netbox_dns/migrations/0020_netbox_3_4.py +1 -1
  41. netbox_dns/models/contact.py +6 -1
  42. netbox_dns/models/nameserver.py +2 -0
  43. netbox_dns/models/record.py +28 -33
  44. netbox_dns/models/registrar.py +5 -1
  45. netbox_dns/models/view.py +54 -1
  46. netbox_dns/models/zone.py +68 -54
  47. netbox_dns/navigation.py +1 -15
  48. netbox_dns/signals/ipam_coupling.py +3 -9
  49. netbox_dns/tables/contact.py +1 -0
  50. netbox_dns/tables/nameserver.py +0 -2
  51. netbox_dns/tables/registrar.py +1 -0
  52. netbox_dns/tables/view.py +9 -2
  53. netbox_dns/template_content.py +4 -8
  54. netbox_dns/templates/netbox_dns/contact.html +60 -56
  55. netbox_dns/templates/netbox_dns/nameserver.html +27 -27
  56. netbox_dns/templates/netbox_dns/record.html +92 -94
  57. netbox_dns/templates/netbox_dns/registrar.html +38 -36
  58. netbox_dns/templates/netbox_dns/view.html +25 -21
  59. netbox_dns/templates/netbox_dns/zone/base.html +5 -3
  60. netbox_dns/templates/netbox_dns/zone/child.html +3 -3
  61. netbox_dns/templates/netbox_dns/zone/managed_record.html +1 -1
  62. netbox_dns/templates/netbox_dns/zone/record.html +3 -3
  63. netbox_dns/templates/netbox_dns/zone/registration.html +26 -27
  64. netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html +1 -1
  65. netbox_dns/templates/netbox_dns/zone.html +148 -149
  66. netbox_dns/urls/__init__.py +17 -0
  67. netbox_dns/urls/contact.py +51 -0
  68. netbox_dns/urls/nameserver.py +69 -0
  69. netbox_dns/urls/record.py +41 -0
  70. netbox_dns/urls/registrar.py +63 -0
  71. netbox_dns/urls/view.py +39 -0
  72. netbox_dns/urls/zone.py +57 -0
  73. netbox_dns/utilities/__init__.py +1 -6
  74. netbox_dns/utilities/ipam_coupling.py +2 -7
  75. netbox_dns/validators/dns_name.py +4 -9
  76. netbox_dns/validators/rfc2317.py +2 -2
  77. netbox_dns/views/contact.py +4 -4
  78. netbox_dns/views/nameserver.py +5 -5
  79. netbox_dns/views/record.py +15 -23
  80. netbox_dns/views/registrar.py +4 -4
  81. netbox_dns/views/view.py +4 -4
  82. netbox_dns/views/zone.py +7 -8
  83. {netbox_plugin_dns-0.22.9.dist-info → netbox_plugin_dns-1.0.0.dist-info}/METADATA +27 -13
  84. netbox_plugin_dns-1.0.0.dist-info/RECORD +112 -0
  85. netbox_dns/filters/nameserver.py +0 -18
  86. netbox_dns/filters/zone.py +0 -112
  87. netbox_dns/graphql/contact.py +0 -19
  88. netbox_dns/graphql/nameserver.py +0 -19
  89. netbox_dns/graphql/record.py +0 -19
  90. netbox_dns/graphql/registrar.py +0 -19
  91. netbox_dns/graphql/view.py +0 -19
  92. netbox_dns/graphql/zone.py +0 -19
  93. netbox_dns/migrations/0001_initial.py +0 -115
  94. netbox_dns/migrations/0002_zone_default_ttl.py +0 -18
  95. netbox_dns/migrations/0003_soa_managed_records.py +0 -112
  96. netbox_dns/migrations/0004_create_ptr_for_a_aaaa_records.py +0 -80
  97. netbox_dns/migrations/0005_update_ns_records.py +0 -41
  98. netbox_dns/migrations/0006_zone_soa_serial_auto.py +0 -29
  99. netbox_dns/migrations/0007_alter_zone_soa_serial_auto.py +0 -17
  100. netbox_dns/migrations/0008_zone_status_names.py +0 -21
  101. netbox_dns/migrations/0009_netbox32.py +0 -71
  102. netbox_dns/migrations/0010_update_soa_records.py +0 -58
  103. netbox_dns/migrations/0011_add_view_model.py +0 -70
  104. netbox_dns/migrations/0012_adjust_zone_and_record.py +0 -17
  105. netbox_dns/migrations/0014_add_view_description.py +0 -16
  106. netbox_dns/migrations/0015_add_record_status.py +0 -17
  107. netbox_dns/migrations/0016_cleanup_ptr_records.py +0 -38
  108. netbox_dns/migrations/0017_alter_record_ttl.py +0 -17
  109. netbox_dns/migrations/0018_zone_arpa_network.py +0 -51
  110. netbox_dns/migrations/0019_update_ns_ttl.py +0 -19
  111. netbox_dns/urls.py +0 -297
  112. netbox_plugin_dns-0.22.9.dist-info/RECORD +0 -117
  113. /netbox_dns/{filters → filtersets}/__init__.py +0 -0
  114. {netbox_plugin_dns-0.22.9.dist-info → netbox_plugin_dns-1.0.0.dist-info}/LICENSE +0 -0
  115. {netbox_plugin_dns-0.22.9.dist-info → netbox_plugin_dns-1.0.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,159 @@
1
+ from rest_framework import serializers
2
+
3
+ from netbox.api.serializers import NetBoxModelSerializer
4
+ from tenancy.api.serializers_.tenants import TenantSerializer
5
+
6
+ from netbox_dns.api.serializers_.view import ViewSerializer
7
+ from netbox_dns.api.serializers_.nameserver import NameServerSerializer
8
+ from netbox_dns.api.serializers_.registrar import RegistrarSerializer
9
+ from netbox_dns.api.serializers_.contact import ContactSerializer
10
+ from netbox_dns.api.nested_serializers import NestedZoneSerializer
11
+
12
+ from netbox_dns.models import Zone
13
+
14
+
15
+ class ZoneSerializer(NetBoxModelSerializer):
16
+ url = serializers.HyperlinkedIdentityField(
17
+ view_name="plugins-api:netbox_dns-api:zone-detail"
18
+ )
19
+ view = ViewSerializer(
20
+ nested=True,
21
+ many=False,
22
+ read_only=False,
23
+ required=False,
24
+ default=None,
25
+ help_text="View the zone belongs to",
26
+ )
27
+ nameservers = NameServerSerializer(
28
+ nested=True,
29
+ many=True,
30
+ read_only=False,
31
+ required=False,
32
+ help_text="Nameservers for the zone",
33
+ )
34
+ soa_mname = NameServerSerializer(
35
+ nested=True,
36
+ many=False,
37
+ read_only=False,
38
+ required=False,
39
+ help_text="Primary nameserver for the zone",
40
+ )
41
+ rfc2317_parent_zone = NestedZoneSerializer(
42
+ many=False,
43
+ read_only=True,
44
+ required=False,
45
+ help_text="RFC2317 arent zone for the zone",
46
+ )
47
+ rfc2317_child_zones = NestedZoneSerializer(
48
+ many=True,
49
+ read_only=True,
50
+ required=False,
51
+ help_text="RFC2317 child zones of the zone",
52
+ )
53
+ registrar = RegistrarSerializer(
54
+ nested=True,
55
+ many=False,
56
+ read_only=False,
57
+ required=False,
58
+ help_text="The registrar the domain is registered with",
59
+ )
60
+ registrant = ContactSerializer(
61
+ many=False,
62
+ read_only=False,
63
+ required=False,
64
+ help_text="The owner of the domain",
65
+ )
66
+ admin_c = ContactSerializer(
67
+ many=False,
68
+ read_only=False,
69
+ required=False,
70
+ help_text="The administrative contact for the domain",
71
+ )
72
+ tech_c = ContactSerializer(
73
+ many=False,
74
+ read_only=False,
75
+ required=False,
76
+ help_text="The technical contact for the domain",
77
+ )
78
+ billing_c = ContactSerializer(
79
+ many=False,
80
+ read_only=False,
81
+ required=False,
82
+ help_text="The billing contact for the domain",
83
+ )
84
+ active = serializers.BooleanField(
85
+ required=False,
86
+ read_only=True,
87
+ allow_null=True,
88
+ )
89
+ tenant = TenantSerializer(nested=True, required=False, allow_null=True)
90
+
91
+ def create(self, validated_data):
92
+ nameservers = validated_data.pop("nameservers", None)
93
+
94
+ zone = super().create(validated_data)
95
+
96
+ if nameservers is not None:
97
+ zone.nameservers.set(nameservers)
98
+
99
+ return zone
100
+
101
+ def update(self, instance, validated_data):
102
+ nameservers = validated_data.pop("nameservers", None)
103
+
104
+ zone = super().update(instance, validated_data)
105
+
106
+ if nameservers is not None:
107
+ zone.nameservers.set(nameservers)
108
+
109
+ return zone
110
+
111
+ class Meta:
112
+ model = Zone
113
+ fields = (
114
+ "id",
115
+ "url",
116
+ "name",
117
+ "view",
118
+ "display",
119
+ "nameservers",
120
+ "status",
121
+ "description",
122
+ "tags",
123
+ "created",
124
+ "last_updated",
125
+ "default_ttl",
126
+ "soa_ttl",
127
+ "soa_mname",
128
+ "soa_rname",
129
+ "soa_serial",
130
+ "soa_serial_auto",
131
+ "soa_refresh",
132
+ "soa_retry",
133
+ "soa_expire",
134
+ "soa_minimum",
135
+ "rfc2317_prefix",
136
+ "rfc2317_parent_managed",
137
+ "rfc2317_parent_zone",
138
+ "rfc2317_child_zones",
139
+ "registrar",
140
+ "registry_domain_id",
141
+ "registrant",
142
+ "tech_c",
143
+ "admin_c",
144
+ "billing_c",
145
+ "active",
146
+ "custom_fields",
147
+ "tenant",
148
+ )
149
+ brief_fields = (
150
+ "id",
151
+ "url",
152
+ "name",
153
+ "view",
154
+ "display",
155
+ "status",
156
+ "description",
157
+ "rfc2317_prefix",
158
+ "active",
159
+ )
netbox_dns/api/views.py CHANGED
@@ -13,13 +13,13 @@ from netbox_dns.api.serializers import (
13
13
  RegistrarSerializer,
14
14
  ContactSerializer,
15
15
  )
16
- from netbox_dns.filters import (
17
- ViewFilter,
18
- ZoneFilter,
19
- NameServerFilter,
20
- RecordFilter,
21
- RegistrarFilter,
22
- ContactFilter,
16
+ from netbox_dns.filtersets import (
17
+ ViewFilterSet,
18
+ ZoneFilterSet,
19
+ NameServerFilterSet,
20
+ RecordFilterSet,
21
+ RegistrarFilterSet,
22
+ ContactFilterSet,
23
23
  )
24
24
  from netbox_dns.models import View, Zone, NameServer, Record, Registrar, Contact
25
25
 
@@ -32,7 +32,7 @@ class NetBoxDNSRootView(APIRootView):
32
32
  class ViewViewSet(NetBoxModelViewSet):
33
33
  queryset = View.objects.all()
34
34
  serializer_class = ViewSerializer
35
- filterset_class = ViewFilter
35
+ filterset_class = ViewFilterSet
36
36
 
37
37
  @action(detail=True, methods=["get"])
38
38
  def views(self, request, pk=None):
@@ -51,7 +51,7 @@ class ZoneViewSet(NetBoxModelViewSet):
51
51
  "tenant",
52
52
  )
53
53
  serializer_class = ZoneSerializer
54
- filterset_class = ZoneFilter
54
+ filterset_class = ZoneFilterSet
55
55
 
56
56
  @action(detail=True, methods=["get"])
57
57
  def records(self, request, pk=None):
@@ -71,7 +71,7 @@ class ZoneViewSet(NetBoxModelViewSet):
71
71
  class NameServerViewSet(NetBoxModelViewSet):
72
72
  queryset = NameServer.objects.prefetch_related("zones", "tenant")
73
73
  serializer_class = NameServerSerializer
74
- filterset_class = NameServerFilter
74
+ filterset_class = NameServerFilterSet
75
75
 
76
76
  @action(detail=True, methods=["get"])
77
77
  def zones(self, request, pk=None):
@@ -83,7 +83,7 @@ class NameServerViewSet(NetBoxModelViewSet):
83
83
  class RecordViewSet(NetBoxModelViewSet):
84
84
  queryset = Record.objects.all().prefetch_related("zone", "zone__view", "tenant")
85
85
  serializer_class = RecordSerializer
86
- filterset_class = RecordFilter
86
+ filterset_class = RecordFilterSet
87
87
 
88
88
  def destroy(self, request, *args, **kwargs):
89
89
  v_object = self.get_object()
@@ -105,10 +105,10 @@ class RecordViewSet(NetBoxModelViewSet):
105
105
  class RegistrarViewSet(NetBoxModelViewSet):
106
106
  queryset = Registrar.objects.all()
107
107
  serializer_class = RegistrarSerializer
108
- filterset_class = RegistrarFilter
108
+ filterset_class = RegistrarFilterSet
109
109
 
110
110
 
111
111
  class ContactViewSet(NetBoxModelViewSet):
112
112
  queryset = Contact.objects.all()
113
113
  serializer_class = ContactSerializer
114
- filterset_class = ContactFilter
114
+ filterset_class = ContactFilterSet
@@ -1,6 +1,6 @@
1
1
  from django import forms
2
2
  from django.db import models
3
- from django.db.models import Lookup, Transform
3
+ from django.db.models import Lookup, Transform, IntegerField
4
4
  from django.core.exceptions import ValidationError
5
5
 
6
6
  from netaddr import AddrFormatError, IPNetwork
@@ -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, qn, connection):
13
- lhs, lhs_params = self.process_lhs(qn, connection)
14
- rhs, rhs_params = self.process_rhs(qn, connection)
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)
15
15
  params = lhs_params + rhs_params
16
- return "%s >> %s" % (lhs, rhs), params
16
+ return f"{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, qn, connection):
23
- lhs, lhs_params = self.process_lhs(qn, connection)
24
- rhs, rhs_params = self.process_rhs(qn, connection)
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)
25
25
  params = lhs_params + rhs_params
26
- return "%s >>= %s" % (lhs, rhs), params
26
+ return f"{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, qn, connection):
33
- lhs, lhs_params = self.process_lhs(qn, connection)
34
- rhs, rhs_params = self.process_rhs(qn, connection)
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)
35
35
  params = lhs_params + rhs_params
36
- return "%s << %s" % (lhs, rhs), params
36
+ return f"{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, qn, connection):
43
- lhs, lhs_params = self.process_lhs(qn, connection)
44
- rhs, rhs_params = self.process_rhs(qn, connection)
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)
45
45
  params = lhs_params + rhs_params
46
- return "%s <<= %s" % (lhs, rhs), params
46
+ return f"{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, qn, connection):
53
- lhs, lhs_params = self.process_lhs(qn, connection)
54
- rhs, rhs_params = self.process_rhs(qn, connection)
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)
55
55
  params = lhs_params + rhs_params
56
- return "%s && %s" % (lhs, rhs), params
56
+ return f"{lhs} && {rhs}", params
57
57
 
58
58
 
59
59
  class NetworkFormField(forms.Field):
@@ -118,7 +118,6 @@ class NetMaskLength(Transform):
118
118
  function = "MASKLEN"
119
119
  lookup_name = "net_mask_length"
120
120
 
121
- @property
122
121
  def output_field(self):
123
122
  return IntegerField()
124
123
 
@@ -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
- else:
22
- raise ValidationError(INVALID_RFC2317)
21
+
22
+ raise ValidationError(INVALID_RFC2317)
23
23
 
24
24
  if len(value.split("/")) != 2:
25
25
  raise ValidationError("Please specify the prefix length")
@@ -51,7 +51,7 @@ class RFC2317NetworkField(models.Field):
51
51
 
52
52
  try:
53
53
  ip_network = IPNetwork(value)
54
- except (AddressFormatError, TypeError, ValueError) as exc:
54
+ except (AddrFormatError, TypeError, ValueError) as exc:
55
55
  raise ValidationError(exc)
56
56
 
57
57
  if ip_network.version != 4:
@@ -5,12 +5,13 @@ from netbox.filtersets import NetBoxModelFilterSet
5
5
  from netbox_dns.models import Contact
6
6
 
7
7
 
8
- class ContactFilter(NetBoxModelFilterSet):
8
+ class ContactFilterSet(NetBoxModelFilterSet):
9
9
  class Meta:
10
10
  model = Contact
11
11
  fields = (
12
12
  "id",
13
13
  "name",
14
+ "description",
14
15
  "contact_id",
15
16
  "organization",
16
17
  "street",
@@ -0,0 +1,37 @@
1
+ import django_filters
2
+ from django.db.models import Q
3
+
4
+ from netbox.filtersets import NetBoxModelFilterSet
5
+ from tenancy.filtersets import TenancyFilterSet
6
+
7
+ from netbox_dns.models import NameServer, Zone
8
+
9
+
10
+ class NameServerFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
11
+ zone_id = django_filters.ModelMultipleChoiceFilter(
12
+ field_name="zones",
13
+ queryset=Zone.objects.all(),
14
+ to_field_name="id",
15
+ label="Zones",
16
+ )
17
+ soa_zone_id = django_filters.ModelMultipleChoiceFilter(
18
+ method="filter_soa_zones",
19
+ queryset=Zone.objects.all(),
20
+ label="SOA Zones",
21
+ )
22
+
23
+ class Meta:
24
+ model = NameServer
25
+ fields = ("id", "name", "description")
26
+
27
+ def search(self, queryset, name, value):
28
+ if not value.strip():
29
+ return queryset
30
+ qs_filter = Q(name__icontains=value)
31
+ return queryset.filter(qs_filter)
32
+
33
+ def filter_soa_zones(self, queryset, name, value):
34
+ if not value:
35
+ return queryset
36
+ soa_mnames = {zone.soa_mname.pk for zone in value}
37
+ return queryset.filter(pk__in=soa_mnames)
@@ -1,3 +1,5 @@
1
+ import netaddr
2
+
1
3
  import django_filters
2
4
  from django.db.models import Q
3
5
 
@@ -5,16 +7,17 @@ from netbox.filtersets import NetBoxModelFilterSet
5
7
  from tenancy.filtersets import TenancyFilterSet
6
8
  from utilities.filters import MultiValueCharFilter
7
9
 
10
+ from ipam.models import IPAddress
11
+
8
12
  from netbox_dns.models import View, Zone, Record, RecordTypeChoices, RecordStatusChoices
9
13
 
10
14
 
11
- class RecordFilter(TenancyFilterSet, NetBoxModelFilterSet):
15
+ class RecordFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
12
16
  fqdn = MultiValueCharFilter(
13
17
  method="filter_fqdn",
14
18
  )
15
19
  type = django_filters.MultipleChoiceFilter(
16
20
  choices=RecordTypeChoices,
17
- null_value=None,
18
21
  )
19
22
  status = django_filters.MultipleChoiceFilter(
20
23
  choices=RecordStatusChoices,
@@ -40,20 +43,48 @@ class RecordFilter(TenancyFilterSet, NetBoxModelFilterSet):
40
43
  to_field_name="name",
41
44
  label="View the Parent Zone belongs to",
42
45
  )
46
+ address_record_id = django_filters.ModelMultipleChoiceFilter(
47
+ field_name="address_record",
48
+ queryset=Record.objects.all(),
49
+ to_field_name="id",
50
+ label="Address Record",
51
+ )
52
+ ptr_record_id = django_filters.ModelMultipleChoiceFilter(
53
+ field_name="ptr_record",
54
+ queryset=Record.objects.all(),
55
+ to_field_name="id",
56
+ label="Pointer Record",
57
+ )
58
+ rfc2317_cname_record_id = django_filters.ModelMultipleChoiceFilter(
59
+ field_name="rfc2317_cname_record",
60
+ queryset=Record.objects.all(),
61
+ to_field_name="id",
62
+ label="Pointer Record",
63
+ )
64
+ ipam_ip_address_id = django_filters.ModelMultipleChoiceFilter(
65
+ field_name="ipam_ip_address",
66
+ queryset=IPAddress.objects.all(),
67
+ to_field_name="id",
68
+ label="IPAM IP Address",
69
+ )
70
+ ip_address = MultiValueCharFilter(
71
+ method="filter_ip_address",
72
+ label="IP Address",
73
+ )
74
+
43
75
  managed = django_filters.BooleanFilter()
44
76
 
45
77
  class Meta:
46
78
  model = Record
47
79
  fields = (
48
80
  "id",
49
- "type",
50
81
  "name",
51
82
  "fqdn",
83
+ "description",
84
+ "ttl",
52
85
  "value",
53
- "status",
54
- "zone",
86
+ "disable_ptr",
55
87
  "managed",
56
- "tenant",
57
88
  )
58
89
 
59
90
  def filter_fqdn(self, queryset, name, value):
@@ -68,6 +99,20 @@ class RecordFilter(TenancyFilterSet, NetBoxModelFilterSet):
68
99
 
69
100
  return queryset.filter(fqdn__in=fqdns)
70
101
 
102
+ def filter_ip_address(self, queryset, name, value):
103
+ if not value:
104
+ return queryset
105
+ try:
106
+ ip_addresses = [
107
+ str(netaddr.IPAddress(item)) for item in value if item.strip()
108
+ ]
109
+ if not ip_addresses:
110
+ return queryset
111
+
112
+ return queryset.filter(ip_address__in=ip_addresses)
113
+ except (netaddr.AddrFormatError, ValueError):
114
+ return queryset.none()
115
+
71
116
  def search(self, queryset, name, value):
72
117
  if not value.strip():
73
118
  return queryset
@@ -5,12 +5,13 @@ from netbox.filtersets import NetBoxModelFilterSet
5
5
  from netbox_dns.models import Registrar
6
6
 
7
7
 
8
- class RegistrarFilter(NetBoxModelFilterSet):
8
+ class RegistrarFilterSet(NetBoxModelFilterSet):
9
9
  class Meta:
10
10
  model = Registrar
11
11
  fields = (
12
12
  "id",
13
13
  "name",
14
+ "description",
14
15
  "iana_id",
15
16
  "address",
16
17
  "referral_url",
@@ -6,10 +6,10 @@ from tenancy.filtersets import TenancyFilterSet
6
6
  from netbox_dns.models import View
7
7
 
8
8
 
9
- class ViewFilter(NetBoxModelFilterSet, TenancyFilterSet):
9
+ class ViewFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
10
10
  class Meta:
11
11
  model = View
12
- fields = ("id", "name", "tenant")
12
+ fields = ("id", "name", "default_view", "description")
13
13
 
14
14
  def search(self, queryset, name, value):
15
15
  if not value.strip():