RDS: improve global clustering behaviour (#6403)
This commit is contained in:
		
							parent
							
								
									932b7a25d6
								
							
						
					
					
						commit
						a15b14085b
					
				@ -78,7 +78,7 @@ class GlobalCluster(BaseModel):
 | 
			
		||||
        self.deletion_protection = (
 | 
			
		||||
            deletion_protection and deletion_protection.lower() == "true"
 | 
			
		||||
        )
 | 
			
		||||
        self.members: List[str] = []
 | 
			
		||||
        self.members: List[Cluster] = []
 | 
			
		||||
 | 
			
		||||
    def to_xml(self) -> str:
 | 
			
		||||
        template = Template(
 | 
			
		||||
@ -92,10 +92,18 @@ class GlobalCluster(BaseModel):
 | 
			
		||||
          <StorageEncrypted>{{ 'true' if cluster.storage_encrypted else 'false' }}</StorageEncrypted>
 | 
			
		||||
          <DeletionProtection>{{ 'true' if cluster.deletion_protection else 'false' }}</DeletionProtection>
 | 
			
		||||
          <GlobalClusterMembers>
 | 
			
		||||
          {% for cluster_arn in cluster.members %}
 | 
			
		||||
          {% for cluster_member in cluster.members %}
 | 
			
		||||
          <GlobalClusterMember>
 | 
			
		||||
            <DBClusterArn>{{ cluster_arn }}</DBClusterArn>
 | 
			
		||||
            <IsWriter>true</IsWriter>
 | 
			
		||||
            <DBClusterArn>{{ cluster_member.db_cluster_arn }}</DBClusterArn>
 | 
			
		||||
            <IsWriter>{{ 'true' if cluster_member.is_writer else 'false' }}</IsWriter>
 | 
			
		||||
            {% if not cluster_member.is_writer %}<GlobalWriteForwardingStatus>disabled</GlobalWriteForwardingStatus>{% endif %}
 | 
			
		||||
                <Readers>
 | 
			
		||||
                    {% if cluster_member.is_writer %}
 | 
			
		||||
                        {% for reader in cluster.members %}
 | 
			
		||||
                            {% if not reader.is_writer %}<Reader>{{ reader.db_cluster_arn }}</Reader>{% endif %}
 | 
			
		||||
                        {% endfor %}
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </Readers>
 | 
			
		||||
          </GlobalClusterMember>
 | 
			
		||||
          {% endfor %}
 | 
			
		||||
          </GlobalClusterMembers>
 | 
			
		||||
@ -141,11 +149,15 @@ class Cluster:
 | 
			
		||||
                engine=self.engine, storage_type=self.storage_type  # type: ignore
 | 
			
		||||
            )
 | 
			
		||||
        self.master_username = kwargs.get("master_username")
 | 
			
		||||
        if not self.master_username:
 | 
			
		||||
        self.global_cluster_identifier = kwargs.get("global_cluster_identifier")
 | 
			
		||||
        if not self.master_username and self.global_cluster_identifier:
 | 
			
		||||
            pass
 | 
			
		||||
        elif not self.master_username:
 | 
			
		||||
            raise InvalidParameterValue(
 | 
			
		||||
                "The parameter MasterUsername must be provided and must not be blank."
 | 
			
		||||
            )
 | 
			
		||||
        self.master_user_password = kwargs.get("master_user_password")  # type: ignore
 | 
			
		||||
        else:
 | 
			
		||||
            self.master_user_password = kwargs.get("master_user_password")  # type: ignore
 | 
			
		||||
 | 
			
		||||
        self.availability_zones = kwargs.get("availability_zones")
 | 
			
		||||
        if not self.availability_zones:
 | 
			
		||||
@ -194,10 +206,10 @@ class Cluster:
 | 
			
		||||
                "timeout_action": "RollbackCapacityChange",
 | 
			
		||||
                "seconds_before_timeout": 300,
 | 
			
		||||
            }
 | 
			
		||||
        self.global_cluster_identifier = kwargs.get("global_cluster_identifier")
 | 
			
		||||
        self.cluster_members: List[str] = list()
 | 
			
		||||
        self.replication_source_identifier = kwargs.get("replication_source_identifier")
 | 
			
		||||
        self.read_replica_identifiers: List[str] = list()
 | 
			
		||||
        self.is_writer: bool = False
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_multi_az(self) -> bool:
 | 
			
		||||
@ -2119,7 +2131,27 @@ class RDSBackend(BaseBackend):
 | 
			
		||||
            and cluster.global_cluster_identifier in self.global_clusters
 | 
			
		||||
        ):
 | 
			
		||||
            global_cluster = self.global_clusters[cluster.global_cluster_identifier]
 | 
			
		||||
            global_cluster.members.append(cluster.db_cluster_arn)
 | 
			
		||||
 | 
			
		||||
            # Main DB cluster, does RW on global cluster
 | 
			
		||||
            setattr(cluster, "is_writer", True)
 | 
			
		||||
            # self.clusters[cluster_id] = cluster
 | 
			
		||||
            global_cluster.members.append(cluster)
 | 
			
		||||
 | 
			
		||||
        # search all backend to check if global cluster named global_cluster_identifier exists
 | 
			
		||||
        # anywhere else
 | 
			
		||||
        if (
 | 
			
		||||
            cluster.global_cluster_identifier
 | 
			
		||||
            and cluster.global_cluster_identifier not in self.global_clusters
 | 
			
		||||
        ):
 | 
			
		||||
            for regional_backend in rds_backends[self.account_id]:
 | 
			
		||||
                if (
 | 
			
		||||
                    cluster.global_cluster_identifier
 | 
			
		||||
                    in rds_backends[self.account_id][regional_backend].global_clusters
 | 
			
		||||
                ):
 | 
			
		||||
                    global_cluster = rds_backends[self.account_id][
 | 
			
		||||
                        regional_backend
 | 
			
		||||
                    ].global_clusters[cluster.global_cluster_identifier]
 | 
			
		||||
                    global_cluster.members.append(cluster)
 | 
			
		||||
 | 
			
		||||
        if cluster.replication_source_identifier:
 | 
			
		||||
            cluster_identifier = cluster.replication_source_identifier
 | 
			
		||||
@ -2623,7 +2655,7 @@ class RDSBackend(BaseBackend):
 | 
			
		||||
        self.global_clusters[global_cluster_identifier] = global_cluster
 | 
			
		||||
        if source_cluster is not None:
 | 
			
		||||
            source_cluster.global_cluster_identifier = global_cluster.global_cluster_arn
 | 
			
		||||
            global_cluster.members.append(source_cluster.db_cluster_arn)
 | 
			
		||||
            global_cluster.members.append(source_cluster)
 | 
			
		||||
        return global_cluster
 | 
			
		||||
 | 
			
		||||
    def describe_global_clusters(self) -> List[GlobalCluster]:
 | 
			
		||||
@ -2650,7 +2682,7 @@ class RDSBackend(BaseBackend):
 | 
			
		||||
            cluster = self.describe_db_clusters(
 | 
			
		||||
                cluster_identifier=db_cluster_identifier
 | 
			
		||||
            )[0]
 | 
			
		||||
            global_cluster.members.remove(cluster.db_cluster_arn)
 | 
			
		||||
            global_cluster.members.remove(cluster)
 | 
			
		||||
            return global_cluster
 | 
			
		||||
        except:  # noqa: E722 Do not use bare except
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
@ -91,6 +91,66 @@ def test_create_global_cluster_from_regular_cluster():
 | 
			
		||||
    assert global_cluster["GlobalClusterMembers"][0]["DBClusterArn"] == cluster_arn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@mock_rds
 | 
			
		||||
def test_create_global_cluster_from_regular_cluster_with_reader():
 | 
			
		||||
    east_client = boto3.client("rds", "eu-west-1")
 | 
			
		||||
    west_client = boto3.client("rds", "eu-west-2")
 | 
			
		||||
 | 
			
		||||
    # Create global cluster
 | 
			
		||||
    east_client.create_global_cluster(
 | 
			
		||||
        GlobalClusterIdentifier="test-global-db",
 | 
			
		||||
        Engine="aurora-mysql",
 | 
			
		||||
        DeletionProtection=False,
 | 
			
		||||
        DatabaseName="test-db",
 | 
			
		||||
        StorageEncrypted=False,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    east_client.create_db_cluster(
 | 
			
		||||
        DBClusterIdentifier="test-primary-cluster",
 | 
			
		||||
        Engine="aurora-mysql",
 | 
			
		||||
        GlobalClusterIdentifier="test-global-db",
 | 
			
		||||
        MasterUsername="testUsername",
 | 
			
		||||
        MasterUserPassword="testPassword",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    east_client.create_db_instance(
 | 
			
		||||
        DBInstanceIdentifier="test-primary-cluster-i1",
 | 
			
		||||
        DBInstanceClass="db.r5.large",
 | 
			
		||||
        Engine="aurora-mysql",
 | 
			
		||||
        PubliclyAccessible=False,
 | 
			
		||||
        DBClusterIdentifier="test-primary-cluster",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    west_client.create_db_cluster(
 | 
			
		||||
        DBClusterIdentifier="test-secondary-cluster",
 | 
			
		||||
        Engine="aurora-mysql",
 | 
			
		||||
        GlobalClusterIdentifier="test-global-db",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    resp = east_client.describe_global_clusters(
 | 
			
		||||
        GlobalClusterIdentifier="test-global-db"
 | 
			
		||||
    )
 | 
			
		||||
    members = resp["GlobalClusters"][0]["GlobalClusterMembers"]
 | 
			
		||||
    assert len(members) == 2
 | 
			
		||||
    assert (
 | 
			
		||||
        members[0]["DBClusterArn"]
 | 
			
		||||
        == "arn:aws:rds:eu-west-1:123456789012:cluster:test-primary-cluster"
 | 
			
		||||
    )
 | 
			
		||||
    assert len(members[0]["Readers"]) == 1
 | 
			
		||||
    assert (
 | 
			
		||||
        members[0]["Readers"][0]
 | 
			
		||||
        == "arn:aws:rds:eu-west-2:123456789012:cluster:test-secondary-cluster"
 | 
			
		||||
    )
 | 
			
		||||
    assert members[0]["IsWriter"]
 | 
			
		||||
 | 
			
		||||
    assert (
 | 
			
		||||
        members[1]["DBClusterArn"]
 | 
			
		||||
        == "arn:aws:rds:eu-west-2:123456789012:cluster:test-secondary-cluster"
 | 
			
		||||
    )
 | 
			
		||||
    assert len(members[1]["Readers"]) == 0
 | 
			
		||||
    assert not members[1]["IsWriter"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@mock_rds
 | 
			
		||||
def test_create_global_cluster_from_regular_cluster__using_name():
 | 
			
		||||
    client = boto3.client("rds", "us-east-1")
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user