mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 08:36:54 +00:00
mc test ok
This commit is contained in:
@@ -88,6 +88,7 @@ tower-http = { workspace = true, features = [
|
||||
uuid = { workspace = true }
|
||||
rustfs-filemeta.workspace = true
|
||||
thiserror.workspace = true
|
||||
rustfs-rio.workspace = true
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
libsystemd.workspace = true
|
||||
|
||||
@@ -7,7 +7,7 @@ use serde_urlencoded::from_bytes;
|
||||
use tokio::sync::broadcast;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{admin::router::Operation, storage::error::to_s3_error};
|
||||
use crate::{admin::router::Operation, error::ApiError};
|
||||
|
||||
pub struct ListPools {}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl Operation for ListPools {
|
||||
let mut pools_status = Vec::new();
|
||||
|
||||
for (idx, _) in endpoints.as_ref().iter().enumerate() {
|
||||
let state = store.status(idx).await.map_err(to_s3_error)?;
|
||||
let state = store.status(idx).await.map_err(ApiError::from)?;
|
||||
|
||||
pools_status.push(state);
|
||||
}
|
||||
@@ -103,7 +103,7 @@ impl Operation for StatusPool {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
};
|
||||
|
||||
let pools_status = store.status(idx).await.map_err(to_s3_error)?;
|
||||
let pools_status = store.status(idx).await.map_err(ApiError::from)?;
|
||||
|
||||
let data = serde_json::to_vec(&pools_status)
|
||||
.map_err(|_e| S3Error::with_message(S3ErrorCode::InternalError, "parse accountInfo failed"))?;
|
||||
@@ -191,7 +191,7 @@ impl Operation for StartDecommission {
|
||||
}
|
||||
|
||||
if !pools_indices.is_empty() {
|
||||
store.decommission(ctx_rx, pools_indices).await.map_err(to_s3_error)?;
|
||||
store.decommission(ctx_rx, pools_indices).await.map_err(ApiError::from)?;
|
||||
}
|
||||
|
||||
Ok(S3Response::new((StatusCode::OK, Body::default())))
|
||||
@@ -245,7 +245,7 @@ impl Operation for CancelDecommission {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
};
|
||||
|
||||
store.decommission_cancel(idx).await.map_err(to_s3_error)?;
|
||||
store.decommission_cancel(idx).await.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new((StatusCode::OK, Body::default())))
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ pub mod router;
|
||||
mod rpc;
|
||||
pub mod utils;
|
||||
|
||||
use common::error::Result;
|
||||
// use ecstore::global::{is_dist_erasure, is_erasure};
|
||||
use handlers::{
|
||||
group, policys, pools, rebalance,
|
||||
@@ -18,7 +17,7 @@ use s3s::route::S3Route;
|
||||
|
||||
const ADMIN_PREFIX: &str = "/rustfs/admin";
|
||||
|
||||
pub fn make_admin_route() -> Result<impl S3Route> {
|
||||
pub fn make_admin_route() -> std::io::Result<impl S3Route> {
|
||||
let mut r: S3Router<AdminOperation> = S3Router::new();
|
||||
|
||||
// 1
|
||||
@@ -124,7 +123,7 @@ pub fn make_admin_route() -> Result<impl S3Route> {
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn register_user_route(r: &mut S3Router<AdminOperation>) -> Result<()> {
|
||||
fn register_user_route(r: &mut S3Router<AdminOperation>) -> std::io::Result<()> {
|
||||
// 1
|
||||
r.insert(
|
||||
Method::GET,
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
use common::error::Result;
|
||||
use hyper::http::Extensions;
|
||||
use hyper::HeaderMap;
|
||||
use hyper::Method;
|
||||
use hyper::StatusCode;
|
||||
use hyper::Uri;
|
||||
use hyper::http::Extensions;
|
||||
use matchit::Params;
|
||||
use matchit::Router;
|
||||
use s3s::header;
|
||||
use s3s::route::S3Route;
|
||||
use s3s::s3_error;
|
||||
use s3s::Body;
|
||||
use s3s::S3Request;
|
||||
use s3s::S3Response;
|
||||
use s3s::S3Result;
|
||||
use s3s::header;
|
||||
use s3s::route::S3Route;
|
||||
use s3s::s3_error;
|
||||
|
||||
use super::rpc::RPC_PREFIX;
|
||||
use super::ADMIN_PREFIX;
|
||||
use super::rpc::RPC_PREFIX;
|
||||
|
||||
pub struct S3Router<T> {
|
||||
router: Router<T>,
|
||||
@@ -28,12 +27,12 @@ impl<T: Operation> S3Router<T> {
|
||||
Self { router }
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, method: Method, path: &str, operation: T) -> Result<()> {
|
||||
pub fn insert(&mut self, method: Method, path: &str, operation: T) -> std::io::Result<()> {
|
||||
let path = Self::make_route_str(method, path);
|
||||
|
||||
// warn!("set uri {}", &path);
|
||||
|
||||
self.router.insert(path, operation)?;
|
||||
self.router.insert(path, operation).map_err(|e| std::io::Error::other(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ use super::router::AdminOperation;
|
||||
use super::router::Operation;
|
||||
use super::router::S3Router;
|
||||
use crate::storage::ecfs::bytes_stream;
|
||||
use common::error::Result;
|
||||
use ecstore::disk::DiskAPI;
|
||||
use ecstore::io::READ_BUFFER_SIZE;
|
||||
use ecstore::store::find_local_disk;
|
||||
@@ -10,19 +9,19 @@ use futures::TryStreamExt;
|
||||
use http::StatusCode;
|
||||
use hyper::Method;
|
||||
use matchit::Params;
|
||||
use s3s::dto::StreamingBlob;
|
||||
use s3s::s3_error;
|
||||
use s3s::Body;
|
||||
use s3s::S3Request;
|
||||
use s3s::S3Response;
|
||||
use s3s::S3Result;
|
||||
use s3s::dto::StreamingBlob;
|
||||
use s3s::s3_error;
|
||||
use serde_urlencoded::from_bytes;
|
||||
use tokio_util::io::ReaderStream;
|
||||
use tokio_util::io::StreamReader;
|
||||
|
||||
pub const RPC_PREFIX: &str = "/rustfs/rpc";
|
||||
|
||||
pub fn regist_rpc_route(r: &mut S3Router<AdminOperation>) -> Result<()> {
|
||||
pub fn regist_rpc_route(r: &mut S3Router<AdminOperation>) -> std::io::Result<()> {
|
||||
r.insert(
|
||||
Method::GET,
|
||||
format!("{}{}", RPC_PREFIX, "/read_file_stream").as_str(),
|
||||
|
||||
+87
-1675
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,6 +1,6 @@
|
||||
use std::{collections::HashMap, io::Cursor, pin::Pin};
|
||||
|
||||
use common::error::Error as EcsError;
|
||||
// use common::error::Error as EcsError;
|
||||
use ecstore::{
|
||||
admin_server_info::get_local_server_property,
|
||||
bucket::{metadata::load_bucket_metadata, metadata_sys},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use appauth::token::Token;
|
||||
use common::error::{Error, Result};
|
||||
use std::io::{Error, Result};
|
||||
use std::sync::OnceLock;
|
||||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
@@ -37,7 +37,7 @@ pub fn license_check() -> Result<()> {
|
||||
let invalid_license = LICENSE.get().map(|token| {
|
||||
if token.expired < SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() {
|
||||
error!("License expired");
|
||||
return Err(Error::from_string("Incorrect license, please contact RustFS.".to_string()));
|
||||
return Err(Error::other("Incorrect license, please contact RustFS."));
|
||||
}
|
||||
info!("License is valid ! expired at {}", token.expired);
|
||||
Ok(())
|
||||
@@ -46,12 +46,12 @@ pub fn license_check() -> Result<()> {
|
||||
// let invalid_license = config::get_config().license.as_ref().map(|license| {
|
||||
// if license.is_empty() {
|
||||
// error!("License is empty");
|
||||
// return Err(Error::from_string("Incorrect license, please contact RustFS.".to_string()));
|
||||
// return Err(Error::other("Incorrect license, please contact RustFS.".to_string()));
|
||||
// }
|
||||
// let token = appauth::token::parse_license(license)?;
|
||||
// if token.expired < SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() {
|
||||
// error!("License expired");
|
||||
// return Err(Error::from_string("Incorrect license, please contact RustFS.".to_string()));
|
||||
// return Err(Error::other("Incorrect license, please contact RustFS.".to_string()));
|
||||
// }
|
||||
|
||||
// info!("License is valid ! expired at {}", token.expired);
|
||||
@@ -59,7 +59,7 @@ pub fn license_check() -> Result<()> {
|
||||
// });
|
||||
|
||||
if invalid_license.is_none() || invalid_license.is_some_and(|v| v.is_err()) {
|
||||
return Err(Error::from_string("Incorrect license, please contact RustFS.".to_string()));
|
||||
return Err(Error::other("Incorrect license, please contact RustFS."));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+8
-8
@@ -73,7 +73,7 @@ const MI_B: usize = 1024 * 1024;
|
||||
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
||||
|
||||
#[allow(clippy::result_large_err)]
|
||||
fn check_auth(req: Request<()>) -> Result<Request<()>, Status> {
|
||||
fn check_auth(req: Request<()>) -> std::result::Result<Request<()>, Status> {
|
||||
let token: MetadataValue<_> = "rustfs rpc".parse().unwrap();
|
||||
|
||||
match req.metadata().get("authorization") {
|
||||
@@ -120,7 +120,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
// Initialize event notifier
|
||||
event::init_event_notifier(opt.event_config).await;
|
||||
|
||||
let server_addr = net::parse_and_resolve_address(opt.address.as_str())?;
|
||||
let server_addr = net::parse_and_resolve_address(opt.address.as_str()).map_err(|err| Error::other(err))?;
|
||||
let server_port = server_addr.port();
|
||||
let server_address = server_addr.to_string();
|
||||
|
||||
@@ -140,7 +140,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
|
||||
// For RPC
|
||||
let (endpoint_pools, setup_type) = EndpointServerPools::from_volumes(server_address.clone().as_str(), opt.volumes.clone())
|
||||
.map_err(|err| Error::from_string(err.to_string()))?;
|
||||
.map_err(|err| Error::other(err.to_string()))?;
|
||||
|
||||
// Print RustFS-style logging for pool formatting
|
||||
for (i, eps) in endpoint_pools.as_ref().iter().enumerate() {
|
||||
@@ -189,7 +189,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
// Initialize the local disk
|
||||
init_local_disks(endpoint_pools.clone())
|
||||
.await
|
||||
.map_err(|err| Error::from_string(err.to_string()))?;
|
||||
.map_err(|err| Error::other(err))?;
|
||||
|
||||
// Setup S3 service
|
||||
// This project uses the S3S library to implement S3 services
|
||||
@@ -518,7 +518,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.map_err(|err| Error::from_string(err.to_string()))?;
|
||||
.map_err(|err| Error::other(err))?;
|
||||
|
||||
let buckets = buckets_list.into_iter().map(|v| v.name).collect();
|
||||
|
||||
@@ -528,7 +528,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
|
||||
new_global_notification_sys(endpoint_pools.clone()).await.map_err(|err| {
|
||||
error!("new_global_notification_sys failed {:?}", &err);
|
||||
Error::from_string(err.to_string())
|
||||
Error::other(err)
|
||||
})?;
|
||||
|
||||
// init scanner
|
||||
@@ -549,7 +549,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
|
||||
if console_address.is_empty() {
|
||||
error!("console_address is empty");
|
||||
return Err(Error::from_string("console_address is empty".to_string()));
|
||||
return Err(Error::other("console_address is empty".to_string()));
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
@@ -571,7 +571,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
// stop event notifier
|
||||
rustfs_event_notifier::shutdown().await.map_err(|err| {
|
||||
error!("Failed to shut down the notification system: {}", err);
|
||||
Error::from_string(err.to_string())
|
||||
Error::other(err)
|
||||
})?;
|
||||
}
|
||||
|
||||
|
||||
+111
-105
@@ -3,8 +3,9 @@ use super::options::del_opts;
|
||||
use super::options::extract_metadata;
|
||||
use super::options::put_opts;
|
||||
use crate::auth::get_condition_values;
|
||||
use crate::error::ApiError;
|
||||
use crate::error::Result;
|
||||
use crate::storage::access::ReqInfo;
|
||||
use crate::storage::error::to_s3_error;
|
||||
use crate::storage::options::copy_dst_opts;
|
||||
use crate::storage::options::copy_src_opts;
|
||||
use crate::storage::options::{extract_metadata_from_mime, get_opts};
|
||||
@@ -12,11 +13,9 @@ use api::query::Context;
|
||||
use api::query::Query;
|
||||
use api::server::dbms::DatabaseManagerSystem;
|
||||
use bytes::Bytes;
|
||||
use common::error::Result;
|
||||
use datafusion::arrow::csv::WriterBuilder as CsvWriterBuilder;
|
||||
use datafusion::arrow::json::writer::JsonArray;
|
||||
use datafusion::arrow::json::WriterBuilder as JsonWriterBuilder;
|
||||
use ecstore::bucket::error::BucketMetadataError;
|
||||
use datafusion::arrow::json::writer::JsonArray;
|
||||
use ecstore::bucket::metadata::BUCKET_LIFECYCLE_CONFIG;
|
||||
use ecstore::bucket::metadata::BUCKET_NOTIFICATION_CONFIG;
|
||||
use ecstore::bucket::metadata::BUCKET_POLICY_CONFIG;
|
||||
@@ -30,6 +29,7 @@ use ecstore::bucket::policy_sys::PolicySys;
|
||||
use ecstore::bucket::tagging::decode_tags;
|
||||
use ecstore::bucket::tagging::encode_tags;
|
||||
use ecstore::bucket::versioning_sys::BucketVersioningSys;
|
||||
use ecstore::error::StorageError;
|
||||
use ecstore::io::READ_BUFFER_SIZE;
|
||||
use ecstore::new_object_layer_fn;
|
||||
use ecstore::store_api::BucketOptions;
|
||||
@@ -42,8 +42,8 @@ use ecstore::store_api::ObjectIO;
|
||||
use ecstore::store_api::ObjectOptions;
|
||||
use ecstore::store_api::ObjectToDelete;
|
||||
use ecstore::store_api::PutObjReader;
|
||||
use ecstore::store_api::StorageAPI;
|
||||
use ecstore::store_api::RESERVED_METADATA_PREFIX_LOWER;
|
||||
use ecstore::store_api::StorageAPI;
|
||||
use ecstore::utils::path::path_join_buf;
|
||||
use ecstore::utils::xml;
|
||||
use ecstore::xhttp;
|
||||
@@ -52,27 +52,28 @@ use futures::{Stream, StreamExt};
|
||||
use http::HeaderMap;
|
||||
use lazy_static::lazy_static;
|
||||
use policy::auth;
|
||||
use policy::policy::action::Action;
|
||||
use policy::policy::action::S3Action;
|
||||
use policy::policy::BucketPolicy;
|
||||
use policy::policy::BucketPolicyArgs;
|
||||
use policy::policy::Validator;
|
||||
use policy::policy::action::Action;
|
||||
use policy::policy::action::S3Action;
|
||||
use query::instance::make_rustfsms;
|
||||
use rustfs_rio::HashReader;
|
||||
use rustfs_zip::CompressionFormat;
|
||||
use s3s::dto::*;
|
||||
use s3s::s3_error;
|
||||
use s3s::S3;
|
||||
use s3s::S3Error;
|
||||
use s3s::S3ErrorCode;
|
||||
use s3s::S3Result;
|
||||
use s3s::S3;
|
||||
use s3s::dto::*;
|
||||
use s3s::s3_error;
|
||||
use s3s::{S3Request, S3Response};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use time::format_description::well_known::Rfc3339;
|
||||
use time::OffsetDateTime;
|
||||
use time::format_description::well_known::Rfc3339;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_stream::wrappers::ReceiverStream;
|
||||
use tokio_tar::Archive;
|
||||
@@ -175,12 +176,15 @@ impl FS {
|
||||
|
||||
println!("Extracted: {}, size {}", fpath, size);
|
||||
|
||||
let mut reader = PutObjReader::new(Box::new(f), size);
|
||||
// Wrap the tar entry with BufReader to make it compatible with Reader trait
|
||||
let reader = Box::new(tokio::io::BufReader::new(f));
|
||||
let hrd = HashReader::new(reader, size as i64, size as i64, None, false).map_err(ApiError::from)?;
|
||||
let mut reader = PutObjReader::new(hrd, size);
|
||||
|
||||
let _obj_info = store
|
||||
.put_object(&bucket, &fpath, &mut reader, &ObjectOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// let e_tag = obj_info.etag;
|
||||
|
||||
@@ -244,7 +248,7 @@ impl S3 for FS {
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let output = CreateBucketOutput::default();
|
||||
Ok(S3Response::new(output))
|
||||
@@ -270,7 +274,7 @@ impl S3 for FS {
|
||||
|
||||
// warn!("copy_object {}/{}, to {}/{}", &src_bucket, &src_key, &bucket, &key);
|
||||
|
||||
let mut src_opts = copy_src_opts(&src_bucket, &src_key, &req.headers).map_err(to_s3_error)?;
|
||||
let mut src_opts = copy_src_opts(&src_bucket, &src_key, &req.headers).map_err(ApiError::from)?;
|
||||
|
||||
src_opts.version_id = version_id.clone();
|
||||
|
||||
@@ -283,7 +287,7 @@ impl S3 for FS {
|
||||
|
||||
let dst_opts = copy_dst_opts(&bucket, &key, version_id, &req.headers, None)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let cp_src_dst_same = path_join_buf(&[&src_bucket, &src_key]) == path_join_buf(&[&bucket, &key]);
|
||||
|
||||
@@ -300,7 +304,7 @@ impl S3 for FS {
|
||||
let gr = store
|
||||
.get_object_reader(&src_bucket, &src_key, None, h, &get_opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let mut src_info = gr.object_info.clone();
|
||||
|
||||
@@ -308,8 +312,11 @@ impl S3 for FS {
|
||||
src_info.metadata_only = true;
|
||||
}
|
||||
|
||||
let hrd = HashReader::new(gr.stream, gr.object_info.size as i64, gr.object_info.size as i64, None, false)
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
src_info.put_object_reader = Some(PutObjReader {
|
||||
stream: gr.stream,
|
||||
stream: hrd,
|
||||
content_length: gr.object_info.size as usize,
|
||||
});
|
||||
|
||||
@@ -320,7 +327,7 @@ impl S3 for FS {
|
||||
let oi = store
|
||||
.copy_object(&src_bucket, &src_key, &bucket, &key, &mut src_info, &src_opts, &dst_opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// warn!("copy_object oi {:?}", &oi);
|
||||
|
||||
@@ -355,7 +362,7 @@ impl S3 for FS {
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(DeleteBucketOutput {}))
|
||||
}
|
||||
@@ -371,7 +378,7 @@ impl S3 for FS {
|
||||
|
||||
let opts: ObjectOptions = del_opts(&bucket, &key, version_id, &req.headers, Some(metadata))
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let version_id = opts.version_id.as_ref().map(|v| Uuid::parse_str(v).ok()).unwrap_or_default();
|
||||
let dobj = ObjectToDelete {
|
||||
@@ -384,7 +391,7 @@ impl S3 for FS {
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
};
|
||||
let (dobjs, _errs) = store.delete_objects(&bucket, objects, opts).await.map_err(to_s3_error)?;
|
||||
let (dobjs, _errs) = store.delete_objects(&bucket, objects, opts).await.map_err(ApiError::from)?;
|
||||
|
||||
// TODO: let errors;
|
||||
|
||||
@@ -392,13 +399,7 @@ impl S3 for FS {
|
||||
if let Some((a, b)) = dobjs
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let delete_marker = {
|
||||
if v.delete_marker {
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
let delete_marker = { if v.delete_marker { Some(true) } else { None } };
|
||||
|
||||
let version_id = v.version_id.clone();
|
||||
|
||||
@@ -447,20 +448,14 @@ impl S3 for FS {
|
||||
|
||||
let opts: ObjectOptions = del_opts(&bucket, "", None, &req.headers, Some(metadata))
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let (dobjs, errs) = store.delete_objects(&bucket, objects, opts).await.map_err(to_s3_error)?;
|
||||
let (dobjs, errs) = store.delete_objects(&bucket, objects, opts).await.map_err(ApiError::from)?;
|
||||
|
||||
let deleted = dobjs
|
||||
.iter()
|
||||
.map(|v| DeletedObject {
|
||||
delete_marker: {
|
||||
if v.delete_marker {
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
delete_marker: { if v.delete_marker { Some(true) } else { None } },
|
||||
delete_marker_version_id: v.delete_marker_version_id.clone(),
|
||||
key: Some(v.object_name.clone()),
|
||||
version_id: v.version_id.clone(),
|
||||
@@ -493,7 +488,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&input.bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let output = GetBucketLocationOutput::default();
|
||||
Ok(S3Response::new(output))
|
||||
@@ -550,7 +545,7 @@ impl S3 for FS {
|
||||
|
||||
let opts: ObjectOptions = get_opts(&bucket, &key, version_id, part_number, &req.headers)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
@@ -559,7 +554,7 @@ impl S3 for FS {
|
||||
let reader = store
|
||||
.get_object_reader(bucket.as_str(), key.as_str(), rs, h, &opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let info = reader.object_info;
|
||||
|
||||
@@ -606,7 +601,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&input.bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
// mc cp step 2 GetBucketInfo
|
||||
|
||||
Ok(S3Response::new(HeadBucketOutput::default()))
|
||||
@@ -651,13 +646,13 @@ impl S3 for FS {
|
||||
|
||||
let opts: ObjectOptions = get_opts(&bucket, &key, version_id, part_number, &req.headers)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
};
|
||||
|
||||
let info = store.get_object_info(&bucket, &key, &opts).await.map_err(to_s3_error)?;
|
||||
let info = store.get_object_info(&bucket, &key, &opts).await.map_err(ApiError::from)?;
|
||||
|
||||
// warn!("head_object info {:?}", &info);
|
||||
|
||||
@@ -700,7 +695,7 @@ impl S3 for FS {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
};
|
||||
|
||||
let mut bucket_infos = store.list_bucket(&BucketOptions::default()).await.map_err(to_s3_error)?;
|
||||
let mut bucket_infos = store.list_bucket(&BucketOptions::default()).await.map_err(ApiError::from)?;
|
||||
|
||||
let mut req = req;
|
||||
|
||||
@@ -792,7 +787,7 @@ impl S3 for FS {
|
||||
start_after,
|
||||
)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// warn!("object_infos objects {:?}", object_infos.objects);
|
||||
|
||||
@@ -873,7 +868,7 @@ impl S3 for FS {
|
||||
let object_infos = store
|
||||
.list_object_versions(&bucket, &prefix, key_marker, version_id_marker, delimiter.clone(), max_keys)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let objects: Vec<ObjectVersion> = object_infos
|
||||
.objects
|
||||
@@ -960,9 +955,14 @@ impl S3 for FS {
|
||||
}
|
||||
};
|
||||
|
||||
let body = Box::new(StreamReader::new(body.map(|f| f.map_err(|e| std::io::Error::other(e.to_string())))));
|
||||
let body = StreamReader::new(body.map(|f| f.map_err(|e| std::io::Error::other(e.to_string()))));
|
||||
let body = Box::new(tokio::io::BufReader::new(body));
|
||||
let hrd = HashReader::new(body, content_length as i64, content_length as i64, None, false).map_err(ApiError::from)?;
|
||||
let mut reader = PutObjReader::new(hrd, content_length as usize);
|
||||
|
||||
let mut reader = PutObjReader::new(body, content_length as usize);
|
||||
// let body = Box::new(StreamReader::new(body.map(|f| f.map_err(|e| std::io::Error::other(e.to_string())))));
|
||||
|
||||
// let mut reader = PutObjReader::new(body, content_length as usize);
|
||||
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||
@@ -978,14 +978,14 @@ impl S3 for FS {
|
||||
|
||||
let opts: ObjectOptions = put_opts(&bucket, &key, version_id, &req.headers, Some(metadata))
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
debug!("put_object opts {:?}", &opts);
|
||||
|
||||
let obj_info = store
|
||||
.put_object(&bucket, &key, &mut reader, &opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let e_tag = obj_info.etag;
|
||||
|
||||
@@ -1027,10 +1027,12 @@ impl S3 for FS {
|
||||
|
||||
let opts: ObjectOptions = put_opts(&bucket, &key, version_id, &req.headers, Some(metadata))
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let MultipartUploadResult { upload_id, .. } =
|
||||
store.new_multipart_upload(&bucket, &key, &opts).await.map_err(to_s3_error)?;
|
||||
let MultipartUploadResult { upload_id, .. } = store
|
||||
.new_multipart_upload(&bucket, &key, &opts)
|
||||
.await
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let output = CreateMultipartUploadOutput {
|
||||
bucket: Some(bucket),
|
||||
@@ -1074,10 +1076,12 @@ impl S3 for FS {
|
||||
}
|
||||
};
|
||||
|
||||
let body = Box::new(StreamReader::new(body.map(|f| f.map_err(|e| std::io::Error::other(e.to_string())))));
|
||||
let body = StreamReader::new(body.map(|f| f.map_err(|e| std::io::Error::other(e.to_string()))));
|
||||
let body = Box::new(tokio::io::BufReader::new(body));
|
||||
let hrd = HashReader::new(body, content_length as i64, content_length as i64, None, false).map_err(ApiError::from)?;
|
||||
|
||||
// mc cp step 4
|
||||
let mut data = PutObjReader::new(body, content_length as usize);
|
||||
let mut data = PutObjReader::new(hrd, content_length as usize);
|
||||
let opts = ObjectOptions::default();
|
||||
|
||||
let Some(store) = new_object_layer_fn() else {
|
||||
@@ -1089,7 +1093,7 @@ impl S3 for FS {
|
||||
let info = store
|
||||
.put_object_part(&bucket, &key, &upload_id, part_id, &mut data, &opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let output = UploadPartOutput {
|
||||
e_tag: info.etag,
|
||||
@@ -1155,7 +1159,7 @@ impl S3 for FS {
|
||||
let oi = store
|
||||
.complete_multipart_upload(&bucket, &key, &upload_id, uploaded_parts, opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let output = CompleteMultipartUploadOutput {
|
||||
bucket: Some(bucket),
|
||||
@@ -1184,7 +1188,7 @@ impl S3 for FS {
|
||||
store
|
||||
.abort_multipart_upload(bucket.as_str(), key.as_str(), upload_id.as_str(), opts)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
Ok(S3Response::new(AbortMultipartUploadOutput { ..Default::default() }))
|
||||
}
|
||||
|
||||
@@ -1222,13 +1226,13 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let data = try_!(xml::serialize(&tagging));
|
||||
|
||||
metadata_sys::update(&bucket, BUCKET_TAGGING_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(Default::default()))
|
||||
}
|
||||
@@ -1242,7 +1246,7 @@ impl S3 for FS {
|
||||
|
||||
metadata_sys::delete(&bucket, BUCKET_TAGGING_CONFIG)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(DeleteBucketTaggingOutput {}))
|
||||
}
|
||||
@@ -1268,7 +1272,7 @@ impl S3 for FS {
|
||||
store
|
||||
.put_object_tags(&bucket, &object, &tags, &ObjectOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(PutObjectTaggingOutput { version_id: None }))
|
||||
}
|
||||
@@ -1285,7 +1289,7 @@ impl S3 for FS {
|
||||
let tags = store
|
||||
.get_object_tags(&bucket, &object, &ObjectOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let tag_set = decode_tags(tags.as_str());
|
||||
|
||||
@@ -1311,7 +1315,7 @@ impl S3 for FS {
|
||||
store
|
||||
.delete_object_tags(&bucket, &object, &ObjectOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(DeleteObjectTaggingOutput { version_id: None }))
|
||||
}
|
||||
@@ -1329,9 +1333,9 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let VersioningConfiguration { status, .. } = BucketVersioningSys::get(&bucket).await.map_err(to_s3_error)?;
|
||||
let VersioningConfiguration { status, .. } = BucketVersioningSys::get(&bucket).await.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(GetBucketVersioningOutput {
|
||||
status,
|
||||
@@ -1359,7 +1363,7 @@ impl S3 for FS {
|
||||
|
||||
metadata_sys::update(&bucket, BUCKET_VERSIONING_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// TODO: globalSiteReplicationSys.BucketMetaHook
|
||||
|
||||
@@ -1379,7 +1383,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let conditions = get_condition_values(&req.headers, &auth::Credentials::default());
|
||||
|
||||
@@ -1426,15 +1430,15 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let cfg = match PolicySys::get(&bucket).await {
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
if BucketMetadataError::BucketPolicyNotFound.is(&err) {
|
||||
if StorageError::BucketPolicyNotFound == err {
|
||||
return Err(s3_error!(NoSuchBucketPolicy));
|
||||
}
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, format!("{}", err)));
|
||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, err.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1453,7 +1457,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// warn!("input policy {}", &policy);
|
||||
|
||||
@@ -1469,7 +1473,7 @@ impl S3 for FS {
|
||||
|
||||
metadata_sys::update(&bucket, BUCKET_POLICY_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(PutBucketPolicyOutput {}))
|
||||
}
|
||||
@@ -1487,11 +1491,11 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
metadata_sys::delete(&bucket, BUCKET_POLICY_CONFIG)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(DeleteBucketPolicyOutput {}))
|
||||
}
|
||||
@@ -1510,7 +1514,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let rules = match metadata_sys::get_lifecycle_config(&bucket).await {
|
||||
Ok((cfg, _)) => Some(cfg.rules),
|
||||
@@ -1549,7 +1553,7 @@ impl S3 for FS {
|
||||
let data = try_!(xml::serialize(&input_cfg));
|
||||
metadata_sys::update(&bucket, BUCKET_LIFECYCLE_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(PutBucketLifecycleConfigurationOutput::default()))
|
||||
}
|
||||
@@ -1568,11 +1572,11 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
metadata_sys::delete(&bucket, BUCKET_LIFECYCLE_CONFIG)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(DeleteBucketLifecycleOutput::default()))
|
||||
}
|
||||
@@ -1590,7 +1594,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let server_side_encryption_configuration = match metadata_sys::get_sse_config(&bucket).await {
|
||||
Ok((cfg, _)) => Some(cfg),
|
||||
@@ -1627,14 +1631,14 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// TODO: check kms
|
||||
|
||||
let data = try_!(xml::serialize(&server_side_encryption_configuration));
|
||||
metadata_sys::update(&bucket, BUCKET_SSECONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
Ok(S3Response::new(PutBucketEncryptionOutput::default()))
|
||||
}
|
||||
|
||||
@@ -1651,8 +1655,10 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
metadata_sys::delete(&bucket, BUCKET_SSECONFIG).await.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
metadata_sys::delete(&bucket, BUCKET_SSECONFIG)
|
||||
.await
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(DeleteBucketEncryptionOutput::default()))
|
||||
}
|
||||
@@ -1699,13 +1705,13 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let data = try_!(xml::serialize(&input_cfg));
|
||||
|
||||
metadata_sys::update(&bucket, OBJECT_LOCK_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(PutObjectLockConfigurationOutput::default()))
|
||||
}
|
||||
@@ -1723,7 +1729,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let replication_configuration = match metadata_sys::get_replication_config(&bucket).await {
|
||||
Ok((cfg, _created)) => Some(cfg),
|
||||
@@ -1755,14 +1761,14 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// TODO: check enable, versioning enable
|
||||
let data = try_!(xml::serialize(&replication_configuration));
|
||||
|
||||
metadata_sys::update(&bucket, BUCKET_REPLICATION_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
Ok(S3Response::new(PutBucketReplicationOutput::default()))
|
||||
}
|
||||
@@ -1780,10 +1786,10 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
metadata_sys::delete(&bucket, BUCKET_REPLICATION_CONFIG)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// TODO: remove targets
|
||||
|
||||
@@ -1803,7 +1809,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let has_notification_config = match metadata_sys::get_notification_config(&bucket).await {
|
||||
Ok(cfg) => cfg,
|
||||
@@ -1850,13 +1856,13 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let data = try_!(xml::serialize(¬ification_configuration));
|
||||
|
||||
metadata_sys::update(&bucket, BUCKET_NOTIFICATION_CONFIG, data)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// TODO: event notice add rule
|
||||
|
||||
@@ -1873,7 +1879,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let grants = vec![Grant {
|
||||
grantee: Some(Grantee {
|
||||
@@ -1909,7 +1915,7 @@ impl S3 for FS {
|
||||
store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
if let Some(canned_acl) = acl {
|
||||
if canned_acl.as_str() != BucketCannedACL::PRIVATE {
|
||||
@@ -2085,14 +2091,14 @@ impl S3 for FS {
|
||||
let _ = store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// check object lock
|
||||
let _ = metadata_sys::get_object_lock_config(&bucket).await.map_err(to_s3_error)?;
|
||||
let _ = metadata_sys::get_object_lock_config(&bucket).await.map_err(ApiError::from)?;
|
||||
|
||||
let opts: ObjectOptions = get_opts(&bucket, &key, version_id, None, &req.headers)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let object_info = store.get_object_info(&bucket, &key, &opts).await.map_err(|e| {
|
||||
error!("get_object_info failed, {}", e.to_string());
|
||||
@@ -2135,14 +2141,14 @@ impl S3 for FS {
|
||||
let _ = store
|
||||
.get_bucket_info(&bucket, &BucketOptions::default())
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
// check object lock
|
||||
let _ = metadata_sys::get_object_lock_config(&bucket).await.map_err(to_s3_error)?;
|
||||
let _ = metadata_sys::get_object_lock_config(&bucket).await.map_err(ApiError::from)?;
|
||||
|
||||
let opts: ObjectOptions = get_opts(&bucket, &key, version_id, None, &req.headers)
|
||||
.await
|
||||
.map_err(to_s3_error)?;
|
||||
.map_err(ApiError::from)?;
|
||||
|
||||
let mut eval_metadata = HashMap::new();
|
||||
let legal_hold = legal_hold
|
||||
@@ -2176,9 +2182,9 @@ impl S3 for FS {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn bytes_stream<S, E>(stream: S, content_length: usize) -> impl Stream<Item = Result<Bytes, E>> + Send + 'static
|
||||
pub fn bytes_stream<S, E>(stream: S, content_length: usize) -> impl Stream<Item = std::result::Result<Bytes, E>> + Send + 'static
|
||||
where
|
||||
S: Stream<Item = Result<Bytes, E>> + Send + 'static,
|
||||
S: Stream<Item = std::result::Result<Bytes, E>> + Send + 'static,
|
||||
E: Send + 'static,
|
||||
{
|
||||
AsyncTryStream::<Bytes, E, _>::new(|mut y| async move {
|
||||
|
||||
+485
-485
@@ -1,485 +1,485 @@
|
||||
use common::error::Error;
|
||||
use ecstore::error::StorageError;
|
||||
use s3s::{S3Error, S3ErrorCode, s3_error};
|
||||
pub fn to_s3_error(err: Error) -> S3Error {
|
||||
if let Some(storage_err) = err.downcast_ref::<StorageError>() {
|
||||
return match storage_err {
|
||||
StorageError::NotImplemented => s3_error!(NotImplemented),
|
||||
StorageError::InvalidArgument(bucket, object, version_id) => {
|
||||
s3_error!(InvalidArgument, "Invalid arguments provided for {}/{}-{}", bucket, object, version_id)
|
||||
}
|
||||
StorageError::MethodNotAllowed => s3_error!(MethodNotAllowed),
|
||||
StorageError::BucketNotFound(bucket) => {
|
||||
s3_error!(NoSuchBucket, "bucket not found {}", bucket)
|
||||
}
|
||||
StorageError::BucketNotEmpty(bucket) => s3_error!(BucketNotEmpty, "bucket not empty {}", bucket),
|
||||
StorageError::BucketNameInvalid(bucket) => s3_error!(InvalidBucketName, "invalid bucket name {}", bucket),
|
||||
StorageError::ObjectNameInvalid(bucket, object) => {
|
||||
s3_error!(InvalidArgument, "invalid object name {}/{}", bucket, object)
|
||||
}
|
||||
StorageError::BucketExists(bucket) => s3_error!(BucketAlreadyExists, "{}", bucket),
|
||||
StorageError::StorageFull => s3_error!(ServiceUnavailable, "Storage reached its minimum free drive threshold."),
|
||||
StorageError::SlowDown => s3_error!(SlowDown, "Please reduce your request rate"),
|
||||
StorageError::PrefixAccessDenied(bucket, object) => {
|
||||
s3_error!(AccessDenied, "PrefixAccessDenied {}/{}", bucket, object)
|
||||
}
|
||||
StorageError::InvalidUploadIDKeyCombination(bucket, object) => {
|
||||
s3_error!(InvalidArgument, "Invalid UploadID KeyCombination: {}/{}", bucket, object)
|
||||
}
|
||||
StorageError::MalformedUploadID(bucket) => s3_error!(InvalidArgument, "Malformed UploadID: {}", bucket),
|
||||
StorageError::ObjectNameTooLong(bucket, object) => {
|
||||
s3_error!(InvalidArgument, "Object name too long: {}/{}", bucket, object)
|
||||
}
|
||||
StorageError::ObjectNamePrefixAsSlash(bucket, object) => {
|
||||
s3_error!(InvalidArgument, "Object name contains forward slash as prefix: {}/{}", bucket, object)
|
||||
}
|
||||
StorageError::ObjectNotFound(bucket, object) => s3_error!(NoSuchKey, "{}/{}", bucket, object),
|
||||
StorageError::VersionNotFound(bucket, object, version_id) => {
|
||||
s3_error!(NoSuchVersion, "{}/{}/{}", bucket, object, version_id)
|
||||
}
|
||||
StorageError::InvalidUploadID(bucket, object, version_id) => {
|
||||
s3_error!(InvalidPart, "Invalid upload id: {}/{}-{}", bucket, object, version_id)
|
||||
}
|
||||
StorageError::InvalidVersionID(bucket, object, version_id) => {
|
||||
s3_error!(InvalidArgument, "Invalid version id: {}/{}-{}", bucket, object, version_id)
|
||||
}
|
||||
// extended
|
||||
StorageError::DataMovementOverwriteErr(bucket, object, version_id) => s3_error!(
|
||||
InvalidArgument,
|
||||
"invalid data movement operation, source and destination pool are the same for : {}/{}-{}",
|
||||
bucket,
|
||||
object,
|
||||
version_id
|
||||
),
|
||||
|
||||
// extended
|
||||
StorageError::ObjectExistsAsDirectory(bucket, object) => {
|
||||
s3_error!(InvalidArgument, "Object exists on :{} as directory {}", bucket, object)
|
||||
}
|
||||
StorageError::InvalidPart(bucket, object, version_id) => {
|
||||
s3_error!(
|
||||
InvalidPart,
|
||||
"Specified part could not be found. PartNumber {}, Expected {}, got {}",
|
||||
bucket,
|
||||
object,
|
||||
version_id
|
||||
)
|
||||
}
|
||||
StorageError::DoneForNow => s3_error!(InternalError, "DoneForNow"),
|
||||
};
|
||||
}
|
||||
|
||||
if is_err_file_not_found(&err) {
|
||||
return S3Error::with_message(S3ErrorCode::NoSuchKey, format!(" ec err {}", err));
|
||||
}
|
||||
|
||||
S3Error::with_message(S3ErrorCode::InternalError, format!(" ec err {}", err))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use s3s::S3ErrorCode;
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_not_implemented() {
|
||||
let storage_err = StorageError::NotImplemented;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NotImplemented);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_invalid_argument() {
|
||||
let storage_err =
|
||||
StorageError::InvalidArgument("test-bucket".to_string(), "test-object".to_string(), "test-version".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Invalid arguments provided"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
assert!(s3_err.message().unwrap().contains("test-version"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_method_not_allowed() {
|
||||
let storage_err = StorageError::MethodNotAllowed;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::MethodNotAllowed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_bucket_not_found() {
|
||||
let storage_err = StorageError::BucketNotFound("test-bucket".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_bucket_not_empty() {
|
||||
let storage_err = StorageError::BucketNotEmpty("test-bucket".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::BucketNotEmpty);
|
||||
assert!(s3_err.message().unwrap().contains("bucket not empty"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_bucket_name_invalid() {
|
||||
let storage_err = StorageError::BucketNameInvalid("invalid-bucket-name".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidBucketName);
|
||||
assert!(s3_err.message().unwrap().contains("invalid bucket name"));
|
||||
assert!(s3_err.message().unwrap().contains("invalid-bucket-name"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_object_name_invalid() {
|
||||
let storage_err = StorageError::ObjectNameInvalid("test-bucket".to_string(), "invalid-object".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("invalid object name"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("invalid-object"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_bucket_exists() {
|
||||
let storage_err = StorageError::BucketExists("existing-bucket".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::BucketAlreadyExists);
|
||||
assert!(s3_err.message().unwrap().contains("existing-bucket"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_storage_full() {
|
||||
let storage_err = StorageError::StorageFull;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::ServiceUnavailable);
|
||||
assert!(
|
||||
s3_err
|
||||
.message()
|
||||
.unwrap()
|
||||
.contains("Storage reached its minimum free drive threshold")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_slow_down() {
|
||||
let storage_err = StorageError::SlowDown;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::SlowDown);
|
||||
assert!(s3_err.message().unwrap().contains("Please reduce your request rate"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_prefix_access_denied() {
|
||||
let storage_err = StorageError::PrefixAccessDenied("test-bucket".to_string(), "test-prefix".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::AccessDenied);
|
||||
assert!(s3_err.message().unwrap().contains("PrefixAccessDenied"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-prefix"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_invalid_upload_id_key_combination() {
|
||||
let storage_err = StorageError::InvalidUploadIDKeyCombination("test-bucket".to_string(), "test-object".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Invalid UploadID KeyCombination"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_malformed_upload_id() {
|
||||
let storage_err = StorageError::MalformedUploadID("malformed-id".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Malformed UploadID"));
|
||||
assert!(s3_err.message().unwrap().contains("malformed-id"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_object_name_too_long() {
|
||||
let storage_err = StorageError::ObjectNameTooLong("test-bucket".to_string(), "very-long-object-name".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Object name too long"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("very-long-object-name"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_object_name_prefix_as_slash() {
|
||||
let storage_err = StorageError::ObjectNamePrefixAsSlash("test-bucket".to_string(), "/invalid-object".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(
|
||||
s3_err
|
||||
.message()
|
||||
.unwrap()
|
||||
.contains("Object name contains forward slash as prefix")
|
||||
);
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("/invalid-object"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_object_not_found() {
|
||||
let storage_err = StorageError::ObjectNotFound("test-bucket".to_string(), "missing-object".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchKey);
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("missing-object"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_version_not_found() {
|
||||
let storage_err =
|
||||
StorageError::VersionNotFound("test-bucket".to_string(), "test-object".to_string(), "missing-version".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchVersion);
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
assert!(s3_err.message().unwrap().contains("missing-version"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_invalid_upload_id() {
|
||||
let storage_err =
|
||||
StorageError::InvalidUploadID("test-bucket".to_string(), "test-object".to_string(), "invalid-upload-id".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidPart);
|
||||
assert!(s3_err.message().unwrap().contains("Invalid upload id"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
assert!(s3_err.message().unwrap().contains("invalid-upload-id"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_invalid_version_id() {
|
||||
let storage_err = StorageError::InvalidVersionID(
|
||||
"test-bucket".to_string(),
|
||||
"test-object".to_string(),
|
||||
"invalid-version-id".to_string(),
|
||||
);
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Invalid version id"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
assert!(s3_err.message().unwrap().contains("invalid-version-id"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_data_movement_overwrite_err() {
|
||||
let storage_err = StorageError::DataMovementOverwriteErr(
|
||||
"test-bucket".to_string(),
|
||||
"test-object".to_string(),
|
||||
"test-version".to_string(),
|
||||
);
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("invalid data movement operation"));
|
||||
assert!(s3_err.message().unwrap().contains("source and destination pool are the same"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
assert!(s3_err.message().unwrap().contains("test-version"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_object_exists_as_directory() {
|
||||
let storage_err = StorageError::ObjectExistsAsDirectory("test-bucket".to_string(), "directory-object".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Object exists on"));
|
||||
assert!(s3_err.message().unwrap().contains("as directory"));
|
||||
assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
assert!(s3_err.message().unwrap().contains("directory-object"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_insufficient_read_quorum() {
|
||||
let storage_err = StorageError::InsufficientReadQuorum;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::SlowDown);
|
||||
assert!(
|
||||
s3_err
|
||||
.message()
|
||||
.unwrap()
|
||||
.contains("Storage resources are insufficient for the read operation")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_insufficient_write_quorum() {
|
||||
let storage_err = StorageError::InsufficientWriteQuorum;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::SlowDown);
|
||||
assert!(
|
||||
s3_err
|
||||
.message()
|
||||
.unwrap()
|
||||
.contains("Storage resources are insufficient for the write operation")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_decommission_not_started() {
|
||||
let storage_err = StorageError::DecommissionNotStarted;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("Decommission Not Started"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_decommission_already_running() {
|
||||
let storage_err = StorageError::DecommissionAlreadyRunning;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InternalError);
|
||||
assert!(s3_err.message().unwrap().contains("Decommission already running"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_volume_not_found() {
|
||||
let storage_err = StorageError::VolumeNotFound("test-volume".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
assert!(s3_err.message().unwrap().contains("test-volume"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_invalid_part() {
|
||||
let storage_err = StorageError::InvalidPart(1, "expected-part".to_string(), "got-part".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidPart);
|
||||
assert!(s3_err.message().unwrap().contains("Specified part could not be found"));
|
||||
assert!(s3_err.message().unwrap().contains("PartNumber"));
|
||||
assert!(s3_err.message().unwrap().contains("expected-part"));
|
||||
assert!(s3_err.message().unwrap().contains("got-part"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_done_for_now() {
|
||||
let storage_err = StorageError::DoneForNow;
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InternalError);
|
||||
assert!(s3_err.message().unwrap().contains("DoneForNow"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_non_storage_error() {
|
||||
// Test with a non-StorageError
|
||||
let err = Error::from_string("Generic error message".to_string());
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InternalError);
|
||||
assert!(s3_err.message().unwrap().contains("ec err"));
|
||||
assert!(s3_err.message().unwrap().contains("Generic error message"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_with_unicode_strings() {
|
||||
let storage_err = StorageError::BucketNotFound("测试桶".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
assert!(s3_err.message().unwrap().contains("测试桶"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_with_special_characters() {
|
||||
let storage_err = StorageError::ObjectNameInvalid("bucket-with-@#$%".to_string(), "object-with-!@#$%^&*()".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
assert!(s3_err.message().unwrap().contains("invalid object name"));
|
||||
assert!(s3_err.message().unwrap().contains("bucket-with-@#$%"));
|
||||
assert!(s3_err.message().unwrap().contains("object-with-!@#$%^&*()"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_with_empty_strings() {
|
||||
let storage_err = StorageError::BucketNotFound("".to_string());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_s3_error_with_very_long_strings() {
|
||||
let long_bucket_name = "a".repeat(1000);
|
||||
let storage_err = StorageError::BucketNotFound(long_bucket_name.clone());
|
||||
let err = Error::new(storage_err);
|
||||
let s3_err = to_s3_error(err);
|
||||
|
||||
assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
assert!(s3_err.message().unwrap().contains(&long_bucket_name));
|
||||
}
|
||||
}
|
||||
// use common::error::Error;
|
||||
// use ecstore::error::StorageError;
|
||||
// use s3s::{S3Error, S3ErrorCode, s3_error};
|
||||
// pub fn to_s3_error(err: Error) -> S3Error {
|
||||
// if let Some(storage_err) = err.downcast_ref::<StorageError>() {
|
||||
// return match storage_err {
|
||||
// StorageError::NotImplemented => s3_error!(NotImplemented),
|
||||
// StorageError::InvalidArgument(bucket, object, version_id) => {
|
||||
// s3_error!(InvalidArgument, "Invalid arguments provided for {}/{}-{}", bucket, object, version_id)
|
||||
// }
|
||||
// StorageError::MethodNotAllowed => s3_error!(MethodNotAllowed),
|
||||
// StorageError::BucketNotFound(bucket) => {
|
||||
// s3_error!(NoSuchBucket, "bucket not found {}", bucket)
|
||||
// }
|
||||
// StorageError::BucketNotEmpty(bucket) => s3_error!(BucketNotEmpty, "bucket not empty {}", bucket),
|
||||
// StorageError::BucketNameInvalid(bucket) => s3_error!(InvalidBucketName, "invalid bucket name {}", bucket),
|
||||
// StorageError::ObjectNameInvalid(bucket, object) => {
|
||||
// s3_error!(InvalidArgument, "invalid object name {}/{}", bucket, object)
|
||||
// }
|
||||
// StorageError::BucketExists(bucket) => s3_error!(BucketAlreadyExists, "{}", bucket),
|
||||
// StorageError::StorageFull => s3_error!(ServiceUnavailable, "Storage reached its minimum free drive threshold."),
|
||||
// StorageError::SlowDown => s3_error!(SlowDown, "Please reduce your request rate"),
|
||||
// StorageError::PrefixAccessDenied(bucket, object) => {
|
||||
// s3_error!(AccessDenied, "PrefixAccessDenied {}/{}", bucket, object)
|
||||
// }
|
||||
// StorageError::InvalidUploadIDKeyCombination(bucket, object) => {
|
||||
// s3_error!(InvalidArgument, "Invalid UploadID KeyCombination: {}/{}", bucket, object)
|
||||
// }
|
||||
// StorageError::MalformedUploadID(bucket) => s3_error!(InvalidArgument, "Malformed UploadID: {}", bucket),
|
||||
// StorageError::ObjectNameTooLong(bucket, object) => {
|
||||
// s3_error!(InvalidArgument, "Object name too long: {}/{}", bucket, object)
|
||||
// }
|
||||
// StorageError::ObjectNamePrefixAsSlash(bucket, object) => {
|
||||
// s3_error!(InvalidArgument, "Object name contains forward slash as prefix: {}/{}", bucket, object)
|
||||
// }
|
||||
// StorageError::ObjectNotFound(bucket, object) => s3_error!(NoSuchKey, "{}/{}", bucket, object),
|
||||
// StorageError::VersionNotFound(bucket, object, version_id) => {
|
||||
// s3_error!(NoSuchVersion, "{}/{}/{}", bucket, object, version_id)
|
||||
// }
|
||||
// StorageError::InvalidUploadID(bucket, object, version_id) => {
|
||||
// s3_error!(InvalidPart, "Invalid upload id: {}/{}-{}", bucket, object, version_id)
|
||||
// }
|
||||
// StorageError::InvalidVersionID(bucket, object, version_id) => {
|
||||
// s3_error!(InvalidArgument, "Invalid version id: {}/{}-{}", bucket, object, version_id)
|
||||
// }
|
||||
// // extended
|
||||
// StorageError::DataMovementOverwriteErr(bucket, object, version_id) => s3_error!(
|
||||
// InvalidArgument,
|
||||
// "invalid data movement operation, source and destination pool are the same for : {}/{}-{}",
|
||||
// bucket,
|
||||
// object,
|
||||
// version_id
|
||||
// ),
|
||||
|
||||
// // extended
|
||||
// StorageError::ObjectExistsAsDirectory(bucket, object) => {
|
||||
// s3_error!(InvalidArgument, "Object exists on :{} as directory {}", bucket, object)
|
||||
// }
|
||||
// StorageError::InvalidPart(bucket, object, version_id) => {
|
||||
// s3_error!(
|
||||
// InvalidPart,
|
||||
// "Specified part could not be found. PartNumber {}, Expected {}, got {}",
|
||||
// bucket,
|
||||
// object,
|
||||
// version_id
|
||||
// )
|
||||
// }
|
||||
// StorageError::DoneForNow => s3_error!(InternalError, "DoneForNow"),
|
||||
// };
|
||||
// }
|
||||
|
||||
// if is_err_file_not_found(&err) {
|
||||
// return S3Error::with_message(S3ErrorCode::NoSuchKey, format!(" ec err {}", err));
|
||||
// }
|
||||
|
||||
// S3Error::with_message(S3ErrorCode::InternalError, format!(" ec err {}", err))
|
||||
// }
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
// use s3s::S3ErrorCode;
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_not_implemented() {
|
||||
// let storage_err = StorageError::NotImplemented;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NotImplemented);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_invalid_argument() {
|
||||
// let storage_err =
|
||||
// StorageError::InvalidArgument("test-bucket".to_string(), "test-object".to_string(), "test-version".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Invalid arguments provided"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-version"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_method_not_allowed() {
|
||||
// let storage_err = StorageError::MethodNotAllowed;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::MethodNotAllowed);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_bucket_not_found() {
|
||||
// let storage_err = StorageError::BucketNotFound("test-bucket".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
// assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_bucket_not_empty() {
|
||||
// let storage_err = StorageError::BucketNotEmpty("test-bucket".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::BucketNotEmpty);
|
||||
// assert!(s3_err.message().unwrap().contains("bucket not empty"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_bucket_name_invalid() {
|
||||
// let storage_err = StorageError::BucketNameInvalid("invalid-bucket-name".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidBucketName);
|
||||
// assert!(s3_err.message().unwrap().contains("invalid bucket name"));
|
||||
// assert!(s3_err.message().unwrap().contains("invalid-bucket-name"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_object_name_invalid() {
|
||||
// let storage_err = StorageError::ObjectNameInvalid("test-bucket".to_string(), "invalid-object".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("invalid object name"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("invalid-object"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_bucket_exists() {
|
||||
// let storage_err = StorageError::BucketExists("existing-bucket".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::BucketAlreadyExists);
|
||||
// assert!(s3_err.message().unwrap().contains("existing-bucket"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_storage_full() {
|
||||
// let storage_err = StorageError::StorageFull;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::ServiceUnavailable);
|
||||
// assert!(
|
||||
// s3_err
|
||||
// .message()
|
||||
// .unwrap()
|
||||
// .contains("Storage reached its minimum free drive threshold")
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_slow_down() {
|
||||
// let storage_err = StorageError::SlowDown;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::SlowDown);
|
||||
// assert!(s3_err.message().unwrap().contains("Please reduce your request rate"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_prefix_access_denied() {
|
||||
// let storage_err = StorageError::PrefixAccessDenied("test-bucket".to_string(), "test-prefix".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::AccessDenied);
|
||||
// assert!(s3_err.message().unwrap().contains("PrefixAccessDenied"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-prefix"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_invalid_upload_id_key_combination() {
|
||||
// let storage_err = StorageError::InvalidUploadIDKeyCombination("test-bucket".to_string(), "test-object".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Invalid UploadID KeyCombination"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_malformed_upload_id() {
|
||||
// let storage_err = StorageError::MalformedUploadID("malformed-id".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Malformed UploadID"));
|
||||
// assert!(s3_err.message().unwrap().contains("malformed-id"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_object_name_too_long() {
|
||||
// let storage_err = StorageError::ObjectNameTooLong("test-bucket".to_string(), "very-long-object-name".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Object name too long"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("very-long-object-name"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_object_name_prefix_as_slash() {
|
||||
// let storage_err = StorageError::ObjectNamePrefixAsSlash("test-bucket".to_string(), "/invalid-object".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(
|
||||
// s3_err
|
||||
// .message()
|
||||
// .unwrap()
|
||||
// .contains("Object name contains forward slash as prefix")
|
||||
// );
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("/invalid-object"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_object_not_found() {
|
||||
// let storage_err = StorageError::ObjectNotFound("test-bucket".to_string(), "missing-object".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchKey);
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("missing-object"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_version_not_found() {
|
||||
// let storage_err =
|
||||
// StorageError::VersionNotFound("test-bucket".to_string(), "test-object".to_string(), "missing-version".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchVersion);
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
// assert!(s3_err.message().unwrap().contains("missing-version"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_invalid_upload_id() {
|
||||
// let storage_err =
|
||||
// StorageError::InvalidUploadID("test-bucket".to_string(), "test-object".to_string(), "invalid-upload-id".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidPart);
|
||||
// assert!(s3_err.message().unwrap().contains("Invalid upload id"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
// assert!(s3_err.message().unwrap().contains("invalid-upload-id"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_invalid_version_id() {
|
||||
// let storage_err = StorageError::InvalidVersionID(
|
||||
// "test-bucket".to_string(),
|
||||
// "test-object".to_string(),
|
||||
// "invalid-version-id".to_string(),
|
||||
// );
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Invalid version id"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
// assert!(s3_err.message().unwrap().contains("invalid-version-id"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_data_movement_overwrite_err() {
|
||||
// let storage_err = StorageError::DataMovementOverwriteErr(
|
||||
// "test-bucket".to_string(),
|
||||
// "test-object".to_string(),
|
||||
// "test-version".to_string(),
|
||||
// );
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("invalid data movement operation"));
|
||||
// assert!(s3_err.message().unwrap().contains("source and destination pool are the same"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-object"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-version"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_object_exists_as_directory() {
|
||||
// let storage_err = StorageError::ObjectExistsAsDirectory("test-bucket".to_string(), "directory-object".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Object exists on"));
|
||||
// assert!(s3_err.message().unwrap().contains("as directory"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-bucket"));
|
||||
// assert!(s3_err.message().unwrap().contains("directory-object"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_insufficient_read_quorum() {
|
||||
// let storage_err = StorageError::InsufficientReadQuorum;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::SlowDown);
|
||||
// assert!(
|
||||
// s3_err
|
||||
// .message()
|
||||
// .unwrap()
|
||||
// .contains("Storage resources are insufficient for the read operation")
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_insufficient_write_quorum() {
|
||||
// let storage_err = StorageError::InsufficientWriteQuorum;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::SlowDown);
|
||||
// assert!(
|
||||
// s3_err
|
||||
// .message()
|
||||
// .unwrap()
|
||||
// .contains("Storage resources are insufficient for the write operation")
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_decommission_not_started() {
|
||||
// let storage_err = StorageError::DecommissionNotStarted;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("Decommission Not Started"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_decommission_already_running() {
|
||||
// let storage_err = StorageError::DecommissionAlreadyRunning;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InternalError);
|
||||
// assert!(s3_err.message().unwrap().contains("Decommission already running"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_volume_not_found() {
|
||||
// let storage_err = StorageError::VolumeNotFound("test-volume".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
// assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
// assert!(s3_err.message().unwrap().contains("test-volume"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_invalid_part() {
|
||||
// let storage_err = StorageError::InvalidPart(1, "expected-part".to_string(), "got-part".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidPart);
|
||||
// assert!(s3_err.message().unwrap().contains("Specified part could not be found"));
|
||||
// assert!(s3_err.message().unwrap().contains("PartNumber"));
|
||||
// assert!(s3_err.message().unwrap().contains("expected-part"));
|
||||
// assert!(s3_err.message().unwrap().contains("got-part"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_done_for_now() {
|
||||
// let storage_err = StorageError::DoneForNow;
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InternalError);
|
||||
// assert!(s3_err.message().unwrap().contains("DoneForNow"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_non_storage_error() {
|
||||
// // Test with a non-StorageError
|
||||
// let err = Error::from_string("Generic error message".to_string());
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InternalError);
|
||||
// assert!(s3_err.message().unwrap().contains("ec err"));
|
||||
// assert!(s3_err.message().unwrap().contains("Generic error message"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_with_unicode_strings() {
|
||||
// let storage_err = StorageError::BucketNotFound("测试桶".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
// assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
// assert!(s3_err.message().unwrap().contains("测试桶"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_with_special_characters() {
|
||||
// let storage_err = StorageError::ObjectNameInvalid("bucket-with-@#$%".to_string(), "object-with-!@#$%^&*()".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::InvalidArgument);
|
||||
// assert!(s3_err.message().unwrap().contains("invalid object name"));
|
||||
// assert!(s3_err.message().unwrap().contains("bucket-with-@#$%"));
|
||||
// assert!(s3_err.message().unwrap().contains("object-with-!@#$%^&*()"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_with_empty_strings() {
|
||||
// let storage_err = StorageError::BucketNotFound("".to_string());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
// assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_to_s3_error_with_very_long_strings() {
|
||||
// let long_bucket_name = "a".repeat(1000);
|
||||
// let storage_err = StorageError::BucketNotFound(long_bucket_name.clone());
|
||||
// let err = Error::new(storage_err);
|
||||
// let s3_err = to_s3_error(err);
|
||||
|
||||
// assert_eq!(*s3_err.code(), S3ErrorCode::NoSuchBucket);
|
||||
// assert!(s3_err.message().unwrap().contains("bucket not found"));
|
||||
// assert!(s3_err.message().unwrap().contains(&long_bucket_name));
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pub mod access;
|
||||
pub mod ecfs;
|
||||
pub mod error;
|
||||
// pub mod error;
|
||||
mod event_notifier;
|
||||
pub mod options;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use common::error::{Error, Result};
|
||||
use ecstore::bucket::versioning_sys::BucketVersioningSys;
|
||||
use ecstore::store_api::ObjectOptions;
|
||||
use ecstore::error::Result;
|
||||
use ecstore::error::StorageError;
|
||||
use ecstore::store_api::ObjectOptions;
|
||||
use ecstore::utils::path::is_dir_object;
|
||||
use http::{HeaderMap, HeaderValue};
|
||||
use lazy_static::lazy_static;
|
||||
@@ -25,24 +25,16 @@ pub async fn del_opts(
|
||||
|
||||
if let Some(ref id) = vid {
|
||||
if let Err(_err) = Uuid::parse_str(id.as_str()) {
|
||||
return Err(Error::new(StorageError::InvalidVersionID(
|
||||
bucket.to_owned(),
|
||||
object.to_owned(),
|
||||
id.clone(),
|
||||
)));
|
||||
return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone()));
|
||||
}
|
||||
|
||||
if !versioned {
|
||||
return Err(Error::new(StorageError::InvalidArgument(
|
||||
bucket.to_owned(),
|
||||
object.to_owned(),
|
||||
id.clone(),
|
||||
)));
|
||||
return Err(StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), id.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut opts = put_opts_from_headers(headers, metadata)
|
||||
.map_err(|err| Error::new(StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), err.to_string())))?;
|
||||
.map_err(|err| StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), err.to_string()))?;
|
||||
|
||||
opts.version_id = {
|
||||
if is_dir_object(object) && vid.is_none() {
|
||||
@@ -72,24 +64,16 @@ pub async fn get_opts(
|
||||
|
||||
if let Some(ref id) = vid {
|
||||
if let Err(_err) = Uuid::parse_str(id.as_str()) {
|
||||
return Err(Error::new(StorageError::InvalidVersionID(
|
||||
bucket.to_owned(),
|
||||
object.to_owned(),
|
||||
id.clone(),
|
||||
)));
|
||||
return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone()));
|
||||
}
|
||||
|
||||
if !versioned {
|
||||
return Err(Error::new(StorageError::InvalidArgument(
|
||||
bucket.to_owned(),
|
||||
object.to_owned(),
|
||||
id.clone(),
|
||||
)));
|
||||
return Err(StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), id.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut opts = get_default_opts(headers, None, false)
|
||||
.map_err(|err| Error::new(StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), err.to_string())))?;
|
||||
.map_err(|err| StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), err.to_string()))?;
|
||||
|
||||
opts.version_id = {
|
||||
if is_dir_object(object) && vid.is_none() {
|
||||
@@ -122,24 +106,16 @@ pub async fn put_opts(
|
||||
|
||||
if let Some(ref id) = vid {
|
||||
if let Err(_err) = Uuid::parse_str(id.as_str()) {
|
||||
return Err(Error::new(StorageError::InvalidVersionID(
|
||||
bucket.to_owned(),
|
||||
object.to_owned(),
|
||||
id.clone(),
|
||||
)));
|
||||
return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone()));
|
||||
}
|
||||
|
||||
if !versioned {
|
||||
return Err(Error::new(StorageError::InvalidArgument(
|
||||
bucket.to_owned(),
|
||||
object.to_owned(),
|
||||
id.clone(),
|
||||
)));
|
||||
return Err(StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), id.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut opts = put_opts_from_headers(headers, metadata)
|
||||
.map_err(|err| Error::new(StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), err.to_string())))?;
|
||||
.map_err(|err| StorageError::InvalidArgument(bucket.to_owned(), object.to_owned(), err.to_string()))?;
|
||||
|
||||
opts.version_id = {
|
||||
if is_dir_object(object) && vid.is_none() {
|
||||
@@ -317,15 +293,13 @@ mod tests {
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(err) = result {
|
||||
if let Some(storage_err) = err.downcast_ref::<StorageError>() {
|
||||
match storage_err {
|
||||
StorageError::InvalidVersionID(bucket, object, version) => {
|
||||
assert_eq!(bucket, "test-bucket");
|
||||
assert_eq!(object, "test-object");
|
||||
assert_eq!(version, "invalid-uuid");
|
||||
}
|
||||
_ => panic!("Expected InvalidVersionID error"),
|
||||
match err {
|
||||
StorageError::InvalidVersionID(bucket, object, version) => {
|
||||
assert_eq!(bucket, "test-bucket");
|
||||
assert_eq!(object, "test-object");
|
||||
assert_eq!(version, "invalid-uuid");
|
||||
}
|
||||
_ => panic!("Expected InvalidVersionID error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -373,15 +347,13 @@ mod tests {
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(err) = result {
|
||||
if let Some(storage_err) = err.downcast_ref::<StorageError>() {
|
||||
match storage_err {
|
||||
StorageError::InvalidVersionID(bucket, object, version) => {
|
||||
assert_eq!(bucket, "test-bucket");
|
||||
assert_eq!(object, "test-object");
|
||||
assert_eq!(version, "invalid-uuid");
|
||||
}
|
||||
_ => panic!("Expected InvalidVersionID error"),
|
||||
match err {
|
||||
StorageError::InvalidVersionID(bucket, object, version) => {
|
||||
assert_eq!(bucket, "test-bucket");
|
||||
assert_eq!(object, "test-object");
|
||||
assert_eq!(version, "invalid-uuid");
|
||||
}
|
||||
_ => panic!("Expected InvalidVersionID error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,15 +391,13 @@ mod tests {
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(err) = result {
|
||||
if let Some(storage_err) = err.downcast_ref::<StorageError>() {
|
||||
match storage_err {
|
||||
StorageError::InvalidVersionID(bucket, object, version) => {
|
||||
assert_eq!(bucket, "test-bucket");
|
||||
assert_eq!(object, "test-object");
|
||||
assert_eq!(version, "invalid-uuid");
|
||||
}
|
||||
_ => panic!("Expected InvalidVersionID error"),
|
||||
match err {
|
||||
StorageError::InvalidVersionID(bucket, object, version) => {
|
||||
assert_eq!(bucket, "test-bucket");
|
||||
assert_eq!(object, "test-object");
|
||||
assert_eq!(version, "invalid-uuid");
|
||||
}
|
||||
_ => panic!("Expected InvalidVersionID error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user