diff --git a/netbox_dns/models/record.py b/netbox_dns/models/record.py
index 279ed613..749cb477 100644
--- a/netbox_dns/models/record.py
+++ b/netbox_dns/models/record.py
@@ -241,6 +241,16 @@ def fqdn(self):
return name.to_text()
+ @property
+ def value_fqdn(self):
+ if self.type != RecordTypeChoices.CNAME:
+ return None
+
+ zone = dns_name.from_text(self.zone.name)
+ value_fqdn = dns_name.from_text(self.value, origin=zone)
+
+ return value_fqdn.to_text()
+
@property
def address_from_name(self):
prefix = arpa_to_prefix(self.fqdn)
diff --git a/netbox_dns/templates/netbox_dns/record.html b/netbox_dns/templates/netbox_dns/record.html
index f6f6201d..efca0fa9 100644
--- a/netbox_dns/templates/netbox_dns/record.html
+++ b/netbox_dns/templates/netbox_dns/record.html
@@ -112,12 +112,6 @@
{{ object.ipam_ip_address }} |
{% endif %}
- {% if object.rfc2317_cname_record %}
-
- RFC2317 CNAME Record |
- {{ object.rfc2317_cname_record }} |
-
- {% endif %}
Status |
{% badge object.get_status_display bg_color=object.get_status_color %} |
@@ -131,23 +125,13 @@
- {% if object.rfc2317_ptr_records.all|length %}
+ {% if cname_target_table and cname_target_table.rows|length > 0 %}
-
-
+ {% include 'inc/panel_table.html' with table=cname_target_table heading='CNAME Targets' %}
+
+ {% elif cname_table and cname_table.rows|length > 0 %}
+
+ {% include 'inc/panel_table.html' with table=cname_table heading='CNAMEs' %}
{% endif %}
{% if not object.managed %}
diff --git a/netbox_dns/views/record.py b/netbox_dns/views/record.py
index 8fccb98e..2f155999 100644
--- a/netbox_dns/views/record.py
+++ b/netbox_dns/views/record.py
@@ -1,5 +1,8 @@
from dns import name as dns_name
+from django.db.models import Q
+from django.db.models.functions import Length
+
from netbox.views import generic
from netbox_dns.filters import RecordFilter
@@ -9,8 +12,8 @@
RecordForm,
RecordBulkEditForm,
)
-from netbox_dns.models import Record
-from netbox_dns.tables import RecordTable, ManagedRecordTable
+from netbox_dns.models import Record, RecordTypeChoices, Zone
+from netbox_dns.tables import RecordTable, ManagedRecordTable, RelatedRecordTable
from netbox_dns.utilities import value_to_unicode
@@ -37,6 +40,72 @@ class ManagedRecordListView(generic.ObjectListView):
class RecordView(generic.ObjectView):
queryset = Record.objects.all().prefetch_related("zone", "ptr_record")
+ def get_value_records(self, instance):
+ value_fqdn = dns_name.from_text(instance.value_fqdn)
+ value_zone_names = [
+ value_fqdn.split(length)[1].to_text().rstrip(".")
+ for length in range(2, len(value_fqdn))
+ ]
+
+ value_zone = (
+ Zone.objects.filter(instance.zone.view_filter, name__in=value_zone_names)
+ .order_by(Length("name").desc())
+ .first()
+ )
+ if not value_zone:
+ return None
+
+ value_name = value_fqdn.relativize(dns_name.from_text(value_zone.name))
+ cname_targets = Record.objects.filter(zone=value_zone, name=value_name)
+
+ if cname_targets:
+ return RelatedRecordTable(
+ data=cname_targets,
+ )
+
+ return None
+
+ def get_cname_records(self, instance):
+ view_filter = (
+ Q(zone__view__isnull=True)
+ if instance.zone.view is None
+ else Q(zone__view=instance.zone.view)
+ )
+ cname_records = set(
+ Record.objects.filter(
+ view_filter, value=instance.fqdn, type=RecordTypeChoices.CNAME
+ )
+ )
+
+ fqdn = dns_name.from_text(instance.fqdn)
+ parent_zone_names = [
+ fqdn.split(length)[1].to_text().rstrip(".")
+ for length in range(1, len(fqdn))
+ ]
+
+ parent_zones = Zone.objects.filter(
+ instance.zone.view_filter, name__in=parent_zone_names
+ )
+
+ for parent_zone in parent_zones:
+ parent_cname_records = Record.objects.filter(
+ view_filter, type=RecordTypeChoices.CNAME, zone=parent_zone
+ )
+ cname_records = cname_records.union(
+ set(
+ record
+ for record in parent_cname_records
+ if record.value_fqdn == instance.fqdn
+ )
+ )
+
+ if cname_records:
+ return RelatedRecordTable(
+ data=cname_records,
+ )
+
+ return None
+
def get_extra_context(self, request, instance):
context = {}
@@ -48,6 +117,11 @@ def get_extra_context(self, request, instance):
if instance.value != unicode_value:
context["unicode_value"] = unicode_value
+ if instance.type == RecordTypeChoices.CNAME:
+ context["cname_target_table"] = self.get_value_records(instance)
+ else:
+ context["cname_table"] = self.get_cname_records(instance)
+
return context