Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker-rds-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ jobs:
type=raw,value=${{ matrix.target.version }}-dev-${{ steps.sha.outputs.short }},enable=${{ github.event_name == 'workflow_dispatch' }}

- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0
uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0
with:
image-ref: ${{ env.IMAGE_BASE }}:${{ steps.meta.outputs.version }}
format: table
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ jobs:
type=raw,value=latest,enable={{is_default_branch}}

- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0
uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
format: table
Expand Down
160 changes: 80 additions & 80 deletions conformance-baseline.json
Original file line number Diff line number Diff line change
@@ -1,138 +1,138 @@
{
"variants_passed": 80074,
"variants_passed": 80073,
"total_variants": 81489,
"per_service": {
"cognito-idp": {
"passed": 4479,
"total": 4479
"cloudformation": {
"passed": 3420,
"total": 3420
},
"wafv2": {
"passed": 2141,
"total": 2141
"athena": {
"passed": 2320,
"total": 2320
},
"apigatewayv2": {
"passed": 2769,
"total": 2769
},
"route53": {
"passed": 2388,
"total": 2388
},
"ses": {
"passed": 2858,
"total": 2858
},
"iam": {
"passed": 5962,
"total": 5962
},
"elasticache": {
"passed": 2219,
"total": 2219
"scheduler": {
"passed": 460,
"total": 491
},
"logs": {
"passed": 3911,
"total": 3911
"ecs": {
"passed": 1733,
"total": 2327
},
"states": {
"passed": 1256,
"total": 1292
"elasticloadbalancing": {
"passed": 1560,
"total": 1560
},
"cloudfront": {
"passed": 3576,
"total": 4103
},
"sqs": {
"passed": 549,
"total": 549
},
"rds": {
"passed": 5376,
"total": 5376
},
"bedrock-runtime": {
"passed": 412,
"total": 412
},
"kms": {
"passed": 2196,
"total": 2196
},
"kinesis": {
"passed": 1611,
"total": 1611
"states": {
"passed": 1256,
"total": 1292
},
"cloudfront": {
"passed": 3576,
"total": 4103
"sts": {
"passed": 438,
"total": 438
},
"sns": {
"passed": 1027,
"total": 1027
},
"apigatewayv1": {
"passed": 3135,
"total": 3362
},
"sts": {
"passed": 438,
"total": 438
"dynamodb": {
"passed": 2123,
"total": 2123
},
"scheduler": {
"passed": 460,
"total": 491
"bedrock": {
"passed": 3591,
"total": 3591
},
"s3": {
"passed": 3620,
"total": 3620
"logs": {
"passed": 3911,
"total": 3911
},
"ecr": {
"passed": 1789,
"total": 1789
"apigatewayv1": {
"passed": 3134,
"total": 3362
},
"secretsmanager": {
"passed": 852,
"total": 852
},
"bedrock": {
"passed": 3591,
"total": 3591
"kms": {
"passed": 2196,
"total": 2196
},
"athena": {
"passed": 2320,
"total": 2320
"wafv2": {
"passed": 2141,
"total": 2141
},
"ssm": {
"passed": 5303,
"total": 5303
"cognito-idp": {
"passed": 4479,
"total": 4479
},
"lambda": {
"passed": 3347,
"total": 3347
},
"ecs": {
"passed": 1733,
"total": 2327
},
"cloudformation": {
"passed": 3420,
"total": 3420
"s3": {
"passed": 3620,
"total": 3620
},
"ses": {
"passed": 2858,
"total": 2858
"bedrock-runtime": {
"passed": 412,
"total": 412
},
"events": {
"passed": 2108,
"total": 2108
},
"apigatewayv2": {
"passed": 2769,
"total": 2769
},
"dynamodb": {
"passed": 2123,
"total": 2123
},
"application-autoscaling": {
"passed": 944,
"total": 944
},
"ecr": {
"passed": 1789,
"total": 1789
},
"elasticache": {
"passed": 2219,
"total": 2219
},
"ssm": {
"passed": 5303,
"total": 5303
},
"acm": {
"passed": 601,
"total": 601
},
"elasticloadbalancing": {
"passed": 1560,
"total": 1560
},
"sqs": {
"passed": 549,
"total": 549
"kinesis": {
"passed": 1611,
"total": 1611
}
}
}
42 changes: 40 additions & 2 deletions crates/fakecloud-conformance/tests/rds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ async fn rds_describe_db_instances() {
.await
.unwrap();

wait_for_db_available(&client, "conf-rds-db").await;

let response = client
.describe_db_instances()
.db_instance_identifier("conf-rds-db")
Expand Down Expand Up @@ -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)
Expand All @@ -553,7 +555,39 @@ async fn create_instance_with_deletion_protection(
.db_name("appdb")
.send()
.await
.unwrap()
.unwrap();

// Async CreateDBInstance returns a `creating` placeholder; the
// background container start has to finish before any caller can
// exercise snapshot / replica / dump paths without hitting
// "Docker/Podman is required for RDS DB instances but is not
// available". Poll until the instance flips to `available`.
wait_for_db_available(client, db_instance_identifier).await;

response
}

async fn wait_for_db_available(client: &aws_sdk_rds::Client, db_instance_identifier: &str) {
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(240);
while std::time::Instant::now() < deadline {
let response = client
.describe_db_instances()
.db_instance_identifier(db_instance_identifier)
.send()
.await
.unwrap();
if let Some(status) = response
.db_instances()
.first()
.and_then(|i| i.db_instance_status())
{
if status == "available" {
return;
}
}
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
panic!("DB instance {db_instance_identifier} did not reach `available` within 240s");
}

#[test_action("rds", "CreateDBSubnetGroup", checksum = "1b1b06a3")]
Expand Down Expand Up @@ -873,6 +907,8 @@ async fn rds_delete_db_instance_with_final_snapshot() {
.await
.unwrap();

wait_for_db_available(&client, "conf-rds-final").await;

// Delete with final snapshot
let response = client
.delete_db_instance()
Expand Down Expand Up @@ -982,6 +1018,8 @@ async fn rds_describe_db_snapshots_pagination() {
.await
.unwrap();

wait_for_db_available(&client, "conf-snap-paginate").await;

// Create 3 snapshots
for i in 1..=3 {
client
Expand Down
24 changes: 24 additions & 0 deletions crates/fakecloud-e2e/tests/rds_mysql_lambda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
//! images. Each test creates a Lambda, spins up the engine container,
//! and exercises both the sync and async invocation paths through the
//! libcurl-backed UDF + bridge endpoint round trip.
//!
//! Gated behind `FAKECLOUD_E2E_HEAVY_DBS=1` (same pattern as
//! `rds_heavy_engines.rs`): on a fresh PR build the prebuilt
//! `fakecloud-mysql` / `fakecloud-mariadb` images are not yet on
//! ghcr.io for the in-flight version, so the runtime falls back to a
//! local `docker build` that pushes the per-job E2E budget over
//! 30 minutes. CI lanes that bake the heavy images opt in via the
//! variable; the regular E2E lane skips.

mod helpers;

Expand All @@ -13,6 +21,12 @@ use aws_sdk_lambda::primitives::Blob;
use helpers::TestServer;
use mysql_async::prelude::*;

fn heavy_dbs_opted_in() -> bool {
std::env::var("FAKECLOUD_E2E_HEAVY_DBS")
.map(|v| v == "1")
.unwrap_or(false)
}

fn make_echo_zip() -> Vec<u8> {
let buf = Vec::new();
let cursor = std::io::Cursor::new(buf);
Expand Down Expand Up @@ -93,10 +107,20 @@ async fn run_lambda_round_trip(engine: &str, engine_version: &str, db_id: &str)

#[tokio::test]
async fn aws_lambda_bridge_mysql_round_trip() {
if !heavy_dbs_opted_in() {
eprintln!(
"skipping aws_lambda_bridge_mysql_round_trip — set FAKECLOUD_E2E_HEAVY_DBS=1 to enable"
);
return;
}
run_lambda_round_trip("mysql", "8.0", "mysql-lambda-db").await;
}

#[tokio::test]
async fn aws_lambda_bridge_mariadb_round_trip() {
if !heavy_dbs_opted_in() {
eprintln!("skipping aws_lambda_bridge_mariadb_round_trip — set FAKECLOUD_E2E_HEAVY_DBS=1 to enable");
return;
}
run_lambda_round_trip("mariadb", "10.11", "mariadb-lambda-db").await;
}
13 changes: 9 additions & 4 deletions crates/fakecloud-rds/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2477,10 +2477,13 @@ fn validate_create_request(
// dev-edition images (gvenzl/oracle-free 23, mssql-server 2022,
// db2_community 11.5). Adding a new version here also requires
// wiring the image tag in `RdsRuntime::ensure_postgres`.
// Major versions ("8.0", "10.11", ...) are accepted alongside the
// full `<major>.<minor>.<patch>` triplets — AWS RDS validates both
// forms and the runtime resolves the matching prebuilt image regardless.
let supported_versions = match engine {
"postgres" => vec!["16.3", "15.5", "14.10", "13.13"],
"mysql" => vec!["8.0.35", "8.0.28", "5.7.44"],
"mariadb" => vec!["10.11.6", "10.6.16"],
"postgres" => vec!["16", "15", "14", "13", "16.3", "15.5", "14.10", "13.13"],
"mysql" => vec!["8.0", "8.0.35", "8.0.28", "5.7.44"],
"mariadb" => vec!["10.6", "10.11", "11.4", "11.4.5", "10.11.6", "10.6.16"],
"oracle-ee" | "oracle-se2" | "oracle-ee-cdb" | "oracle-se2-cdb" => {
vec!["23.0.0", "21.0.0", "19.0.0"]
}
Expand Down Expand Up @@ -3178,7 +3181,9 @@ fn default_parameter_group(engine: &str, engine_version: &str) -> String {
format!("default.mysql{}", major)
}
"mariadb" => {
let major = if engine_version.starts_with("10.11") {
let major = if engine_version.starts_with("11.4") {
"11.4"
} else if engine_version.starts_with("10.11") {
"10.11"
} else {
"10.6"
Expand Down
Loading
Loading