From 5f7c3eb6ce47006989f0b0cb0640a9d45935aa62 Mon Sep 17 00:00:00 2001 From: Lucas Vieira Date: Tue, 28 Apr 2026 08:53:07 -0300 Subject: [PATCH] test(rds): wait for db instance available before chaining ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CreateDBInstance is async (returns immediately with status="creating" and the postgres container starts in a background task). Conformance tests that chain operations on the new instance — CreateDBSnapshot, RebootDBInstance, ModifyDBInstance with apply_immediately, read replica creation, restore from snapshot, delete with final snapshot — were running against a "creating" instance and either erroring or observing intermediate state. 10 RDS tests have been failing on main since the async work landed. Adds wait_for_db_instance_available helper that polls DescribeDBInstances every 250ms (60s timeout) until status is "available". Wires it into the create_instance helper so every test that uses it gets a ready instance, and adds inline waits in the three tests that build the instance manually instead of going through the helper. Tests covered: rds_describe_db_instances, rds_create_db_snapshot, rds_describe_db_snapshots, rds_delete_db_snapshot, rds_describe_db_snapshots_pagination, rds_reboot_db_instance, rds_modify_db_instance_with_apply_immediately_false, rds_create_db_instance_read_replica, rds_restore_db_instance_from_db_snapshot, rds_delete_db_instance_with_final_snapshot. --- crates/fakecloud-conformance/tests/rds.rs | 55 ++++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/crates/fakecloud-conformance/tests/rds.rs b/crates/fakecloud-conformance/tests/rds.rs index 994db753..429071cc 100644 --- a/crates/fakecloud-conformance/tests/rds.rs +++ b/crates/fakecloud-conformance/tests/rds.rs @@ -91,6 +91,8 @@ async fn rds_describe_db_instances() { .await .unwrap(); + wait_for_db_instance_available(&client, "conf-rds-db").await; + let response = client .describe_db_instances() .db_instance_identifier("conf-rds-db") @@ -540,7 +542,7 @@ async fn create_instance_with_deletion_protection( db_instance_identifier: &str, deletion_protection: bool, ) -> aws_sdk_rds::operation::create_db_instance::CreateDbInstanceOutput { - client + let response = client .create_db_instance() .db_instance_identifier(db_instance_identifier) .allocated_storage(20) @@ -553,7 +555,52 @@ async fn create_instance_with_deletion_protection( .db_name("appdb") .send() .await - .unwrap() + .unwrap(); + wait_for_db_instance_available(client, db_instance_identifier).await; + response +} + +/// CreateDBInstance returns immediately with status="creating" and the +/// real postgres container starts in a background task. Tests that +/// chain operations on the instance (snapshot, modify, reboot, etc.) +/// need it to reach "available" first or the followup either errors or +/// observes intermediate state. Polls DescribeDBInstances every 250ms +/// for up to 60s. +async fn wait_for_db_instance_available( + client: &aws_sdk_rds::Client, + db_instance_identifier: &str, +) { + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(60); + loop { + let response = client + .describe_db_instances() + .db_instance_identifier(db_instance_identifier) + .send() + .await + .unwrap_or_else(|err| { + panic!("describe_db_instances during wait failed: {err:?}"); + }); + let status = response + .db_instances() + .first() + .and_then(|i| i.db_instance_status()) + .unwrap_or("") + .to_string(); + if status == "available" { + return; + } + if status == "failed" { + panic!( + "db instance {db_instance_identifier} entered status `failed` while waiting for available" + ); + } + if std::time::Instant::now() >= deadline { + panic!( + "timed out waiting for db instance {db_instance_identifier} to reach available (last status: {status})" + ); + } + tokio::time::sleep(std::time::Duration::from_millis(250)).await; + } } #[test_action("rds", "CreateDBSubnetGroup", checksum = "1b1b06a3")] @@ -873,6 +920,8 @@ async fn rds_delete_db_instance_with_final_snapshot() { .await .unwrap(); + wait_for_db_instance_available(&client, "conf-rds-final").await; + // Delete with final snapshot let response = client .delete_db_instance() @@ -982,6 +1031,8 @@ async fn rds_describe_db_snapshots_pagination() { .await .unwrap(); + wait_for_db_instance_available(&client, "conf-snap-paginate").await; + // Create 3 snapshots for i in 1..=3 { client