Skip to content

Commit

Permalink
Merge pull request #102 from peteeckel/fix/ipam-coupling-model
Browse files Browse the repository at this point in the history
Internal improvements to the IPAM coupling feature
  • Loading branch information
peteeckel authored Dec 21, 2023
2 parents 24eb768 + c6c8859 commit ef3fb7b
Show file tree
Hide file tree
Showing 12 changed files with 1,496 additions and 643 deletions.
1 change: 0 additions & 1 deletion netbox_dns/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class DNSConfig(PluginConfig):
version = __version__
author = "Peter Eckel"
author_email = "[email protected]"
middleware = ["netbox_dns.middleware.IpamCouplingMiddleware"]
required_settings = []
default_settings = {
"zone_default_ttl": 86400,
Expand Down
226 changes: 0 additions & 226 deletions netbox_dns/middleware.py

This file was deleted.

2 changes: 2 additions & 0 deletions netbox_dns/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
from .view import *
from .contact import *
from .registrar import *

from netbox_dns.signals import ipam_coupling
File renamed without changes.
149 changes: 149 additions & 0 deletions netbox_dns/signals/ipam_coupling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
from django.dispatch import receiver
from django.db.models.signals import pre_save, post_save, pre_delete
from django.core.exceptions import ValidationError, PermissionDenied
from rest_framework.exceptions import PermissionDenied as APIPermissionDenied

from netbox.signals import post_clean
from netbox.context import current_request
from ipam.models import IPAddress

from netbox_dns.models import Zone
from netbox_dns.utilities.ipam_coupling import (
ipaddress_cf_data,
get_address_record,
new_address_record,
update_address_record,
check_permission,
dns_changed,
DNSPermissionDenied,
)

try:
# NetBox 3.5.0 - 3.5.7, 3.5.9+
from extras.plugins import get_plugin_config
except ImportError:
# NetBox 3.5.8
from extras.plugins.utils import get_plugin_config


@receiver(post_clean, sender=IPAddress)
def ip_address_check_permissions_save(instance, **kwargs):
if not get_plugin_config("netbox_dns", "feature_ipam_coupling"):
return

request = current_request.get()
if request is None:
return

try:
if instance.id is None:
record = new_address_record(instance)
if record is not None:
record.full_clean()
check_permission(request, "netbox_dns.add_record", record)

else:
if not dns_changed(IPAddress.objects.get(pk=instance.id), instance):
return

record = get_address_record(instance)
if record is not None:
name, zone_id = ipaddress_cf_data(instance)
if zone_id is not None:
update_address_record(record, instance)
record.full_clean()
check_permission(request, "netbox_dns.change_record", record)
else:
check_permission(request, "netbox_dns.delete_record", record)

else:
record = new_address_record(instance)
if record is not None:
record.full_clean()
check_permission(request, "netbox_dns.add_record", record)

except ValidationError as exc:
if hasattr(exc, "error_dict"):
value = exc.error_dict.pop("name", None)
if value is not None:
exc.error_dict["cf_ipaddress_dns_record_name"] = value

value = exc.error_dict.pop("value", None)
if value is not None:
exc.error_dict["cf_ipaddress_dns_record_name"] = value

raise ValidationError(exc)

except DNSPermissionDenied as exc:
raise ValidationError(exc)


@receiver(pre_delete, sender=IPAddress)
def ip_address_delete_address_record(instance, **kwargs):
if not get_plugin_config("netbox_dns", "feature_ipam_coupling"):
return

request = current_request.get()
if request is not None:
try:
for record in instance.netbox_dns_records.all():
check_permission(request, "netbox_dns.delete_record", record)

except DNSPermissionDenied as exc:
if request.path_info.startswith("/api/"):
raise APIPermissionDenied(exc) from None

raise PermissionDenied(exc) from None

for record in instance.netbox_dns_records.all():
record.delete()


#
# Update DNS related fields according to the contents of the IPAM-DNS
# coupling custom fields.
#
@receiver(pre_save, sender=IPAddress)
def ip_address_update_dns_information(instance, **kwargs):
if not get_plugin_config("netbox_dns", "feature_ipam_coupling"):
return

name, zone_id = ipaddress_cf_data(instance)

if zone_id is not None:
instance.dns_name = f"{name}.{Zone.objects.get(pk=zone_id).name}"
else:
instance.dns_name = ""
instance.custom_field_data["ipaddress_dns_record_name"] = None
instance.custom_field_data["ipaddress_dns_zone_id"] = None


#
# Handle DNS record operation after IPAddress has been created or modified
#
@receiver(post_save, sender=IPAddress)
def ip_address_update_address_record(instance, **kwargs):
if not get_plugin_config("netbox_dns", "feature_ipam_coupling"):
return

name, zone_id = ipaddress_cf_data(instance)

if zone_id is None:
#
# Name/Zone CF data has been removed: Remove the DNS address record
#
for record in instance.netbox_dns_records.all():
record.delete()

else:
#
# Name/Zone CF data is present: Check for a DNS address record and add
# or modify it as necessary
#
record = get_address_record(instance)
if record is None:
record = new_address_record(instance)
else:
update_address_record(record, instance)

record.save()
1 change: 0 additions & 1 deletion netbox_dns/tables/zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
ChoiceFieldColumn,
NetBoxTable,
TagColumn,
ActionsColumn,
)
from tenancy.tables import TenancyColumnsMixin

Expand Down
Loading

0 comments on commit ef3fb7b

Please sign in to comment.