1# SPDX-License-Identifier: Apache-2.0
2# Copyright (C) 2025 Marcin Zieba <marcinpsk@gmail.com>
3from netbox.api.serializers import NetBoxModelSerializer
4from rest_framework import serializers
5
6from netbox_interface_name_rules.models import InterfaceNameRule
7
8
9class InterfaceNameRuleSerializer(NetBoxModelSerializer):
10 """Serializer for InterfaceNameRule with mutual-exclusivity validation."""
11
12 class Meta:
13 model = InterfaceNameRule
14 fields = [
15 "id",
16 "module_type",
17 "module_type_pattern",
18 "module_type_is_regex",
19 "parent_module_type",
20 "device_type",
21 "platform",
22 "name_template",
23 "channel_count",
24 "channel_start",
25 "description",
26 "enabled",
27 "applies_to_device_interfaces",
28 ]
29
30 def validate(self, attrs):
31 """Ensure module_type XOR module_type_pattern depending on regex mode."""
32 attrs = super().validate(attrs)
33 instance = self.instance
34
35 # For PATCH requests, fall back to existing instance values for fields not in attrs
36 is_device_level = attrs.get(
37 "applies_to_device_interfaces", getattr(instance, "applies_to_device_interfaces", False)
38 )
39 is_regex = attrs.get("module_type_is_regex", getattr(instance, "module_type_is_regex", False))
40 module_type = attrs.get("module_type", getattr(instance, "module_type", None))
41 pattern = attrs.get("module_type_pattern", getattr(instance, "module_type_pattern", ""))
42
43 if is_device_level:
44 # Device-level rules must not have a module_type FK
45 if module_type: # pragma: no cover # model.clean() runs first
46 raise serializers.ValidationError(
47 {"module_type": "Module type must be empty for device-level interface rules."}
48 )
49 elif is_regex:
50 if not pattern: # pragma: no cover # model.clean() runs first
51 raise serializers.ValidationError(
52 {"module_type_pattern": "Regex pattern is required when regex mode is enabled."}
53 )
54 if module_type: # pragma: no cover # model.clean() runs first
55 raise serializers.ValidationError(
56 {"module_type": "Cannot set both module_type and module_type_pattern. Choose one."}
57 )
58 else:
59 if not module_type: # pragma: no cover # model.clean() runs first
60 raise serializers.ValidationError(
61 {"module_type": "module_type is required when regex mode is disabled."}
62 )
63 if pattern: # pragma: no cover # model.clean() runs first
64 raise serializers.ValidationError(
65 {"module_type_pattern": "Cannot set module_type_pattern when regex mode is disabled."}
66 )
67 return attrs