Repository: getmoto/moto

Issue:
RDS's describe_db_clusters Filter argument not supported
RDS's `describe_db_clusters` takes a `Filters` argument to reduce the number of results server side. This argument is silently ignored by moto and all results are returned instead.

Sample test case:
```python
import boto3
import pytest
import sure

from moto import mock_rds

@mock_rds
def test_filter():
    client = boto3.client("rds", region_name="eu-north-1")

    client.create_db_cluster(
            DBClusterIdentifier="id",
            Engine="aurora-mysql",
            MasterUsername="root",
            MasterUserPassword="hunter21",
        )

    resp = client.describe_db_clusters(Filters = [{
            "Name": "engine",
            "Values": ["aurora-postgresql"],
        }])

    resp.should.have.key("DBClusters").should.have.length_of(0)

```

Using:
* moto: 4.1.6
* boto3: 1.26.99
* botocore: 1.29.99

Thank you


Discussion:

Resolving patch:
diff --git a/moto/rds/models.py b/moto/rds/models.py
--- a/moto/rds/models.py
+++ b/moto/rds/models.py
@@ -46,6 +46,13 @@
 
 
 class Cluster:
+    SUPPORTED_FILTERS = {
+        "db-cluster-id": FilterDef(
+            ["db_cluster_arn", "db_cluster_identifier"], "DB Cluster Identifiers"
+        ),
+        "engine": FilterDef(["engine"], "Engine Names"),
+    }
+
     def __init__(self, **kwargs):
         self.db_name = kwargs.get("db_name")
         self.db_cluster_identifier = kwargs.get("db_cluster_identifier")
@@ -1948,17 +1955,19 @@ def delete_db_cluster_snapshot(self, db_snapshot_identifier):
 
         return self.cluster_snapshots.pop(db_snapshot_identifier)
 
-    def describe_db_clusters(self, cluster_identifier):
+    def describe_db_clusters(self, cluster_identifier=None, filters=None):
+        clusters = self.clusters
+        clusters_neptune = self.neptune.clusters
         if cluster_identifier:
-            # ARN to identifier
-            # arn:aws:rds:eu-north-1:123456789012:cluster:cluster --> cluster-id
-            cluster_identifier = cluster_identifier.split(":")[-1]
-            if cluster_identifier in self.clusters:
-                return [self.clusters[cluster_identifier]]
-            if cluster_identifier in self.neptune.clusters:
-                return [self.neptune.clusters[cluster_identifier]]
+            filters = merge_filters(filters, {"db-cluster-id": [cluster_identifier]})
+        if filters:
+            clusters = self._filter_resources(clusters, filters, Cluster)
+            clusters_neptune = self._filter_resources(
+                clusters_neptune, filters, Cluster
+            )
+        if cluster_identifier and not (clusters or clusters_neptune):
             raise DBClusterNotFoundError(cluster_identifier)
-        return list(self.clusters.values()) + list(self.neptune.clusters.values())
+        return list(clusters.values()) + list(clusters_neptune.values())
 
     def describe_db_cluster_snapshots(
         self, db_cluster_identifier, db_snapshot_identifier, filters=None
diff --git a/moto/rds/responses.py b/moto/rds/responses.py
--- a/moto/rds/responses.py
+++ b/moto/rds/responses.py
@@ -583,7 +583,11 @@ def modify_db_cluster(self):
 
     def describe_db_clusters(self):
         _id = self._get_param("DBClusterIdentifier")
-        clusters = self.backend.describe_db_clusters(cluster_identifier=_id)
+        filters = self._get_multi_param("Filters.Filter.")
+        filters = {f["Name"]: f["Values"] for f in filters}
+        clusters = self.backend.describe_db_clusters(
+            cluster_identifier=_id, filters=filters
+        )
         template = self.response_template(DESCRIBE_CLUSTERS_TEMPLATE)
         return template.render(clusters=clusters)
 


Test patch:
diff --git a/tests/test_neptune/test_clusters.py b/tests/test_neptune/test_clusters.py
--- a/tests/test_neptune/test_clusters.py
+++ b/tests/test_neptune/test_clusters.py
@@ -64,7 +64,9 @@ def test_describe_db_clusters():
 
     client.create_db_cluster(DBClusterIdentifier="cluster-id", Engine="neptune")
 
-    clusters = client.describe_db_clusters()["DBClusters"]
+    clusters = client.describe_db_clusters(DBClusterIdentifier="cluster-id")[
+        "DBClusters"
+    ]
     clusters.should.have.length_of(1)
     clusters[0]["DBClusterIdentifier"].should.equal("cluster-id")
     clusters[0].should.have.key("Engine").equals("neptune")
diff --git a/tests/test_rds/test_rds_clusters.py b/tests/test_rds/test_rds_clusters.py
--- a/tests/test_rds/test_rds_clusters.py
+++ b/tests/test_rds/test_rds_clusters.py
@@ -811,3 +811,37 @@ def test_create_db_cluster_with_enable_http_endpoint_invalid():
     )
     cluster = resp["DBCluster"]
     cluster.should.have.key("HttpEndpointEnabled").equal(False)
+
+
+@mock_rds
+def test_describe_db_clusters_filter_by_engine():
+    client = boto3.client("rds", region_name="eu-north-1")
+
+    client.create_db_cluster(
+        DBClusterIdentifier="id1",
+        Engine="aurora-mysql",
+        MasterUsername="root",
+        MasterUserPassword="hunter21",
+    )
+
+    client.create_db_cluster(
+        DBClusterIdentifier="id2",
+        Engine="aurora-postgresql",
+        MasterUsername="root",
+        MasterUserPassword="hunter21",
+    )
+
+    resp = client.describe_db_clusters(
+        Filters=[
+            {
+                "Name": "engine",
+                "Values": ["aurora-postgresql"],
+            }
+        ]
+    )
+
+    clusters = resp["DBClusters"]
+    assert len(clusters) == 1
+    cluster = clusters[0]
+    assert cluster["DBClusterIdentifier"] == "id2"
+    assert cluster["Engine"] == "aurora-postgresql"