From 1deb58907736931e957db6d55f650b06c50af00d Mon Sep 17 00:00:00 2001 From: overtrue Date: Sun, 23 Aug 2026 03:06:52 +0800 Subject: [PATCH] test(e2e): reject missing awscurl --- .github/workflows/e2e-replication-nightly.yml | 8 +-- .../e2e_test/src/bucket_policy_check_test.rs | 3 -- crates/e2e_test/src/common.rs | 11 ---- .../src/existing_object_tag_policy_test.rs | 24 +-------- crates/e2e_test/src/kms/common.rs | 17 +------ crates/e2e_test/src/kms/kms_local_test.rs | 6 +-- crates/e2e_test/src/kms/kms_vault_test.rs | 19 +------ crates/e2e_test/src/multipart_auth_test.rs | 4 -- crates/e2e_test/src/quota_test.rs | 51 ------------------- .../src/replication_extension_test.rs | 10 +--- crates/e2e_test/src/security_boundary_test.rs | 11 ++-- 11 files changed, 12 insertions(+), 152 deletions(-) diff --git a/.github/workflows/e2e-replication-nightly.yml b/.github/workflows/e2e-replication-nightly.yml index 837d9f79f..cd5cab019 100644 --- a/.github/workflows/e2e-replication-nightly.yml +++ b/.github/workflows/e2e-replication-nightly.yml @@ -75,11 +75,7 @@ jobs: cache-save-if: ${{ github.ref == 'refs/heads/main' }} install-build-packaging-tools: 'false' - # awscurl lets the STS dual-node test actually exercise its path. Without - # it the test skips gracefully with a visible log line - # (`awscurl_available()` in crates/e2e_test/src/common.rs), so the lane - # still passes — installing it just upgrades that one test from skip to - # real coverage. + # The STS dual-node test requires awscurl and fails if it is unavailable. - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: @@ -87,7 +83,7 @@ jobs: - name: Install awscurl run: | - python3 -m pip install --user --upgrade pip awscurl + python3 -m pip install --user --upgrade pip "awscurl==0.44" echo "AWSCURL_PATH=$HOME/.local/bin/awscurl" >> "$GITHUB_ENV" - name: Verify awscurl diff --git a/crates/e2e_test/src/bucket_policy_check_test.rs b/crates/e2e_test/src/bucket_policy_check_test.rs index 3060954d6..0b9345f06 100644 --- a/crates/e2e_test/src/bucket_policy_check_test.rs +++ b/crates/e2e_test/src/bucket_policy_check_test.rs @@ -52,9 +52,6 @@ fn create_user_client(env: &RustFSTestEnvironment, access_key: &str, secret_key: #[tokio::test] async fn test_bucket_policy_authenticated_user() -> Result<(), Box> { init_logging(); - if !crate::common::awscurl_available() { - return Err("awscurl is required for test_bucket_policy_authenticated_user".into()); - } info!("Starting test_bucket_policy_authenticated_user..."); let mut env = RustFSTestEnvironment::new().await?; diff --git a/crates/e2e_test/src/common.rs b/crates/e2e_test/src/common.rs index 7fad7ea76..9fbf720cc 100644 --- a/crates/e2e_test/src/common.rs +++ b/crates/e2e_test/src/common.rs @@ -494,17 +494,6 @@ fn awscurl_binary_path() -> PathBuf { .unwrap_or_else(|| PathBuf::from("awscurl")) } -pub fn awscurl_available() -> bool { - let path = awscurl_binary_path(); - if path.components().count() > 1 || path.is_absolute() { - return path.is_file(); - } - - std::env::var_os("PATH") - .map(|paths| std::env::split_paths(&paths).any(|dir| dir.join(&path).is_file())) - .unwrap_or(false) -} - // Global initialization static INIT: Once = Once::new(); diff --git a/crates/e2e_test/src/existing_object_tag_policy_test.rs b/crates/e2e_test/src/existing_object_tag_policy_test.rs index 17c34f166..7668773ed 100644 --- a/crates/e2e_test/src/existing_object_tag_policy_test.rs +++ b/crates/e2e_test/src/existing_object_tag_policy_test.rs @@ -16,9 +16,7 @@ //! session policy** (`Policy` parameter) via `awscurl --service sts` with explicit //! `Content-Type: application/x-www-form-urlencoded` on `POST /`. -use crate::common::{ - RustFSTestEnvironment, awscurl_available, awscurl_delete, awscurl_post_sts_form_urlencoded, awscurl_put, init_logging, -}; +use crate::common::{RustFSTestEnvironment, awscurl_delete, awscurl_post_sts_form_urlencoded, awscurl_put, init_logging}; use aws_sdk_s3::config::{Credentials, Region}; use aws_sdk_s3::primitives::ByteStream; use aws_sdk_s3::types::{Delete, ObjectIdentifier, Tag, Tagging}; @@ -175,11 +173,6 @@ async fn cleanup_bucket_and_object(admin: &Client, bucket: &str, key: &str) { #[tokio::test] async fn test_e2e_iam_policy_existing_object_tag_get_object() -> Result<(), Box> { init_logging(); - if !awscurl_available() { - info!("Skipping test_e2e_iam_policy_existing_object_tag_get_object: awscurl not available"); - return Ok(()); - } - let suffix = Uuid::new_v4(); let user = format!("e2eiamtag-{suffix}"); let user_secret = "longSecretKeyForTest123!"; @@ -233,11 +226,6 @@ async fn test_e2e_iam_policy_existing_object_tag_get_object() -> Result<(), Box< #[tokio::test] async fn test_e2e_bucket_policy_existing_object_tag_get_object() -> Result<(), Box> { init_logging(); - if !awscurl_available() { - info!("Skipping test_e2e_bucket_policy_existing_object_tag_get_object: awscurl not available"); - return Ok(()); - } - let suffix = Uuid::new_v4(); let user = format!("e2ebptag-{suffix}"); let user_secret = "longSecretKeyForTest456!"; @@ -294,11 +282,6 @@ async fn test_e2e_bucket_policy_existing_object_tag_get_object() -> Result<(), B #[tokio::test] async fn test_e2e_sts_assume_role_session_policy_existing_object_tag() -> Result<(), Box> { init_logging(); - if !awscurl_available() { - info!("Skipping test_e2e_sts_assume_role_session_policy_existing_object_tag: awscurl not available"); - return Ok(()); - } - let suffix = Uuid::new_v4(); let parent = format!("e2e-sts-par-{suffix}"); let parent_secret = "longSecretKeyForParentSts99!"; @@ -370,11 +353,6 @@ async fn test_e2e_sts_assume_role_session_policy_existing_object_tag() -> Result #[tokio::test] async fn test_e2e_sts_session_policy_delete_objects_object_prefix_only() -> Result<(), Box> { init_logging(); - if !awscurl_available() { - info!("Skipping test_e2e_sts_session_policy_delete_objects_object_prefix_only: awscurl not available"); - return Ok(()); - } - let suffix = Uuid::new_v4(); let parent = format!("e2e-sts-del-par-{suffix}"); let parent_secret = "longSecretKeyForParentDelete99!"; diff --git a/crates/e2e_test/src/kms/common.rs b/crates/e2e_test/src/kms/common.rs index 07b21db4d..3a6c2d364 100644 --- a/crates/e2e_test/src/kms/common.rs +++ b/crates/e2e_test/src/kms/common.rs @@ -22,9 +22,7 @@ //! - KMS backend configuration (Local and Vault) //! - SSE encryption testing utilities -use crate::common::{ - RustFSTestEnvironment, awscurl_available, awscurl_get, awscurl_post, init_logging as common_init_logging, local_http_client, -}; +use crate::common::{RustFSTestEnvironment, awscurl_get, awscurl_post, init_logging as common_init_logging, local_http_client}; use aws_sdk_s3::Client; use aws_sdk_s3::primitives::ByteStream; use aws_sdk_s3::types::ServerSideEncryption; @@ -59,15 +57,6 @@ pub fn init_logging() { // Additional KMS-specific logging configuration can be added here if needed } -pub fn skip_if_kms_admin_tool_unavailable(test_name: &str) -> bool { - if awscurl_available() { - return false; - } - - info!("Skipping {} because awscurl is not available in PATH", test_name); - true -} - pub fn sse_customer_key_md5_base64(key: &str) -> String { let mut hasher = Md5::new(); hasher.update(key.as_bytes()); @@ -490,10 +479,6 @@ pub async fn test_kms_key_management( access_key: &str, secret_key: &str, ) -> Result<(), Box> { - if skip_if_kms_admin_tool_unavailable("test_kms_key_management") { - return Ok(()); - } - info!("Testing KMS key management APIs"); // Test CreateKey diff --git a/crates/e2e_test/src/kms/kms_local_test.rs b/crates/e2e_test/src/kms/kms_local_test.rs index 522b28478..4a8550b32 100644 --- a/crates/e2e_test/src/kms/kms_local_test.rs +++ b/crates/e2e_test/src/kms/kms_local_test.rs @@ -20,8 +20,7 @@ //! - Complete encryption/decryption lifecycle use super::common::{ - LocalKMSTestEnvironment, get_kms_status, skip_if_kms_admin_tool_unavailable, sse_customer_key_md5_base64, - test_kms_key_management, test_sse_c_encryption, + LocalKMSTestEnvironment, get_kms_status, sse_customer_key_md5_base64, test_kms_key_management, test_sse_c_encryption, }; use crate::common::{TEST_BUCKET, init_logging}; use tracing::{error, info}; @@ -29,9 +28,6 @@ use tracing::{error, info}; #[tokio::test] async fn test_local_kms_end_to_end() -> Result<(), Box> { init_logging(); - if skip_if_kms_admin_tool_unavailable("test_local_kms_end_to_end") { - return Ok(()); - } info!("Starting Local KMS End-to-End Test"); // Create LocalKMS test environment diff --git a/crates/e2e_test/src/kms/kms_vault_test.rs b/crates/e2e_test/src/kms/kms_vault_test.rs index 0dd19f703..c73515d95 100644 --- a/crates/e2e_test/src/kms/kms_vault_test.rs +++ b/crates/e2e_test/src/kms/kms_vault_test.rs @@ -22,8 +22,8 @@ use crate::common::{TEST_BUCKET, init_logging}; use tracing::{error, info}; use super::common::{ - VAULT_KEY_NAME, VaultTestEnvironment, get_kms_status, skip_if_kms_admin_tool_unavailable, sse_customer_key_md5_base64, - start_kms, test_all_multipart_encryption_types, test_error_scenarios, test_kms_key_management, test_sse_c_encryption, + VAULT_KEY_NAME, VaultTestEnvironment, get_kms_status, sse_customer_key_md5_base64, start_kms, + test_all_multipart_encryption_types, test_error_scenarios, test_kms_key_management, test_sse_c_encryption, test_sse_kms_encryption, test_sse_s3_encryption, }; @@ -62,9 +62,6 @@ impl VaultKmsTestContext { #[tokio::test] async fn test_vault_kms_end_to_end() -> Result<(), Box> { init_logging(); - if skip_if_kms_admin_tool_unavailable("test_vault_kms_end_to_end") { - return Ok(()); - } info!("Starting Vault KMS End-to-End Test with default key {}", VAULT_KEY_NAME); let context = VaultKmsTestContext::new().await?; @@ -117,9 +114,6 @@ async fn test_vault_kms_end_to_end() -> Result<(), Box Result<(), Box> { init_logging(); - if skip_if_kms_admin_tool_unavailable("test_vault_kms_key_isolation") { - return Ok(()); - } info!("Starting Vault KMS SSE-C key isolation test"); let context = VaultKmsTestContext::new().await?; @@ -203,9 +197,6 @@ async fn test_vault_kms_key_isolation() -> Result<(), Box Result<(), Box> { init_logging(); - if skip_if_kms_admin_tool_unavailable("test_vault_kms_large_file") { - return Ok(()); - } info!("Starting Vault KMS large file SSE-S3 test"); let context = VaultKmsTestContext::new().await?; @@ -267,9 +258,6 @@ async fn test_vault_kms_large_file() -> Result<(), Box Result<(), Box> { init_logging(); - if skip_if_kms_admin_tool_unavailable("test_vault_kms_multipart_upload") { - return Ok(()); - } info!("Starting Vault KMS multipart upload encryption suite"); let context = VaultKmsTestContext::new().await?; @@ -297,9 +285,6 @@ async fn test_vault_kms_multipart_upload() -> Result<(), Box Result<(), Box> { init_logging(); - if skip_if_kms_admin_tool_unavailable("test_vault_kms_key_operations") { - return Ok(()); - } info!("Starting Vault KMS key operations test (CRUD)"); let context = VaultKmsTestContext::new().await?; diff --git a/crates/e2e_test/src/multipart_auth_test.rs b/crates/e2e_test/src/multipart_auth_test.rs index 247cb46d7..334c55339 100644 --- a/crates/e2e_test/src/multipart_auth_test.rs +++ b/crates/e2e_test/src/multipart_auth_test.rs @@ -4278,10 +4278,6 @@ async fn test_signed_put_object_extract_preserves_pax_metadata_and_version_id() async fn test_signed_put_object_extract_authorizes_each_pax_privilege_and_retention_conditions() -> Result<(), Box> { init_logging(); - if !crate::common::awscurl_available() { - return Ok(()); - } - let mut env = RustFSTestEnvironment::new().await?; env.start_rustfs_server(vec![]).await?; diff --git a/crates/e2e_test/src/quota_test.rs b/crates/e2e_test/src/quota_test.rs index adff548ad..85d54b3f8 100644 --- a/crates/e2e_test/src/quota_test.rs +++ b/crates/e2e_test/src/quota_test.rs @@ -18,15 +18,6 @@ use http::{Method, StatusCode}; use tokio::time::{Duration, sleep, timeout}; use tracing::{debug, info}; -fn skip_without_awscurl() -> bool { - if crate::common::awscurl_available() { - return false; - } - - info!("Skipping quota test because awscurl is not available"); - true -} - /// Test environment setup for quota tests pub struct QuotaTestEnv { pub env: RustFSTestEnvironment, @@ -276,9 +267,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_basic_operations() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; // Create test bucket @@ -320,9 +308,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_admission_aws_chunked_declared_encoding() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -371,9 +356,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_update_and_clear() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -406,9 +388,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_delete_operations() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -442,9 +421,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_usage_tracking() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -480,9 +456,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_statistics() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -513,9 +486,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_check_api() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -553,9 +523,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_multiple_buckets() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; // Create two buckets in the same environment @@ -593,9 +560,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_error_handling() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -628,9 +592,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_http_endpoints() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -689,9 +650,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_normal_user_permissions() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -744,9 +702,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_copy_operations() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -789,9 +744,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_batch_delete() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; @@ -847,9 +799,6 @@ mod integration_tests { #[tokio::test] async fn test_quota_multipart_upload() -> Result<(), Box> { init_logging(); - if skip_without_awscurl() { - return Ok(()); - } let env = QuotaTestEnv::new().await?; env.create_bucket().await?; diff --git a/crates/e2e_test/src/replication_extension_test.rs b/crates/e2e_test/src/replication_extension_test.rs index 3d51d139b..be19fe4ed 100644 --- a/crates/e2e_test/src/replication_extension_test.rs +++ b/crates/e2e_test/src/replication_extension_test.rs @@ -13,9 +13,8 @@ // limitations under the License. use crate::common::{ - RustFSTestEnvironment, admin_create_user, awscurl_available, awscurl_post_sts_form_urlencoded, init_logging, - local_http_client, replication_fast_env, rustfs_binary_path, signed_request, signed_request_with_client, - signed_request_with_session_token, + RustFSTestEnvironment, admin_create_user, awscurl_post_sts_form_urlencoded, init_logging, local_http_client, + replication_fast_env, rustfs_binary_path, signed_request, signed_request_with_client, signed_request_with_session_token, }; use crate::fake_s3_target::{ FAKE_ACCESS_KEY, FAKE_SECRET_KEY, FakeS3Target, FaultAction as FakeTargetFault, Operation as FakeTargetOperation, @@ -7281,11 +7280,6 @@ async fn test_site_replication_replicates_multiple_service_accounts_real_dual_no async fn test_site_replication_replicates_service_accounts_created_from_sts_session_real_dual_node() -> TestResult { init_logging(); - if !awscurl_available() { - eprintln!("Skipping STS site replication service-account test because awscurl is unavailable"); - return Ok(()); - } - let mut source_env = RustFSTestEnvironment::new().await?; source_env .start_rustfs_server_with_env(vec![], LOOPBACK_REPLICATION_TARGET_ENV) diff --git a/crates/e2e_test/src/security_boundary_test.rs b/crates/e2e_test/src/security_boundary_test.rs index 0a62ef0f5..ee21ca9fa 100644 --- a/crates/e2e_test/src/security_boundary_test.rs +++ b/crates/e2e_test/src/security_boundary_test.rs @@ -21,7 +21,7 @@ //! - SSRF prevention (internal/private endpoints rejected for tiering) //! - Race condition handling (concurrent writes converge without corruption) -use crate::common::{RustFSTestEnvironment, awscurl_available, awscurl_put, init_logging}; +use crate::common::{RustFSTestEnvironment, awscurl_put, init_logging}; use aws_sdk_s3::error::ProvideErrorMetadata; use aws_sdk_s3::primitives::ByteStream; use aws_sdk_s3::types::{CompletedMultipartUpload, CompletedPart, Tag, Tagging}; @@ -225,16 +225,11 @@ async fn test_concurrent_object_operations() -> Result<(), Box Result<(), Box> { init_logging(); - if !awscurl_available() { - info!("Skipping tiering URL validation test because awscurl is not available"); - return Ok(()); - } - let mut env = RustFSTestEnvironment::new().await?; env.start_rustfs_server(vec![]).await?;