RDS: add cluster engine validation when creating a rds cluster (#7001)
This commit is contained in:
parent
e43619ae07
commit
3ca46c3c24
@ -49,6 +49,7 @@ from .utils import (
|
|||||||
merge_filters,
|
merge_filters,
|
||||||
validate_filters,
|
validate_filters,
|
||||||
valid_preferred_maintenance_window,
|
valid_preferred_maintenance_window,
|
||||||
|
ClusterEngine,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -129,6 +130,17 @@ class Cluster:
|
|||||||
self.db_cluster_instance_class = kwargs.get("db_cluster_instance_class")
|
self.db_cluster_instance_class = kwargs.get("db_cluster_instance_class")
|
||||||
self.deletion_protection = kwargs.get("deletion_protection")
|
self.deletion_protection = kwargs.get("deletion_protection")
|
||||||
self.engine = kwargs.get("engine")
|
self.engine = kwargs.get("engine")
|
||||||
|
if self.engine not in ClusterEngine.list_cluster_engines():
|
||||||
|
raise InvalidParameterValue(
|
||||||
|
(
|
||||||
|
"Engine '{engine}' is not supported "
|
||||||
|
"to satisfy constraint: Member must satisfy enum value set: "
|
||||||
|
"{valid_engines}"
|
||||||
|
).format(
|
||||||
|
engine=self.engine,
|
||||||
|
valid_engines=ClusterEngine.list_cluster_engines(),
|
||||||
|
)
|
||||||
|
)
|
||||||
self.engine_version = kwargs.get("engine_version") or Cluster.default_engine_version(self.engine) # type: ignore
|
self.engine_version = kwargs.get("engine_version") or Cluster.default_engine_version(self.engine) # type: ignore
|
||||||
self.engine_mode = kwargs.get("engine_mode") or "provisioned"
|
self.engine_mode = kwargs.get("engine_mode") or "provisioned"
|
||||||
self.iops = kwargs.get("iops")
|
self.iops = kwargs.get("iops")
|
||||||
@ -1591,7 +1603,10 @@ class RDSBackend(BaseBackend):
|
|||||||
if cluster_id is not None:
|
if cluster_id is not None:
|
||||||
cluster = self.clusters.get(cluster_id)
|
cluster = self.clusters.get(cluster_id)
|
||||||
if cluster is not None:
|
if cluster is not None:
|
||||||
if cluster.engine == "aurora" and cluster.engine_mode == "serverless":
|
if (
|
||||||
|
cluster.engine in ClusterEngine.serverless_engines()
|
||||||
|
and cluster.engine_mode == "serverless"
|
||||||
|
):
|
||||||
raise InvalidParameterValue(
|
raise InvalidParameterValue(
|
||||||
"Instances cannot be added to Aurora Serverless clusters."
|
"Instances cannot be added to Aurora Serverless clusters."
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import copy
|
import copy
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from typing import Any, Dict, Tuple, Optional
|
from typing import Any, Dict, Tuple, Optional, List
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
from botocore.utils import merge_dicts
|
from botocore.utils import merge_dicts
|
||||||
|
|
||||||
@ -22,6 +23,21 @@ FilterDef = namedtuple(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ClusterEngine(str, Enum):
|
||||||
|
AURORA_POSTGRESQL = "aurora-postgresql"
|
||||||
|
AURORA_MYSQL = "aurora-mysql"
|
||||||
|
RDS_POSTGRESQL = "postgres"
|
||||||
|
RDS_MYSQL = "mysql"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_cluster_engines(self) -> List[str]:
|
||||||
|
return sorted([item.value for item in ClusterEngine])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def serverless_engines(self) -> List[str]:
|
||||||
|
return [ClusterEngine.AURORA_MYSQL, ClusterEngine.AURORA_POSTGRESQL]
|
||||||
|
|
||||||
|
|
||||||
def get_object_value(obj: Any, attr: str) -> Any:
|
def get_object_value(obj: Any, attr: str) -> Any:
|
||||||
"""Retrieves an arbitrary attribute value from an object.
|
"""Retrieves an arbitrary attribute value from an object.
|
||||||
|
|
||||||
|
@ -31,12 +31,29 @@ def test_describe_db_cluster_fails_for_non_existent_cluster():
|
|||||||
assert err["Message"] == "DBCluster cluster-id not found."
|
assert err["Message"] == "DBCluster cluster-id not found."
|
||||||
|
|
||||||
|
|
||||||
|
@mock_rds
|
||||||
|
def test_create_db_cluster_invalid_engine():
|
||||||
|
client = boto3.client("rds", region_name=RDS_REGION)
|
||||||
|
|
||||||
|
with pytest.raises(ClientError) as ex:
|
||||||
|
client.create_db_cluster(
|
||||||
|
DBClusterIdentifier="cluster-id", Engine="aurora-postgresql"
|
||||||
|
)
|
||||||
|
err = ex.value.response["Error"]
|
||||||
|
assert err["Code"] == "InvalidParameterValue"
|
||||||
|
assert err["Message"] == (
|
||||||
|
"The parameter MasterUsername must be provided and must not be blank."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@mock_rds
|
@mock_rds
|
||||||
def test_create_db_cluster_needs_master_username():
|
def test_create_db_cluster_needs_master_username():
|
||||||
client = boto3.client("rds", region_name=RDS_REGION)
|
client = boto3.client("rds", region_name=RDS_REGION)
|
||||||
|
|
||||||
with pytest.raises(ClientError) as ex:
|
with pytest.raises(ClientError) as ex:
|
||||||
client.create_db_cluster(DBClusterIdentifier="cluster-id", Engine="aurora")
|
client.create_db_cluster(
|
||||||
|
DBClusterIdentifier="cluster-id", Engine="aurora-postgresql"
|
||||||
|
)
|
||||||
err = ex.value.response["Error"]
|
err = ex.value.response["Error"]
|
||||||
assert err["Code"] == "InvalidParameterValue"
|
assert err["Code"] == "InvalidParameterValue"
|
||||||
assert err["Message"] == (
|
assert err["Message"] == (
|
||||||
@ -50,7 +67,9 @@ def test_create_db_cluster_needs_master_user_password():
|
|||||||
|
|
||||||
with pytest.raises(ClientError) as ex:
|
with pytest.raises(ClientError) as ex:
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id", Engine="aurora", MasterUsername="root"
|
DBClusterIdentifier="cluster-id",
|
||||||
|
Engine="aurora-postgresql",
|
||||||
|
MasterUsername="root",
|
||||||
)
|
)
|
||||||
err = ex.value.response["Error"]
|
err = ex.value.response["Error"]
|
||||||
assert err["Code"] == "InvalidParameterValue"
|
assert err["Code"] == "InvalidParameterValue"
|
||||||
@ -66,7 +85,7 @@ def test_create_db_cluster_needs_long_master_user_password():
|
|||||||
with pytest.raises(ClientError) as ex:
|
with pytest.raises(ClientError) as ex:
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2",
|
MasterUserPassword="hunter2",
|
||||||
)
|
)
|
||||||
@ -84,7 +103,7 @@ def test_modify_db_cluster_needs_long_master_user_password():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter21",
|
MasterUserPassword="hunter21",
|
||||||
)
|
)
|
||||||
@ -110,7 +129,7 @@ def test_modify_db_cluster_new_cluster_identifier():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier=old_id,
|
DBClusterIdentifier=old_id,
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter21",
|
MasterUserPassword="hunter21",
|
||||||
)
|
)
|
||||||
@ -137,7 +156,7 @@ def test_create_db_cluster__verify_default_properties():
|
|||||||
|
|
||||||
resp = client.create_db_cluster(
|
resp = client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-mysql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -169,8 +188,8 @@ def test_create_db_cluster__verify_default_properties():
|
|||||||
)
|
)
|
||||||
assert cluster["ReaderEndpoint"] == expected_readonly
|
assert cluster["ReaderEndpoint"] == expected_readonly
|
||||||
assert cluster["MultiAZ"] is False
|
assert cluster["MultiAZ"] is False
|
||||||
assert cluster["Engine"] == "aurora"
|
assert cluster["Engine"] == "aurora-mysql"
|
||||||
assert cluster["EngineVersion"] == "5.6.mysql_aurora.1.22.5"
|
assert cluster["EngineVersion"] == "5.7.mysql_aurora.2.07.2"
|
||||||
assert cluster["Port"] == 3306
|
assert cluster["Port"] == 3306
|
||||||
assert cluster["MasterUsername"] == "root"
|
assert cluster["MasterUsername"] == "root"
|
||||||
assert cluster["PreferredBackupWindow"] == "01:37-02:07"
|
assert cluster["PreferredBackupWindow"] == "01:37-02:07"
|
||||||
@ -206,7 +225,7 @@ def test_create_db_cluster_additional_parameters():
|
|||||||
AvailabilityZones=["eu-north-1b"],
|
AvailabilityZones=["eu-north-1b"],
|
||||||
DatabaseName="users",
|
DatabaseName="users",
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
EngineVersion="8.0.mysql_aurora.3.01.0",
|
EngineVersion="8.0.mysql_aurora.3.01.0",
|
||||||
EngineMode="serverless",
|
EngineMode="serverless",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
@ -232,7 +251,7 @@ def test_create_db_cluster_additional_parameters():
|
|||||||
|
|
||||||
assert cluster["AvailabilityZones"] == ["eu-north-1b"]
|
assert cluster["AvailabilityZones"] == ["eu-north-1b"]
|
||||||
assert cluster["DatabaseName"] == "users"
|
assert cluster["DatabaseName"] == "users"
|
||||||
assert cluster["Engine"] == "aurora"
|
assert cluster["Engine"] == "aurora-postgresql"
|
||||||
assert cluster["EngineVersion"] == "8.0.mysql_aurora.3.01.0"
|
assert cluster["EngineVersion"] == "8.0.mysql_aurora.3.01.0"
|
||||||
assert cluster["EngineMode"] == "serverless"
|
assert cluster["EngineMode"] == "serverless"
|
||||||
assert cluster["Port"] == 1234
|
assert cluster["Port"] == 1234
|
||||||
@ -259,14 +278,14 @@ def test_describe_db_cluster_after_creation():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id1",
|
DBClusterIdentifier="cluster-id1",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
|
|
||||||
cluster_arn = client.create_db_cluster(
|
cluster_arn = client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id2",
|
DBClusterIdentifier="cluster-id2",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)["DBCluster"]["DBClusterArn"]
|
)["DBCluster"]["DBClusterArn"]
|
||||||
@ -292,7 +311,7 @@ def test_delete_db_cluster():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -308,7 +327,7 @@ def test_delete_db_cluster_do_snapshot():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -329,7 +348,7 @@ def test_delete_db_cluster_that_is_protected():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
DeletionProtection=True,
|
DeletionProtection=True,
|
||||||
@ -369,7 +388,7 @@ def test_start_db_cluster_after_stopping():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -386,7 +405,7 @@ def test_start_db_cluster_without_stopping():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -404,7 +423,7 @@ def test_stop_db_cluster():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -425,7 +444,7 @@ def test_stop_db_cluster_already_stopped():
|
|||||||
|
|
||||||
client.create_db_cluster(
|
client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
)
|
)
|
||||||
@ -838,7 +857,7 @@ def test_create_db_cluster_with_enable_http_endpoint_invalid():
|
|||||||
resp = client.create_db_cluster(
|
resp = client.create_db_cluster(
|
||||||
DBClusterIdentifier="cluster-id",
|
DBClusterIdentifier="cluster-id",
|
||||||
DatabaseName="users",
|
DatabaseName="users",
|
||||||
Engine="aurora-mysql",
|
Engine="aurora-postgresql",
|
||||||
EngineMode="serverless",
|
EngineMode="serverless",
|
||||||
EngineVersion="5.7.0",
|
EngineVersion="5.7.0",
|
||||||
MasterUsername="root",
|
MasterUsername="root",
|
||||||
|
@ -74,7 +74,7 @@ def test_add_instance_to_serverless_cluster():
|
|||||||
|
|
||||||
_ = client.create_db_cluster(
|
_ = client.create_db_cluster(
|
||||||
DBClusterIdentifier="dbci",
|
DBClusterIdentifier="dbci",
|
||||||
Engine="aurora",
|
Engine="aurora-postgresql",
|
||||||
EngineMode="serverless",
|
EngineMode="serverless",
|
||||||
MasterUsername="masterusername",
|
MasterUsername="masterusername",
|
||||||
MasterUserPassword="hunter2_",
|
MasterUserPassword="hunter2_",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user