feat: migrate FTP/SFTP to protocols crate and update dependencies (#1580)

Signed-off-by: yxrxy <yxrxytrigger@gmail.com>
Signed-off-by: houseme <housemecn@gmail.com>
Signed-off-by: heihutu <30542132+heihutu@users.noreply.github.com>
Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: heihutu <30542132+heihutu@users.noreply.github.com>
Co-authored-by: loverustfs <hello@rustfs.com>
This commit is contained in:
yxrxy
2026-02-06 20:58:42 +08:00
committed by GitHub
parent a2b88a79ec
commit 5c2eda356e
38 changed files with 1997 additions and 4756 deletions
+8
View File
@@ -81,6 +81,14 @@ fn build_rustfs_binary() {
let mut cmd = Command::new("cargo");
cmd.current_dir(&workspace).args(["build", "--bin", "rustfs"]);
// Read features from environment variable for e2e tests
if let Ok(features) = std::env::var("RUSTFS_BUILD_FEATURES")
&& !features.is_empty()
{
cmd.arg("--features").arg(&features);
info!("Building with features: {}", features);
}
if !cfg!(debug_assertions) {
cmd.arg("--release");
}
+4 -8
View File
@@ -1,6 +1,6 @@
# Protocol E2E Tests
FTPS and SFTP protocol end-to-end tests for RustFS.
FTPS protocol end-to-end tests for RustFS.
## Prerequisites
@@ -21,12 +21,7 @@ brew install sshpass openssh
Run all protocol tests:
```bash
cargo test --package e2e_test test_protocol_core_suite -- --test-threads=1 --nocapture
```
Run only FTPS tests:
```bash
cargo test --package e2e_test test_ftps_core_operations -- --test-threads=1 --nocapture
RUSTFS_BUILD_FEATURES=ftps cargo test --package e2e_test test_protocol_core_suite -- --test-threads=1 --nocapture
```
## Test Coverage
@@ -41,4 +36,5 @@ cargo test --package e2e_test test_ftps_core_operations -- --test-threads=1 --no
- cd nonexistent bucket (should fail)
- delete object
- cdup
- rmdir delete bucket
- rmdir delete bucket
+21 -11
View File
@@ -36,15 +36,26 @@ const FTPS_ADDRESS: &str = "127.0.0.1:9021";
pub async fn test_ftps_core_operations() -> Result<()> {
let env = ProtocolTestEnvironment::new().map_err(|e| anyhow::anyhow!("{}", e))?;
// Generate and write certificate
let cert = generate_simple_self_signed(vec!["localhost".to_string(), "127.0.0.1".to_string()])?;
let cert_path = PathBuf::from(&env.temp_dir).join("ftps.crt");
let key_path = PathBuf::from(&env.temp_dir).join("ftps.key");
let cert_dir = PathBuf::from(&env.temp_dir).join("ftps_certs");
tokio::fs::create_dir_all(&cert_dir).await?;
let cert_pem = cert.cert.pem();
let key_pem = cert.signing_key.serialize_pem();
tokio::fs::write(&cert_path, &cert_pem).await?;
tokio::fs::write(&key_path, &key_pem).await?;
// Generate default certificate for root directory
let default_cert = generate_simple_self_signed(vec!["localhost".to_string(), "127.0.0.1".to_string()])?;
let default_cert_path = cert_dir.join("rustfs_cert.pem");
let default_key_path = cert_dir.join("rustfs_key.pem");
tokio::fs::write(&default_cert_path, default_cert.cert.pem()).await?;
tokio::fs::write(&default_key_path, default_cert.signing_key.serialize_pem()).await?;
// Create subdirectory for domain-specific certificate
let example_domain_dir = cert_dir.join("example1.com");
tokio::fs::create_dir_all(&example_domain_dir).await?;
let domain_cert = generate_simple_self_signed(vec!["example1.com".to_string()])?;
let domain_cert_path = example_domain_dir.join("rustfs_cert.pem");
let domain_key_path = example_domain_dir.join("rustfs_key.pem");
tokio::fs::write(&domain_cert_path, domain_cert.cert.pem()).await?;
tokio::fs::write(&domain_key_path, domain_cert.signing_key.serialize_pem()).await?;
info!("Generated 2 certificates in {:?}", cert_dir);
// Start server manually
info!("Starting FTPS server on {}", FTPS_ADDRESS);
@@ -52,8 +63,7 @@ pub async fn test_ftps_core_operations() -> Result<()> {
let mut server_process = Command::new(&binary_path)
.env("RUSTFS_FTPS_ENABLE", "true")
.env("RUSTFS_FTPS_ADDRESS", FTPS_ADDRESS)
.env("RUSTFS_FTPS_CERTS_FILE", cert_path.to_str().unwrap())
.env("RUSTFS_FTPS_KEY_FILE", key_path.to_str().unwrap())
.env("RUSTFS_FTPS_CERTS_DIR", cert_dir.to_str().unwrap())
.arg(&env.temp_dir)
.spawn()?;
@@ -73,7 +83,7 @@ pub async fn test_ftps_core_operations() -> Result<()> {
let mut root_store = RootCertStore::empty();
// Add the self-signed certificate to the trust store for e2e
// Note: In a real environment, you'd use proper root certificates
let cert_pem = cert.cert.pem();
let cert_pem = default_cert.cert.pem();
let cert_der = rustls_pemfile::certs(&mut Cursor::new(cert_pem))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| anyhow::anyhow!("Failed to parse cert: {}", e))?;
+1 -1
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Protocol tests for FTPS and SFTP
//! Protocol tests for FTPS
pub mod ftps_core;
pub mod test_env;
+3 -11
View File
@@ -59,12 +59,9 @@ struct TestDefinition {
impl ProtocolTestSuite {
/// Create default test suite
pub fn new() -> Self {
let tests = vec![
TestDefinition {
name: "test_ftps_core_operations".to_string(),
},
// TestDefinition { name: "test_sftp_core_operations".to_string() },
];
let tests = vec![TestDefinition {
name: "test_ftps_core_operations".to_string(),
}];
Self { tests }
}
@@ -86,10 +83,6 @@ impl ProtocolTestSuite {
info!("=== Starting FTPS Module Test ===");
"FTPS core operations (put, ls, mkdir, rmdir, delete)"
}
"test_sftp_core_operations" => {
info!("=== Starting SFTP Module Test ===");
"SFTP core operations (put, ls, mkdir, rmdir, delete)"
}
_ => "",
};
@@ -128,7 +121,6 @@ impl ProtocolTestSuite {
async fn run_single_test(&self, test_def: &TestDefinition) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
match test_def.name.as_str() {
"test_ftps_core_operations" => test_ftps_core_operations().await.map_err(|e| e.into()),
// "test_sftp_core_operations" => test_sftp_core_operations().await.map_err(|e| e.into()),
_ => Err(format!("Test {} not implemented", test_def.name).into()),
}
}