Repository: cloudtools/troposphere (python)

Issue:
AllocatedStorage can't be a Ref
If I try to use a Parameter for setting the AllocatedStorage of an RDS database I get the following error:
```
  File "/home/cup/.local/share/virtualenvs/system-oD26KLrH/lib/python3.11/site-packages/troposphere/validators/rds.py", line 402, in validate_dbinstance
    and int(allocated_storage) < 400
        ^^^^^^^^^^^^^^^^^^^^^^
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'Ref'
```

Version: 4.4.1

Pull request:
Fix RDS validator for gp3 iops/allocated_storage ratio check
Fixes #2176
The [test case](https://github.com/cloudtools/troposphere/issues/2176#issuecomment-1940482962) in the Issue was [falling through](https://github.com/cloudtools/troposphere/issues/2176#issuecomment-1938252769) to the body of the if statement which was an indication the test was incorrect.

@tnielsen2 @JohnPreston @uldall looking for a quick code review if you have time to check it

Patch:
diff --git a/troposphere/validators/rds.py b/troposphere/validators/rds.py
index 62be1e3e..7dcffafe 100644
--- a/troposphere/validators/rds.py
+++ b/troposphere/validators/rds.py
@@ -493,18 +493,17 @@ def validate_dbinstance(self) -> None:
             )
 
         # Validate storage performance constraints for iops ratios
-        if not (
+        if (
             not isinstance(allocated_storage, AWSHelperFn)
             and not isinstance(iops, AWSHelperFn)
-            and (
-                min_iops_to_allocated_storage_ratio
-                < iops / int(allocated_storage)
-                < max_iops_to_allocated_storage_ratio
-            )
+        ) and not (
+            min_iops_to_allocated_storage_ratio
+            < iops / int(allocated_storage)
+            < max_iops_to_allocated_storage_ratio
         ):
             raise ValueError(
                 "Invalid ratio of Iops to AllocatedStorage. Minimum ratio for "
                 f"engine {engine} is {min_iops_to_allocated_storage_ratio} "
-                f"and maximum ratio is {max_iops_to_allocated_storage_ratio}"
-                f"current value is {iops / int(allocated_storage)}"
+                f"and maximum ratio is {max_iops_to_allocated_storage_ratio}. "
+                f"Current value is {iops / int(allocated_storage)}"
             )


Test patch:
diff --git a/tests/test_rds.py b/tests/test_rds.py
index 43276f5a..d42aa07d 100644
--- a/tests/test_rds.py
+++ b/tests/test_rds.py
@@ -237,6 +237,41 @@ class TestRDS(unittest.TestCase):
         )
         i.validate()
 
+    def test_gp3_storage_performance(self):
+        # Using a Ref() will disable the gp3 ratio check
+        db_az = "us-east-1"
+        allocated_storage = Parameter("allocatedstorage", Type="int")
+        i = rds.DBInstance(
+            "Database1",
+            Engine="postgres",
+            EngineVersion="15.3",
+            StorageType="gp3",
+            AllocatedStorage=Ref(allocated_storage),
+            Iops=12000,
+            StorageThroughput=500,
+            MasterUsername="test",
+            MasterUserPassword="test",
+        )
+        i.validate()
+
+        # Specify invalid ratio for iops/allocated_storage for gp3
+        i = rds.DBInstance(
+            "Database2",
+            Engine="postgres",
+            EngineVersion="15.3",
+            StorageType="gp3",
+            AllocatedStorage="400",
+            Iops=200400,
+            StorageThroughput=500,
+            MasterUsername="test",
+            MasterUserPassword="test",
+        )
+        with self.assertRaisesRegex(
+            ValueError,
+            r"Invalid ratio of Iops to AllocatedStorage",
+        ):
+            i.to_dict()
+
     def test_io1_storage_type_and_iops(self):
         i = rds.DBInstance(
             "NoAZAndMultiAZ",