Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 1a9880e8 authored by Frederico SEQUEIRA's avatar Frederico SEQUEIRA
Browse files

:safety_vest: :white_check_mark: Add API tests and add API missing validations

parent 469a1529
No related branches found
No related tags found
1 merge request!27🦺 ✅ Add API tests and add API missing validations
Pipeline #258443 passed
......@@ -13,6 +13,7 @@ from django.contrib.contenttypes.models import ContentType
from .nested_serializers import *
from virtualization.choices import *
from netbox.api.serializers import NetBoxModelSerializer
from ..utils import validate_extra_config_values
#Netbox Data Serializer
......@@ -157,13 +158,62 @@ class VmAssignedExtraConfigSerializer(NetBoxModelSerializer):
id = serializers.IntegerField(read_only=True)
virtual_machine = NestedVirtualMachineSerializer(source='assigned_object', read_only=True)
assigned_object_id = serializers.IntegerField(write_only=True)
assigned_object_type = serializers.CharField(write_only=True)
display = serializers.CharField(source="__str__")
assigned_object_type = serializers.PrimaryKeyRelatedField(
queryset=ContentType.objects.all(),
write_only=True,
)
display = serializers.CharField(source="__str__",read_only=True)
class Meta:
model = VmAssignedExtraConfig
fields = '__all__'
def create(self, validated_data):
assigned_object_type = validated_data.pop("assigned_object_type")
validated_data["assigned_object_type"] = assigned_object_type
return super().create(validated_data)
def validate_extra_config_values(self, extra_config_values):
"""
Validates the `extra_config_values` against the associated provider config structure.
"""
provider_config = self.initial_data.get("provider_type_extra_config")
if provider_config:
try:
provider_instance = ProviderTypeExtraConfig.objects.get(id=provider_config)
structure_dict = provider_instance.extra_config_structure
# Validate using the first key in the structure dict
first_structure_name = next(iter(structure_dict), None)
if first_structure_name:
structure = structure_dict[first_structure_name][0]
if isinstance(structure, dict): # Ensure structure is in the expected format
is_valid, errors = validate_extra_config_values(structure, extra_config_values)
if not is_valid:
raise serializers.ValidationError(errors)
except ProviderTypeExtraConfig.DoesNotExist:
raise serializers.ValidationError("Invalid ProviderTypeExtraConfig selected.")
return extra_config_values
def validate(self, data):
"""
Perform complete object-level validation.
"""
if 'extra_config_values' in data:
# Validate extra_config_values
data['extra_config_values'] = self.validate_extra_config_values(data.get('extra_config_values', {}))
# Ensure a valid virtual machine assignment
if not self.partial and not data.get("assigned_object_id"):
raise serializers.ValidationError(
{"__all__": "Can't assign more than one Extra Config to the same Virtual Machine"}
)
return data
class VirtualMachineSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='plugins-api:netbox_sys_plugin-api:virtualmachine-detail')
status = ChoiceField(choices=VirtualMachineStatusChoices, required=False)
......
"""SYS Plugin VM Assigned Extra Config API Test Case Class"""
from users.models import ObjectPermission
from django.contrib.contenttypes.models import ContentType
from rest_framework import status
from virtualization.models import VirtualMachine, Cluster, ClusterType
from netbox_sys_plugin.models import VmAssignedExtraConfig, ProviderTypeExtraConfig
from ..base import BaseAPITestCase
class VmAssignedExtraConfigApiTestCase(BaseAPITestCase):
"""Test suite for VmAssignedExtraConfig API"""
model = VmAssignedExtraConfig
brief_fields = ["extra_config_name","extra_config_structure","extra_config_description", "assigned_object_id", "assigned_object_type"]
@classmethod
def setUpTestData(cls):
"""Set up test data for VmAssignedExtraConfig API"""
cls.ct_ct = ContentType.objects.get_for_model(ClusterType)
cls.vm_ct = ContentType.objects.get_for_model(VirtualMachine)
# Create a ClusterType
cls.cluster_type = ClusterType.objects.create(name="Test ClusterType", slug="CT")
# Create a ClusterType 2
cls.cluster_type2 = ClusterType.objects.create(name="Test ClusterType2", slug="CT2")
# Create a Cluster linked to the ClusterType
cls.cluster = Cluster.objects.create(name="Test Cluster", type=cls.cluster_type)
# Create a Cluster linked to the ClusterType 2
cls.cluster2 = Cluster.objects.create(name="Test Cluster", type=cls.cluster_type2)
# Create a VirtualMachine linked to the Cluster
cls.virtual_machine = VirtualMachine.objects.create(
name="Test VM",
status="active",
cluster=cls.cluster
)
# Create a VirtualMachine linked to the Cluster 2
cls.virtual_machine2 = VirtualMachine.objects.create(
name="Test VM 2",
status="active",
cluster=cls.cluster2
)
# Create a VirtualMachine linked to the Cluster
cls.virtual_machine3 = VirtualMachine.objects.create(
name="Test VM 3",
status="active",
cluster=cls.cluster2
)
# Create a VirtualMachine linked to the Cluster
cls.virtual_machine4 = VirtualMachine.objects.create(
name="Test VM 4",
status="active",
cluster=cls.cluster2
)
cls.virtual_machine5 = VirtualMachine.objects.create(
name="Test VM 5",
status="active",
cluster=cls.cluster2
)
cls.virtual_machine6 = VirtualMachine.objects.create(
name="Test VM 6",
status="active",
cluster=cls.cluster2
)
cls.virtual_machine7 = VirtualMachine.objects.create(
name="Test VM 7",
status="active",
cluster=cls.cluster2
)
# Create a Extra Config Structure linked to the Cluster Type
cls.structure1 = ProviderTypeExtraConfig.objects.create(
extra_config_name="TEST",
extra_config_structure={'test_extra': [{'id': {'required': 'true','type': 'String'}}]},
extra_config_description="Test Extra",
assigned_object=cls.cluster_type
)
cls.structure2 = ProviderTypeExtraConfig.objects.create(
extra_config_name="TEST2",
extra_config_structure={'test_extra2': [{'id': {'required': 'true','type': 'String'}}]},
extra_config_description="Test Extra2",
assigned_object=cls.cluster_type2
)
# Create Extra Configs entries linked to VMs
VmAssignedExtraConfig.objects.create(
extra_config_values={'id': 'id1'},
provider_type_extra_config_assignment_desc="Test Assign",
assigned_object=cls.virtual_machine,
provider_type_extra_config= cls.structure1
)
VmAssignedExtraConfig.objects.create(
extra_config_values={'id': 'id2'},
provider_type_extra_config_assignment_desc="Test Assign 2",
assigned_object=cls.virtual_machine2,
provider_type_extra_config= cls.structure2
)
# Data for valid creation
cls.valid_create_data = [
{
"extra_config_values":{'id': 'id2'},
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":cls.virtual_machine3.pk,
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":cls.structure2.pk
}
]
# Data for invalid creation
cls.invalid_create_data = [
{
"extra_config_values":{'desc': 'id2'}, #Wrong field
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":cls.virtual_machine4.pk,
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":cls.structure2.pk
},
{
"extra_config_values":{'id': True}, #Wrong type
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":cls.virtual_machine5.pk,
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":cls.structure2.pk
},
{
"extra_config_values":{'id': 'id2'},
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":cls.virtual_machine7.pk,
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":None #No Structure
},
{
"extra_config_values":{'id': 'id2'},
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":None, #No Assignment
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":cls.structure2.pk
},
]
# Data for checking unique key
cls.valid_check_unique_data = [
{
"extra_config_values":{'id': 'id2'},
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":cls.virtual_machine5.pk,
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":cls.structure2.pk
},
{
"extra_config_values":{'id': 'id2'},
"provider_type_extra_config_assignment_desc":"Test Assign 2",
"assigned_object_id":cls.virtual_machine5.pk,
"assigned_object_type": cls.vm_ct.pk,
"provider_type_extra_config":cls.structure2.pk
},
]
def test_create_valid_extra_config(self):
"""Test creating a valid extra config"""
obj_perm = ObjectPermission(
name="Create Extra Config Permission",
actions=["add", "view"],
)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
form_data = self.valid_create_data[0]
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(response.data["extra_config_values"], form_data["extra_config_values"])
self.assertEqual(response.data["provider_type_extra_config_assignment_desc"], form_data["provider_type_extra_config_assignment_desc"])
def test_extra_config_unique_key(self):
"""Test extra config unique key"""
obj_perm = ObjectPermission(
name="Invalid Extra Config Permission",
actions=["add", "view"],
)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
for form_data in self.valid_check_unique_data:
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('The fields assigned_object_id must make a unique set.',str(response.data))
def test_create_invalid_extra_config(self):
"""Test creating invalid extra config"""
obj_perm = ObjectPermission(
name="Invalid Extra Config Permission",
actions=["add", "view"],
)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
form_data = self.invalid_create_data[0]
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('Missing or empty required field: \'id\' with type string',str(response.data))
form_data = self.invalid_create_data[1]
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('Incorrect type for field \'id\': expected string, got bool',str(response.data))
form_data = self.invalid_create_data[2]
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('This field may not be null.',str(response.data))
form_data = self.invalid_create_data[3]
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('This field may not be null.',str(response.data))
def test_update_extra_config(self):
"""Test updating an existing extra config"""
extra_config = VmAssignedExtraConfig.objects.first()
obj_perm = ObjectPermission(
name="Update Extra Config Permission",
actions=["change", "view"],
)
print("EXTRA CONFIG --------",extra_config)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
update_data = {"provider_type_extra_config_assignment_desc": "Update Data"}
response = self.client.patch(self._get_detail_url(extra_config), update_data, format="json", **self.header)
print("response---------",response.data)
print("update_data------------",update_data)
print("self._get_detail_url(extra_config)---------",self._get_detail_url(extra_config))
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.data["provider_type_extra_config_assignment_desc"], update_data["provider_type_extra_config_assignment_desc"])
def test_get_all_extra_config(self):
"""Test fetching all extra config"""
obj_perm = ObjectPermission(
name="Create Extra Config Permission",
actions=["view"],
)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
response = self.client.get(self._get_list_url(), **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertGreaterEqual(len(response.data), 2)
def test_get_single_extra_config(self):
"""Test fetching a single extra config"""
obj_perm = ObjectPermission(
name="View Extra Config Permission",
actions=["view"],
)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
extra_config = VmAssignedExtraConfig.objects.first()
response = self.client.get(self._get_detail_url(extra_config), **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.data["extra_config_values"], extra_config.extra_config_values)
self.assertEqual(response.data["provider_type_extra_config_assignment_desc"], extra_config.provider_type_extra_config_assignment_desc)
def test_delete_extra_config(self):
"""Test deleting a extra config"""
extra_config = VmAssignedExtraConfig.objects.first()
obj_perm = ObjectPermission(
name="Delete Extra Config Permission",
actions=["delete"],
)
obj_perm.save()
obj_perm.users.add(self.user)
obj_perm.object_types.add(ContentType.objects.get_for_model(VmAssignedExtraConfig))
response = self.client.delete(self._get_detail_url(extra_config), **self.header)
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
self.assertFalse(VmAssignedExtraConfig.objects.filter(id=extra_config.id).exists())
......@@ -152,15 +152,12 @@ class VirtualMachinedomain_namesApiTestCase(BaseAPITestCase):
obj_perm.object_types.add(ContentType.objects.get_for_model(DomainNames))
form_data = self.invalid_create_data[0]
print("form_data",form_data)
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
print("RESPONSE API 1",response.data)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('This field may not be null.',str(response.data))
form_data = self.invalid_create_data[1]
response = self.client.post(self._get_list_url(), form_data, format="json", **self.header)
print("RESPONSE API 2",response.data)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertIn('This field may not be null.',str(response.data))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment