diff --git a/src/tests/test_compute_plans.py b/src/tests/test_compute_plans.py new file mode 100644 index 0000000..0317229 --- /dev/null +++ b/src/tests/test_compute_plans.py @@ -0,0 +1,199 @@ +from unittest.mock import Mock + +import pytest + +from servala.core.models import ( + ComputePlan, + ComputePlanAssignment, + ServiceInstance, +) + + +@pytest.mark.django_db +def test_create_compute_plan(): + plan = ComputePlan.objects.create( + name="Small", + description="Small resource plan", + memory_requests="512Mi", + memory_limits="1Gi", + cpu_requests="100m", + cpu_limits="500m", + is_active=True, + ) + + assert plan.name == "Small" + assert plan.memory_requests == "512Mi" + assert plan.memory_limits == "1Gi" + assert plan.cpu_requests == "100m" + assert plan.cpu_limits == "500m" + assert plan.is_active is True + + +@pytest.mark.django_db +def test_compute_plan_str(): + plan = ComputePlan.objects.create( + name="Medium", + memory_requests="1Gi", + memory_limits="2Gi", + cpu_requests="500m", + cpu_limits="1000m", + ) + assert str(plan) == "Medium" + + +@pytest.mark.django_db +def test_get_resource_summary(): + plan = ComputePlan.objects.create( + name="Large", + memory_requests="2Gi", + memory_limits="4Gi", + cpu_requests="1000m", + cpu_limits="2000m", + ) + summary = plan.get_resource_summary() + assert summary == "2000m vCPU, 4Gi RAM" + + +def test_apply_compute_plan_to_spec(): + compute_plan = Mock() + compute_plan.memory_requests = "512Mi" + compute_plan.memory_limits = "1Gi" + compute_plan.cpu_requests = "100m" + compute_plan.cpu_limits = "500m" + + compute_plan_assignment = Mock() + compute_plan_assignment.compute_plan = compute_plan + compute_plan_assignment.sla = "besteffort" + + spec_data = {"parameters": {}} + + result = ServiceInstance._apply_compute_plan_to_spec( + spec_data, compute_plan_assignment + ) + + assert result["parameters"]["size"]["memory"] == "1Gi" + assert result["parameters"]["size"]["cpu"] == "500m" + assert result["parameters"]["size"]["requests"]["memory"] == "512Mi" + assert result["parameters"]["size"]["requests"]["cpu"] == "100m" + + assert result["parameters"]["service"]["serviceLevel"] == "besteffort" + + +def test_apply_compute_plan_preserves_existing_spec(): + compute_plan = Mock() + compute_plan.memory_requests = "512Mi" + compute_plan.memory_limits = "1Gi" + compute_plan.cpu_requests = "100m" + compute_plan.cpu_limits = "500m" + + compute_plan_assignment = Mock() + compute_plan_assignment.compute_plan = compute_plan + compute_plan_assignment.sla = "guaranteed" + + spec_data = { + "parameters": { + "custom_field": "custom_value", + "service": {"existingField": "value"}, + } + } + + result = ServiceInstance._apply_compute_plan_to_spec( + spec_data, compute_plan_assignment + ) + + assert result["parameters"]["custom_field"] == "custom_value" + assert result["parameters"]["service"]["existingField"] == "value" + + assert result["parameters"]["size"]["memory"] == "1Gi" + assert result["parameters"]["service"]["serviceLevel"] == "guaranteed" + + +def test_apply_compute_plan_with_none(): + spec_data = {"parameters": {}} + result = ServiceInstance._apply_compute_plan_to_spec(spec_data, None) + + assert result == spec_data + + +def test_build_billing_annotations_complete(): + compute_plan_assignment = Mock() + compute_plan_assignment.odoo_product_id = "test-product-123" + compute_plan_assignment.odoo_unit_id = "test-unit-hour" + + control_plane = Mock() + control_plane.storage_plan_odoo_product_id = "storage-product-id" + control_plane.storage_plan_odoo_unit_id = "storage-unit-id" + + annotations = ServiceInstance._build_billing_annotations( + compute_plan_assignment, control_plane + ) + + assert annotations["servala.com/erp_product_id_resource"] == "test-product-123" + assert annotations["servala.com/erp_unit_id_resource"] == "test-unit-hour" + + assert annotations["servala.com/erp_product_id_storage"] == "storage-product-id" + assert annotations["servala.com/erp_unit_id_storage"] == "storage-unit-id" + + +def test_build_billing_annotations_no_compute_plan(): + control_plane = Mock() + control_plane.storage_plan_odoo_product_id = "storage-product-id" + control_plane.storage_plan_odoo_unit_id = "storage-unit-id" + + annotations = ServiceInstance._build_billing_annotations(None, control_plane) + + assert "servala.com/erp_product_id_resource" not in annotations + assert "servala.com/erp_unit_id_resource" not in annotations + assert annotations["servala.com/erp_product_id_storage"] == "storage-product-id" + assert annotations["servala.com/erp_unit_id_storage"] == "storage-unit-id" + + +def test_build_billing_annotations_no_storage_plan(): + compute_plan_assignment = Mock() + compute_plan_assignment.odoo_product_id = "product-id" + compute_plan_assignment.odoo_unit_id = "unit-id" + + control_plane = Mock() + control_plane.storage_plan_odoo_product_id = None + control_plane.storage_plan_odoo_unit_id = None + + annotations = ServiceInstance._build_billing_annotations( + compute_plan_assignment, control_plane + ) + + assert annotations["servala.com/erp_product_id_resource"] == "product-id" + assert annotations["servala.com/erp_unit_id_resource"] == "unit-id" + assert "servala.com/erp_product_id_storage" not in annotations + assert "servala.com/erp_unit_id_storage" not in annotations + + +def test_build_billing_annotations_empty(): + control_plane = Mock() + control_plane.storage_plan_odoo_product_id = None + control_plane.storage_plan_odoo_unit_id = None + + annotations = ServiceInstance._build_billing_annotations(None, control_plane) + + assert annotations == {} + + +@pytest.mark.django_db +def test_hour_unit(): + choices = dict(ComputePlanAssignment.BILLING_UNIT_CHOICES) + assert "hour" in choices + assert str(choices["hour"]) == "Hour" + + +@pytest.mark.django_db +def test_all_billing_units(): + choices = dict(ComputePlanAssignment.BILLING_UNIT_CHOICES) + + assert "hour" in choices + assert "day" in choices + assert "month" in choices + assert "year" in choices + + assert str(choices["hour"]) == "Hour" + assert str(choices["day"]) == "Day" + assert "Month" in str(choices["month"]) + assert str(choices["year"]) == "Year"