RDS: detect rds instance / cluster engine mismatch (#6994)
This commit is contained in:
		
							parent
							
								
									3945decb60
								
							
						
					
					
						commit
						0a5e2d3e4d
					
				| @ -201,3 +201,11 @@ class InvalidDBInstanceIdentifier(InvalidParameterValue): | ||||
|             "Identifiers must begin with a letter; must contain only ASCII letters, digits, and hyphens; " | ||||
|             "and must not end with a hyphen or contain two consecutive hyphens." | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class InvalidDBInstanceEngine(InvalidParameterCombination): | ||||
|     def __init__(self, instance_engine: str, cluster_engine: str) -> None: | ||||
|         super().__init__( | ||||
|             f"The engine name requested for your DB instance ({instance_engine}) doesn't match " | ||||
|             f"the engine name of your DB cluster ({cluster_engine})." | ||||
|         ) | ||||
|  | ||||
| @ -27,6 +27,7 @@ from .exceptions import ( | ||||
|     DBClusterParameterGroupNotFoundError, | ||||
|     OptionGroupNotFoundFaultError, | ||||
|     InvalidDBClusterStateFaultError, | ||||
|     InvalidDBInstanceEngine, | ||||
|     InvalidDBInstanceStateError, | ||||
|     SnapshotQuotaExceededError, | ||||
|     DBSnapshotAlreadyExistsError, | ||||
| @ -1593,6 +1594,10 @@ class RDSBackend(BaseBackend): | ||||
|                     raise InvalidParameterValue( | ||||
|                         "Instances cannot be added to Aurora Serverless clusters." | ||||
|                     ) | ||||
|                 if database.engine != cluster.engine: | ||||
|                     raise InvalidDBInstanceEngine( | ||||
|                         str(database.engine), str(cluster.engine) | ||||
|                     ) | ||||
|                 cluster.cluster_members.append(database_id) | ||||
|         self.databases[database_id] = database | ||||
|         return database | ||||
|  | ||||
| @ -7,10 +7,12 @@ import pytest | ||||
| from moto import mock_rds | ||||
| from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID | ||||
| 
 | ||||
| RDS_REGION = "eu-north-1" | ||||
| 
 | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_describe_db_cluster_initial(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     resp = client.describe_db_clusters() | ||||
|     assert len(resp["DBClusters"]) == 0 | ||||
| @ -18,7 +20,7 @@ def test_describe_db_cluster_initial(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_describe_db_cluster_fails_for_non_existent_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     resp = client.describe_db_clusters() | ||||
|     assert len(resp["DBClusters"]) == 0 | ||||
| @ -31,7 +33,7 @@ def test_describe_db_cluster_fails_for_non_existent_cluster(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_db_cluster_needs_master_username(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         client.create_db_cluster(DBClusterIdentifier="cluster-id", Engine="aurora") | ||||
| @ -44,7 +46,7 @@ def test_create_db_cluster_needs_master_username(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_db_cluster_needs_master_user_password(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         client.create_db_cluster( | ||||
| @ -59,7 +61,7 @@ def test_create_db_cluster_needs_master_user_password(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_db_cluster_needs_long_master_user_password(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         client.create_db_cluster( | ||||
| @ -78,7 +80,7 @@ def test_create_db_cluster_needs_long_master_user_password(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_modify_db_cluster_needs_long_master_user_password(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -102,7 +104,7 @@ def test_modify_db_cluster_needs_long_master_user_password(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_modify_db_cluster_new_cluster_identifier(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
|     old_id = "cluster-id" | ||||
|     new_id = "new-cluster-id" | ||||
| 
 | ||||
| @ -131,7 +133,7 @@ def test_modify_db_cluster_new_cluster_identifier(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_db_cluster__verify_default_properties(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     resp = client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -198,7 +200,7 @@ def test_create_db_cluster__verify_default_properties(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_db_cluster_additional_parameters(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     resp = client.create_db_cluster( | ||||
|         AvailabilityZones=["eu-north-1b"], | ||||
| @ -253,7 +255,7 @@ def test_create_db_cluster_additional_parameters(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_describe_db_cluster_after_creation(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id1", | ||||
| @ -286,7 +288,7 @@ def test_describe_db_cluster_after_creation(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_delete_db_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -302,7 +304,7 @@ def test_delete_db_cluster(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_delete_db_cluster_do_snapshot(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -323,7 +325,7 @@ def test_delete_db_cluster_do_snapshot(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_delete_db_cluster_that_is_protected(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -341,7 +343,7 @@ def test_delete_db_cluster_that_is_protected(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_delete_db_cluster_unknown_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         client.delete_db_cluster(DBClusterIdentifier="cluster-unknown") | ||||
| @ -352,7 +354,7 @@ def test_delete_db_cluster_unknown_cluster(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_start_db_cluster_unknown_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         client.start_db_cluster(DBClusterIdentifier="cluster-unknown") | ||||
| @ -363,7 +365,7 @@ def test_start_db_cluster_unknown_cluster(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_start_db_cluster_after_stopping(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -380,7 +382,7 @@ def test_start_db_cluster_after_stopping(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_start_db_cluster_without_stopping(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -398,7 +400,7 @@ def test_start_db_cluster_without_stopping(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_stop_db_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -419,7 +421,7 @@ def test_stop_db_cluster(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_stop_db_cluster_already_stopped(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -439,7 +441,7 @@ def test_stop_db_cluster_already_stopped(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_stop_db_cluster_unknown_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         client.stop_db_cluster(DBClusterIdentifier="cluster-unknown") | ||||
| @ -807,7 +809,7 @@ def test_add_tags_to_cluster_snapshot(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_serverless_db_cluster(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     resp = client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -831,7 +833,7 @@ def test_create_serverless_db_cluster(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_create_db_cluster_with_enable_http_endpoint_invalid(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     resp = client.create_db_cluster( | ||||
|         DBClusterIdentifier="cluster-id", | ||||
| @ -850,7 +852,7 @@ def test_create_db_cluster_with_enable_http_endpoint_invalid(): | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_describe_db_clusters_filter_by_engine(): | ||||
|     client = boto3.client("rds", region_name="eu-north-1") | ||||
|     client = boto3.client("rds", region_name=RDS_REGION) | ||||
| 
 | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier="id1", | ||||
| @ -922,3 +924,37 @@ def test_replicate_cluster(): | ||||
|     replica = us_west.describe_db_clusters()["DBClusters"][0] | ||||
|     assert "ReplicationSourceIdentifier" not in replica | ||||
|     assert replica["MultiAZ"] is False | ||||
| 
 | ||||
| 
 | ||||
| @mock_rds | ||||
| def test_createdb_instance_engine_mismatch_fail(): | ||||
|     # Setup | ||||
|     client = boto3.client("rds", "us-east-1") | ||||
|     cluster_name = "test-cluster" | ||||
|     client.create_db_cluster( | ||||
|         DBClusterIdentifier=cluster_name, | ||||
|         Engine="aurora-postgresql", | ||||
|         EngineVersion="12.14", | ||||
|         MasterUsername="testuser", | ||||
|         MasterUserPassword="password", | ||||
|     ) | ||||
| 
 | ||||
|     # Execute | ||||
| 
 | ||||
|     with pytest.raises(ClientError) as exc: | ||||
|         client.create_db_instance( | ||||
|             DBClusterIdentifier=cluster_name, | ||||
|             Engine="mysql", | ||||
|             EngineVersion="12.14", | ||||
|             DBInstanceIdentifier="test-instance", | ||||
|             DBInstanceClass="db.t4g.medium", | ||||
|         ) | ||||
| 
 | ||||
|     # Verify | ||||
|     err = exc.value.response["Error"] | ||||
|     assert err["Code"] == "InvalidParameterCombination" | ||||
|     assert ( | ||||
|         err["Message"] | ||||
|         == "The engine name requested for your DB instance (mysql) doesn't match " | ||||
|         "the engine name of your DB cluster (aurora-postgresql)." | ||||
|     ) | ||||
|  | ||||
| @ -21,7 +21,7 @@ def test_add_instance_as_cluster_member(): | ||||
|         DBInstanceIdentifier="dbi", | ||||
|         DBClusterIdentifier="dbci", | ||||
|         DBInstanceClass="db.r5.large", | ||||
|         Engine="aurora-postgresql", | ||||
|         Engine="mysql", | ||||
|     ) | ||||
| 
 | ||||
|     cluster = client.describe_db_clusters()["DBClusters"][0] | ||||
| @ -53,7 +53,7 @@ def test_remove_instance_from_cluster(): | ||||
|         DBInstanceIdentifier="dbi", | ||||
|         DBClusterIdentifier="dbci", | ||||
|         DBInstanceClass="db.r5.large", | ||||
|         Engine="aurora-postgresql", | ||||
|         Engine="mysql", | ||||
|     ) | ||||
| 
 | ||||
|     client.delete_db_instance( | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user