diff --git a/Cargo.lock b/Cargo.lock index aa95ca26..32be9a4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,12 +161,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - [[package]] name = "block-buffer" version = "0.10.4" @@ -842,17 +836,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] @@ -864,24 +848,11 @@ dependencies = [ "cfg-if", "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", "winapi", ] -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.2", - "smallvec", - "windows-targets 0.52.5", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -940,16 +911,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" -dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -960,7 +922,7 @@ checksum = "7263373d500d4d4f505d43a2a662d475a894aa94503a1ee28e9188b5f3960d4f" dependencies = [ "libm", "lru", - "parking_lot 0.11.2", + "parking_lot", "smallvec", "spin", ] @@ -1019,6 +981,7 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" name = "rustfs" version = "0.1.0" dependencies = [ + "anyhow", "async-trait", "clap", "ecstore", @@ -1026,7 +989,6 @@ dependencies = [ "s3s", "time", "tokio", - "tokio-util", "tracing", "tracing-subscriber", ] @@ -1207,9 +1169,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.67" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -1279,9 +1241,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -1303,7 +1265,6 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", @@ -1468,9 +1429,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" [[package]] name = "valuable" diff --git a/Cargo.toml b/Cargo.toml index efc56d59..d4ff0696 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,4 @@ http = "1.1.0" thiserror = "1.0.61" time = "0.3.36" async-trait = "0.1.80" -# tokio = { version = "1.38.0", features = ["macros", "rt", "rt-multi-thread", "fs", "io-util"] } -tokio = { version = "1.38.0", features = ["full"] } -tokio-util = { version = "0.7.8", features = ["io"] } +tokio = "1.38.0" diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index cee3b6c4..16e43ace 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -19,12 +19,12 @@ name = "rustfs" [dependencies] ecstore = { path = "../ecstore" } -time = { workspace = true, features = ["parsing", "formatting"] } -s3s = "0.10.0" -hyper-util = { version = "0.1.5", features = ["server-auto", "server-graceful", "http1", "http2", "tokio"] } -tokio.workspace = true clap = { version = "4.5.7", features = ["derive"] } -tracing.workspace = true -tokio-util.workspace = true +s3s = { version = "0.10.0" } +anyhow = { version = "1.0.86" } +tracing = { workspace = true } tracing-subscriber = { version = "0.3.18", features = ["env-filter", "time"] } -async-trait = "0.1.80" +time = { workspace = true, features = ["parsing", "formatting"] } +async-trait = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "macros", "net", "signal"] } +hyper-util = { version = "0.1.5", features = ["tokio", "server-auto", "server-graceful"] } diff --git a/rustfs/src/config/mod.rs b/rustfs/src/config/mod.rs new file mode 100644 index 00000000..043de8b6 --- /dev/null +++ b/rustfs/src/config/mod.rs @@ -0,0 +1,30 @@ +use clap::Parser; +use std::path::PathBuf; + +/// Default port that a rustfs server listens on. +/// +/// Used if no port is specified. +pub const DEFAULT_PORT: u16 = 9000; + +#[derive(Debug, Parser)] +pub struct Opt { + /// DIR points to a directory on a filesystem. + #[arg(required = true)] + pub volumes: Vec, + + /// bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname + #[arg(long, default_value_t = format!(":{}", DEFAULT_PORT))] + pub address: String, + + /// Access key used for authentication. + #[arg(long)] + pub access_key: Option, + + /// Secret key used for authentication. + #[arg(long)] + pub secret_key: Option, + + /// Domain name used for virtual-hosted-style requests. + #[arg(long)] + pub domain_name: Option, +} diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index e49b09d6..b0f45231 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -1,54 +1,17 @@ -use ecstore::error::Result; -use ecstore::store::ECStore; - -use s3s::auth::SimpleAuth; -use s3s::service::S3ServiceBuilder; +mod config; +mod storage; +use anyhow::Result; +use clap::Parser; +use hyper_util::{ + rt::{TokioExecutor, TokioIo}, + server::conn::auto::Builder as ConnBuilder, +}; +use s3s::{auth::SimpleAuth, service::S3ServiceBuilder}; use std::io::IsTerminal; -use std::path::PathBuf; - use tokio::net::TcpListener; - -use clap::{CommandFactory, Parser}; use tracing::info; -use hyper_util::rt::{TokioExecutor, TokioIo}; -use hyper_util::server::conn::auto::Builder as ConnBuilder; - -#[derive(Debug, Parser)] -#[command(version)] -struct Opt { - /// Host name to listen on. - #[arg(long, default_value = "localhost")] - host: String, - - /// Port number to listen on. - #[arg(long, default_value = "9010")] - port: u16, - - /// Access key used for authentication. - #[arg(long, default_value = "AKEXAMPLERUSTFS")] - access_key: Option, - - /// Secret key used for authentication. - #[arg(long, default_value = "SKEXAMPLERUSTFS")] - secret_key: Option, - - /// Domain name used for virtual-hosted-style requests. - #[arg(long)] - domain_name: Option, - - #[arg( - required = true, - help = r#"DIR points to a directory on a filesystem. When you want to combine -multiple drives into a single large system, pass one directory per -filesystem separated by space. You may also use a '...' convention -to abbreviate the directory arguments. Remote directories in a -distributed setup are encoded as HTTP(s) URIs."# - )] - volumes: Vec, -} - fn setup_tracing() { use tracing_subscriber::EnvFilter; @@ -62,28 +25,8 @@ fn setup_tracing() { .init(); } -fn check_cli_args(opt: &Opt) { - use clap::error::ErrorKind; - - let mut cmd = Opt::command(); - - // TODO: how to specify the requirements with clap derive API? - if let (Some(_), None) | (None, Some(_)) = (&opt.access_key, &opt.secret_key) { - let msg = "access key and secret key must be specified together"; - cmd.error(ErrorKind::MissingRequiredArgument, msg).exit(); - } - - if let Some(ref s) = opt.domain_name { - if s.contains('/') { - let msg = format!("expected domain name, found URL-like string: {s:?}"); - cmd.error(ErrorKind::InvalidValue, msg).exit(); - } - } -} - -fn main() -> Result { - let opt = Opt::parse(); - check_cli_args(&opt); +fn main() -> Result<()> { + let opt = config::Opt::parse(); setup_tracing(); @@ -91,13 +34,10 @@ fn main() -> Result { } #[tokio::main] -async fn run(opt: Opt) -> Result { - // Setup S3 provider - let sto = ECStore::new(opt.volumes)?; - +async fn run(opt: config::Opt) -> Result<()> { // Setup S3 service let service = { - let mut b = S3ServiceBuilder::new(sto); + let mut b = S3ServiceBuilder::new(storage::SimpleFS {}); // Enable authentication if let (Some(ak), Some(sk)) = (opt.access_key, opt.secret_key) { @@ -114,8 +54,7 @@ async fn run(opt: Opt) -> Result { b.build() }; - // Run server - let listener = TcpListener::bind((opt.host.as_str(), opt.port)).await?; + let listener = TcpListener::bind(opt.address).await?; let local_addr = listener.local_addr()?; let hyper_service = service.into_shared(); diff --git a/rustfs/src/storage/mod.rs b/rustfs/src/storage/mod.rs new file mode 100644 index 00000000..30a6d416 --- /dev/null +++ b/rustfs/src/storage/mod.rs @@ -0,0 +1,3 @@ +mod simple_fs; + +pub use simple_fs::SimpleFS; diff --git a/rustfs/src/storage/simple_fs.rs b/rustfs/src/storage/simple_fs.rs new file mode 100644 index 00000000..b8e0a9fd --- /dev/null +++ b/rustfs/src/storage/simple_fs.rs @@ -0,0 +1,6 @@ +use s3s::S3; + +pub struct SimpleFS {} + +#[async_trait::async_trait] +impl S3 for SimpleFS {}