diff --git a/netbox_sys_plugin/api/serializers.py b/netbox_sys_plugin/api/serializers.py index bf20a580be83136fc0e58260ce49097ce15e0ea2..7ab5f57a5704620c71c40ea10b95acf7cd2bdcd6 100644 --- a/netbox_sys_plugin/api/serializers.py +++ b/netbox_sys_plugin/api/serializers.py @@ -92,12 +92,21 @@ class VirtualMachineTypeSerializer(NetBoxModelSerializer): id = serializers.IntegerField(read_only=True) cluster_type = ClusterTypeSerializer(source='assigned_object', read_only=True) assigned_object_id = serializers.IntegerField(write_only=True) - assigned_object_type = serializers.CharField(write_only=True) + assigned_object_type = serializers.PrimaryKeyRelatedField( + queryset=ContentType.objects.all(), + write_only=True, + ) + display = serializers.CharField(source="__str__",read_only=True) class Meta: model = VirtualMachineType 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) + class VmAssignedVirtualMachineTypeSerializer(NetBoxModelSerializer): id = serializers.IntegerField(read_only=True) virtual_machine = NestedVirtualMachineSerializer(source='assigned_object', read_only=True) diff --git a/netbox_sys_plugin/tests/vm_machine_type/__init__.py b/netbox_sys_plugin/tests/vm_machine_type/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/netbox_sys_plugin/tests/vm_machine_type/test_vm_machine_type_api.py b/netbox_sys_plugin/tests/vm_machine_type/test_vm_machine_type_api.py new file mode 100644 index 0000000000000000000000000000000000000000..81b1e8136aed12aa7cf98d79e9426d95b0e09e15 --- /dev/null +++ b/netbox_sys_plugin/tests/vm_machine_type/test_vm_machine_type_api.py @@ -0,0 +1,184 @@ +"""SYS Plugin VM Machine Type 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 ClusterType +from netbox_sys_plugin.models import VirtualMachineType +from ..base import BaseAPITestCase + +class VmMachineTypeApiTestCase(BaseAPITestCase): + """Test suite for VmMachineType API""" + model = VirtualMachineType + brief_fields = ["virtual_machine_type_name","virtual_machine_type_desc","assigned_object_id", "assigned_object_type"] + + + @classmethod + def setUpTestData(cls): + + """Set up test data for VirtualMachineType API""" + cls.cluster_type_ct = ContentType.objects.get_for_model(ClusterType) + + # Create a ClusterType + cls.cluster_type = ClusterType.objects.create(name="Test ClusterType1", slug="ClusterType1") + + + # Create a ClusterType2 + cls.cluster_type2 = ClusterType.objects.create(name="Test ClusterType2", slug="ClusterType2") + + # Create vm machine type entries linked to the ClusterType + VirtualMachineType.objects.create( + virtual_machine_type_name='vm_type_name1', + virtual_machine_type_desc='vm_type_desc_1', + assigned_object=cls.cluster_type + ) + VirtualMachineType.objects.create( + virtual_machine_type_name='vm_type_name2', + virtual_machine_type_desc='vm_type_desc_2', + assigned_object=cls.cluster_type2 + ) + + # Data for valid creation + cls.valid_create_data = [ + { + "virtual_machine_type_name": "vm_type_name3", + "virtual_machine_type_desc":"vm_type_desc_3", + "assigned_object_type": cls.cluster_type_ct.pk, + "assigned_object_id": cls.cluster_type.id, + } + ] + + # Data for invalid creation + cls.invalid_create_data = [ + { + "virtual_machine_type_name": "vm_type_name4", + "virtual_machine_type_desc":"vm_type_desc_4", + "assigned_object_type": cls.cluster_type_ct.pk, + "assigned_object_id": None, # Missing ClusterType + }, + ] + + # Data for checking unique key + cls.valid_check_unique_data = [ + { + "virtual_machine_type_name": "vm_type_name4", # Same name + "virtual_machine_type_desc":"vm_type_desc_different", + "assigned_object_type": cls.cluster_type_ct.pk, + "assigned_object_id": cls.cluster_type2.id, # Same ClusterType + }, + { + "virtual_machine_type_name": "vm_type_name4", # Same name + "virtual_machine_type_desc":"vm_type_desc_4", + "assigned_object_type": cls.cluster_type_ct.pk, + "assigned_object_id": cls.cluster_type2.id, # Same ClusterType + } + ] + + def test_create_valid_machine_type(self): + """Test creating a valid machine type""" + obj_perm = ObjectPermission( + name="Create Machine Type Permission", + actions=["add", "view"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + 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["virtual_machine_type_name"], form_data["virtual_machine_type_name"]) + self.assertEqual(response.data["virtual_machine_type_desc"], form_data["virtual_machine_type_desc"]) + + + def test_machine_type_unique_key(self): + """Test machine type unique key""" + obj_perm = ObjectPermission( + name="Invalid Machine Type Permission", + actions=["add", "view"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + 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) + + def test_create_invalid_machine_type(self): + """Test creating invalid machine type""" + obj_perm = ObjectPermission( + name="Invalid Machine Type Permission", + actions=["add", "view"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + for form_data in self.invalid_create_data: + response = self.client.post(self._get_list_url(), form_data, format="json", **self.header) + self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) + + def test_update_machine_type(self): + """Test updating an existing machine type""" + machine_type = VirtualMachineType.objects.first() + obj_perm = ObjectPermission( + name="Update Machine Type Permission", + actions=["change", "view"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + update_data = {"virtual_machine_type_name": "vm_type_name_updated", + "virtual_machine_type_desc":"vm_type_desc_updated"} + + response = self.client.patch(self._get_detail_url(machine_type), update_data, format="json", **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + self.assertEqual(response.data["virtual_machine_type_name"], update_data["virtual_machine_type_name"]) + self.assertEqual(response.data["virtual_machine_type_desc"], update_data["virtual_machine_type_desc"]) + + def test_delete_machine_type(self): + """Test deleting a machine type""" + machine_type = VirtualMachineType.objects.first() + obj_perm = ObjectPermission( + name="Delete Machine Type Permission", + actions=["delete"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + response = self.client.delete(self._get_detail_url(machine_type), **self.header) + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) + self.assertFalse(VirtualMachineType.objects.filter(id=machine_type.id).exists()) + + def test_get_all_machine_type(self): + """Test fetching all machine types""" + obj_perm = ObjectPermission( + name="View Machine Type Permission", + actions=["view"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + 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_machine_type(self): + """Test fetching a single machine type""" + obj_perm = ObjectPermission( + name="View Machine Type Permission", + actions=["view"], + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(VirtualMachineType)) + + machine_type = VirtualMachineType.objects.first() + response = self.client.get(self._get_detail_url(machine_type), **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + self.assertEqual(response.data["virtual_machine_type_name"], machine_type.virtual_machine_type_name) + self.assertEqual(response.data["virtual_machine_type_desc"], machine_type.virtual_machine_type_desc) diff --git a/netbox_sys_plugin/tests/vm_machine_type/test_vm_machine_type_view.py b/netbox_sys_plugin/tests/vm_machine_type/test_vm_machine_type_view.py new file mode 100644 index 0000000000000000000000000000000000000000..aa991c49623c85bc6ef45fa56b6891feed391d4f --- /dev/null +++ b/netbox_sys_plugin/tests/vm_machine_type/test_vm_machine_type_view.py @@ -0,0 +1,95 @@ +"""VM Maintenance Views Test Case Class""" + +from django.contrib.contenttypes.models import ContentType +from users.models import ObjectPermission +from virtualization.models import ClusterType +from netbox_sys_plugin.models import VirtualMachineType +from netbox_sys_plugin.forms import VmTypeForm +from .. base import BaseModelViewTestCase + + + +class VmMachineTypeFormTestCase( + BaseModelViewTestCase, +): + """VM Machine Type Test Case Class""" + + model = VirtualMachineType + form = VmTypeForm + + + @classmethod + # pylint: disable=invalid-name + def setUpTestData(cls): + """ SetUp Test Data """ + #Create Cluster type + cluster_type_content_type = ContentType.objects.get_for_model(ClusterType) + cluster_type1 = ClusterType.objects.create(name="Test ClusterType1", slug="ClusterType1") + cluster_type2 = ClusterType.objects.create(name="Test ClusterType2", slug="ClusterType2") + + vmMachineType1 = VirtualMachineType.objects.create(virtual_machine_type_name='vm_type_name1', + virtual_machine_type_desc='vm_type_desc_1', + assigned_object_type=cluster_type_content_type, + assigned_object_id=cluster_type1.pk) + vmMachineType2 = VirtualMachineType.objects.create(virtual_machine_type_name='vm_type_name2', + virtual_machine_type_desc='vm_type_desc_2', + assigned_object_type=cluster_type_content_type, + assigned_object_id=cluster_type2.pk) + + cls.form_data = { + "virtual_machine_type_name": "vm_type_name3", + "cluster_type": cluster_type2.pk, + "virtual_machine_type_desc":"vm_type_desc_3" + + } + cls.csv_data = ( + "virtual_machine_type_name","virtual_machine_type_desc","assigned_object_type","assigned_object_id\n" + "vm_type_name4,vm_type_desc_4," + str(cluster_type_content_type.pk) + ", " + str(cluster_type1.pk) + "\n" + ) + + cls.csv_update_data = ( + "id,virtual_machine_type_name","virtual_machine_type_desc","assigned_object_type","assigned_object_id\n" + f"{vmMachineType1.pk},vm_type_new_name1,vm_type_desc_new,{cluster_type_content_type.pk},{cluster_type1.pk}\n" + f"{vmMachineType2.pk},vm_type_new_name2,vm_type_desc_new2,{cluster_type_content_type.pk},{cluster_type2.pk}\n" + ) + + def test_create_already_existing_vm_type(self): + """Test the creation of 2 vm types with same name and cluster type""" + + #Create Cluster type for testing + # pylint: disable=W0201 + cluster_type_content_type = ContentType.objects.get_for_model(ClusterType) + cluster_type = ClusterType.objects.create(name="Test ClusterType3", slug="ClusterType3") + + # pylint: disable=W0201 + self.vmMachineType1 = VirtualMachineType.objects.create( + virtual_machine_type_name='vm_type_name', + virtual_machine_type_desc='vm_type_desc', + assigned_object_type=cluster_type_content_type, + assigned_object_id=cluster_type.pk) + + form = VmTypeForm(data= { + "virtual_machine_type_name": "vm_type_name", + "cluster_type": cluster_type.pk, + "virtual_machine_type_desc":"vm_type_desc" + }) + + self.assertFalse(form.is_valid()) + # Setup object permissions for the test user + obj_perm = ObjectPermission( + name='Test permission', + actions=['add', 'change'] + ) + obj_perm.save() + obj_perm.users.add(self.user) # pylint: disable=no-member + obj_perm.object_types.add(ContentType.objects.get_for_model(self.model)) # pylint: disable=no-member + + self.assertIn( + "A Type with this name and cluster type already exists", + form.errors.get("__all__",[]) + ) + + def tearDown(self) -> None:# pylint: disable=invalid-name + """Method called immediately after the test method has been called and the result recorded.""" + VirtualMachineType.objects.all().delete() + super().tearDown()