Browse Source

Fixes #23125: Add missing standard REST API fields for VLAN Translation Policies and Rules (#23127)

Martin Hauser 4 hours ago
parent
commit
dfb99e1f69

+ 10 - 3
netbox/ipam/api/serializers_/vlans.py

@@ -117,13 +117,20 @@ class VLANTranslationRuleSerializer(NetBoxModelSerializer):
 
     class Meta:
         model = VLANTranslationRule
-        fields = ['id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description']
+        fields = [
+            'id', 'url', 'display_url', 'display', 'policy', 'local_vid', 'remote_vid', 'description', 'tags',
+            'custom_fields', 'created', 'last_updated',
+        ]
+        brief_fields = ('id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description')
 
 
 class VLANTranslationPolicySerializer(PrimaryModelSerializer):
-    rules = VLANTranslationRuleSerializer(many=True, read_only=True)
+    rules = VLANTranslationRuleSerializer(nested=True, many=True, read_only=True)
 
     class Meta:
         model = VLANTranslationPolicy
-        fields = ['id', 'url', 'display', 'name', 'description', 'display', 'rules', 'owner', 'comments']
+        fields = [
+            'id', 'url', 'display_url', 'display', 'name', 'description', 'rules', 'owner', 'comments', 'tags',
+            'custom_fields', 'created', 'last_updated',
+        ]
         brief_fields = ('id', 'url', 'display', 'name', 'description')

+ 2 - 2
netbox/ipam/tests/query_counts.json

@@ -28,9 +28,9 @@
   "vlan:list_objects_with_permission": 21,
   "vlangroup:api_list_objects": 12,
   "vlangroup:list_objects_with_permission": 22,
-  "vlantranslationpolicy:api_list_objects": 12,
+  "vlantranslationpolicy:api_list_objects": 13,
   "vlantranslationpolicy:list_objects_with_permission": 17,
-  "vlantranslationrule:api_list_objects": 12,
+  "vlantranslationrule:api_list_objects": 13,
   "vlantranslationrule:list_objects_with_permission": 18,
   "vrf:api_list_objects": 20,
   "vrf:list_objects_with_permission": 17

+ 57 - 1
netbox/ipam/tests/test_api.py

@@ -11,7 +11,7 @@ from ipam.choices import *
 from ipam.models import *
 from tenancy.models import Tenant
 from utilities.data import string_to_ranges
-from utilities.testing import APITestCase, APIViewTestCases, create_test_device, disable_logging
+from utilities.testing import APITestCase, APIViewTestCases, create_tags, create_test_device, disable_logging
 
 
 class AppTestCase(APITestCase):
@@ -1422,6 +1422,39 @@ class VLANTranslationPolicyTestCase(APIViewTestCases.APIViewTestCase):
             },
         ]
 
+    def test_standard_fields_in_representation(self):
+        """The standard URL, tag, custom-field and change-tracking names appear in the representation."""
+        policy = VLANTranslationPolicy.objects.first()
+        self.add_permissions('ipam.view_vlantranslationpolicy')
+
+        response = self.client.get(self._get_detail_url(policy), **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        expected = {'display_url', 'tags', 'custom_fields', 'created', 'last_updated'}
+        self.assertEqual(expected - set(response.data), set())
+
+    def test_nested_rules_are_brief(self):
+        """Rules nested in a policy representation carry only the rule serializer's brief fields."""
+        policy = VLANTranslationPolicy.objects.first()
+        VLANTranslationRule.objects.create(policy=policy, local_vid=100, remote_vid=200)
+        self.add_permissions('ipam.view_vlantranslationpolicy')
+
+        response = self.client.get(self._get_detail_url(policy), **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertEqual(sorted(response.data['rules'][0]), VLANTranslationRuleTestCase.brief_fields)
+
+    def test_update_tags(self):
+        """Tags supplied on update are assigned and rendered in the response."""
+        policy = VLANTranslationPolicy.objects.first()
+        create_tags('Alpha')
+        self.add_permissions('ipam.change_vlantranslationpolicy', 'extras.view_tag')
+
+        data = {'tags': [{'slug': 'alpha'}]}
+        response = self.client.patch(self._get_detail_url(policy), data, format='json', **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertIn('tags', response.data)
+        self.assertEqual([tag['slug'] for tag in response.data['tags']], ['alpha'])
+        self.assertEqual(list(policy.tags.values_list('slug', flat=True)), ['alpha'])
+
 
 class VLANTranslationRuleTestCase(APIViewTestCases.APIViewTestCase):
     model = VLANTranslationRule
@@ -1491,6 +1524,29 @@ class VLANTranslationRuleTestCase(APIViewTestCases.APIViewTestCase):
             'description': 'New description',
         }
 
+    def test_standard_fields_in_representation(self):
+        """The standard URL, tag, custom-field and change-tracking names appear in the representation."""
+        rule = VLANTranslationRule.objects.first()
+        self.add_permissions('ipam.view_vlantranslationrule')
+
+        response = self.client.get(self._get_detail_url(rule), **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        expected = {'display_url', 'tags', 'custom_fields', 'created', 'last_updated'}
+        self.assertEqual(expected - set(response.data), set())
+
+    def test_update_tags(self):
+        """Tags supplied on update are assigned and rendered in the response."""
+        rule = VLANTranslationRule.objects.first()
+        create_tags('Alpha')
+        self.add_permissions('ipam.change_vlantranslationrule', 'extras.view_tag')
+
+        data = {'tags': [{'slug': 'alpha'}]}
+        response = self.client.patch(self._get_detail_url(rule), data, format='json', **self.header)
+        self.assertHttpStatus(response, status.HTTP_200_OK)
+        self.assertIn('tags', response.data)
+        self.assertEqual([tag['slug'] for tag in response.data['tags']], ['alpha'])
+        self.assertEqual(list(rule.tags.values_list('slug', flat=True)), ['alpha'])
+
 
 class ServiceTemplateTestCase(APIViewTestCases.APIViewTestCase):
     model = ServiceTemplate