mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-16 09:58:21 +00:00
refactor: clean Swift ECStore boundaries (#3570)
This commit is contained in:
@@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
//! Swift account operations and validation
|
//! Swift account operations and validation
|
||||||
|
|
||||||
|
use super::storage_compat::{get_swift_bucket_metadata, resolve_swift_object_store_handle, set_swift_bucket_metadata};
|
||||||
use super::{SwiftError, SwiftResult};
|
use super::{SwiftError, SwiftResult};
|
||||||
use rustfs_credentials::Credentials;
|
use rustfs_credentials::Credentials;
|
||||||
use rustfs_ecstore::resolve_object_store_handle;
|
|
||||||
use rustfs_storage_api::{BucketOperations, MakeBucketOptions};
|
use rustfs_storage_api::{BucketOperations, MakeBucketOptions};
|
||||||
use s3s::dto::{Tag, Tagging};
|
use s3s::dto::{Tag, Tagging};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
@@ -119,7 +119,7 @@ pub async fn get_account_metadata(account: &str, _credentials: &Option<Credentia
|
|||||||
let bucket_name = get_account_metadata_bucket_name(account);
|
let bucket_name = get_account_metadata_bucket_name(account);
|
||||||
|
|
||||||
// Try to load bucket metadata
|
// Try to load bucket metadata
|
||||||
let bucket_meta = match rustfs_ecstore::bucket::metadata_sys::get(&bucket_name).await {
|
let bucket_meta = match get_swift_bucket_metadata(&bucket_name).await {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Bucket doesn't exist - return empty metadata
|
// Bucket doesn't exist - return empty metadata
|
||||||
@@ -159,12 +159,12 @@ pub async fn update_account_metadata(
|
|||||||
) -> SwiftResult<()> {
|
) -> SwiftResult<()> {
|
||||||
let bucket_name = get_account_metadata_bucket_name(account);
|
let bucket_name = get_account_metadata_bucket_name(account);
|
||||||
|
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create bucket if it doesn't exist
|
// Create bucket if it doesn't exist
|
||||||
let bucket_exists = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name).await.is_ok();
|
let bucket_exists = get_swift_bucket_metadata(&bucket_name).await.is_ok();
|
||||||
if !bucket_exists {
|
if !bucket_exists {
|
||||||
// Create bucket for account metadata
|
// Create bucket for account metadata
|
||||||
store
|
store
|
||||||
@@ -174,7 +174,7 @@ pub async fn update_account_metadata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load current bucket metadata
|
// Load current bucket metadata
|
||||||
let bucket_meta = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name)
|
let bucket_meta = get_swift_bucket_metadata(&bucket_name)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ pub async fn update_account_metadata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save updated metadata
|
// Save updated metadata
|
||||||
rustfs_ecstore::bucket::metadata_sys::set_bucket_metadata(bucket_name.clone(), bucket_meta_clone)
|
set_swift_bucket_metadata(bucket_name.clone(), bucket_meta_clone)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
//! This module implements Swift container CRUD operations and container-bucket translation.
|
//! This module implements Swift container CRUD operations and container-bucket translation.
|
||||||
|
|
||||||
use super::account::validate_account_access;
|
use super::account::validate_account_access;
|
||||||
|
use super::storage_compat::{get_swift_bucket_metadata, resolve_swift_object_store_handle, set_swift_bucket_metadata};
|
||||||
use super::types::Container;
|
use super::types::Container;
|
||||||
use super::{SwiftError, SwiftResult};
|
use super::{SwiftError, SwiftResult};
|
||||||
use rustfs_credentials::Credentials;
|
use rustfs_credentials::Credentials;
|
||||||
use rustfs_ecstore::resolve_object_store_handle;
|
|
||||||
use rustfs_storage_api::{
|
use rustfs_storage_api::{
|
||||||
BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, ListOperations as _, MakeBucketOptions,
|
BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, ListOperations as _, MakeBucketOptions,
|
||||||
};
|
};
|
||||||
@@ -243,7 +243,7 @@ pub async fn list_containers(account: &str, credentials: &Credentials) -> SwiftR
|
|||||||
let mapper = ContainerMapper::default();
|
let mapper = ContainerMapper::default();
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ pub async fn create_container(account: &str, container: &str, credentials: &Cred
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ pub async fn get_container_metadata(account: &str, container: &str, credentials:
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -413,7 +413,7 @@ pub async fn get_container_metadata(account: &str, container: &str, credentials:
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Load bucket metadata to get custom metadata from tags
|
// Load bucket metadata to get custom metadata from tags
|
||||||
let custom_metadata = match rustfs_ecstore::bucket::metadata_sys::get(&bucket_name).await {
|
let custom_metadata = match get_swift_bucket_metadata(&bucket_name).await {
|
||||||
Ok(bucket_meta) => {
|
Ok(bucket_meta) => {
|
||||||
if let Some(tagging) = &bucket_meta.tagging_config {
|
if let Some(tagging) = &bucket_meta.tagging_config {
|
||||||
s3_tags_to_swift_metadata(tagging)
|
s3_tags_to_swift_metadata(tagging)
|
||||||
@@ -472,7 +472,7 @@ pub async fn update_container_metadata(
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ pub async fn update_container_metadata(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Load current bucket metadata
|
// Load current bucket metadata
|
||||||
let bucket_meta = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name)
|
let bucket_meta = get_swift_bucket_metadata(&bucket_name)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -536,7 +536,7 @@ pub async fn update_container_metadata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save updated metadata
|
// Save updated metadata
|
||||||
rustfs_ecstore::bucket::metadata_sys::set_bucket_metadata(bucket_name, bucket_meta_clone)
|
set_swift_bucket_metadata(bucket_name, bucket_meta_clone)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -571,7 +571,7 @@ pub async fn delete_container(account: &str, container: &str, credentials: &Cred
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -659,7 +659,7 @@ pub async fn list_objects(
|
|||||||
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -769,7 +769,7 @@ pub async fn enable_versioning(
|
|||||||
let archive_bucket_name = mapper.swift_to_s3_bucket(archive_container, &project_id);
|
let archive_bucket_name = mapper.swift_to_s3_bucket(archive_container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -802,7 +802,7 @@ pub async fn enable_versioning(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Load current bucket metadata
|
// Load current bucket metadata
|
||||||
let bucket_meta = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name)
|
let bucket_meta = get_swift_bucket_metadata(&bucket_name)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -836,7 +836,7 @@ pub async fn enable_versioning(
|
|||||||
bucket_meta_clone.tagging_config = Some(existing_tagging);
|
bucket_meta_clone.tagging_config = Some(existing_tagging);
|
||||||
|
|
||||||
// Save updated metadata
|
// Save updated metadata
|
||||||
rustfs_ecstore::bucket::metadata_sys::set_bucket_metadata(bucket_name, bucket_meta_clone)
|
set_swift_bucket_metadata(bucket_name, bucket_meta_clone)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -865,12 +865,12 @@ pub async fn disable_versioning(account: &str, container: &str, credentials: &Cr
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Verify container exists
|
// Verify container exists
|
||||||
let Some(_store) = resolve_object_store_handle() else {
|
let Some(_store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load current bucket metadata
|
// Load current bucket metadata
|
||||||
let bucket_meta = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name)
|
let bucket_meta = get_swift_bucket_metadata(&bucket_name)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -905,7 +905,7 @@ pub async fn disable_versioning(account: &str, container: &str, credentials: &Cr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save updated metadata
|
// Save updated metadata
|
||||||
rustfs_ecstore::bucket::metadata_sys::set_bucket_metadata(bucket_name, bucket_meta_clone)
|
set_swift_bucket_metadata(bucket_name, bucket_meta_clone)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -937,7 +937,7 @@ pub async fn get_versions_location(account: &str, container: &str, credentials:
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Load bucket metadata
|
// Load bucket metadata
|
||||||
let bucket_meta = match rustfs_ecstore::bucket::metadata_sys::get(&bucket_name).await {
|
let bucket_meta = match get_swift_bucket_metadata(&bucket_name).await {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => meta,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Container doesn't exist
|
// Container doesn't exist
|
||||||
@@ -1016,7 +1016,7 @@ pub async fn set_container_acl(
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1033,7 +1033,7 @@ pub async fn set_container_acl(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Load current bucket metadata
|
// Load current bucket metadata
|
||||||
let bucket_meta = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name)
|
let bucket_meta = get_swift_bucket_metadata(&bucket_name)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to load bucket metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -1088,7 +1088,7 @@ pub async fn set_container_acl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save updated metadata
|
// Save updated metadata
|
||||||
rustfs_ecstore::bucket::metadata_sys::set_bucket_metadata(bucket_name, bucket_meta_clone)
|
set_swift_bucket_metadata(bucket_name, bucket_meta_clone)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
.map_err(|e| SwiftError::InternalServerError(format!("Failed to save metadata: {}", e)))?;
|
||||||
|
|
||||||
@@ -1135,7 +1135,7 @@ pub async fn get_container_acl(
|
|||||||
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket_name = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// Load bucket metadata
|
// Load bucket metadata
|
||||||
let bucket_meta = rustfs_ecstore::bucket::metadata_sys::get(&bucket_name).await.map_err(|e| {
|
let bucket_meta = get_swift_bucket_metadata(&bucket_name).await.map_err(|e| {
|
||||||
if e.to_string().contains("not found") {
|
if e.to_string().contains("not found") {
|
||||||
SwiftError::NotFound(format!("Container '{}' not found", container))
|
SwiftError::NotFound(format!("Container '{}' not found", container))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -51,10 +51,10 @@
|
|||||||
|
|
||||||
use super::account::validate_account_access;
|
use super::account::validate_account_access;
|
||||||
use super::container::ContainerMapper;
|
use super::container::ContainerMapper;
|
||||||
|
use super::storage_compat::resolve_swift_object_store_handle;
|
||||||
use super::{SwiftError, SwiftResult};
|
use super::{SwiftError, SwiftResult};
|
||||||
use axum::http::HeaderMap;
|
use axum::http::HeaderMap;
|
||||||
use rustfs_credentials::Credentials;
|
use rustfs_credentials::Credentials;
|
||||||
use rustfs_ecstore::resolve_object_store_handle;
|
|
||||||
use rustfs_rio::HashReader;
|
use rustfs_rio::HashReader;
|
||||||
use rustfs_storage_api::{BucketOperations, BucketOptions, ObjectIO as _, ObjectOperations as _};
|
use rustfs_storage_api::{BucketOperations, BucketOptions, ObjectIO as _, ObjectOperations as _};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -384,7 +384,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 12. Get storage layer
|
// 12. Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -464,7 +464,7 @@ where
|
|||||||
validate_metadata(metadata)?;
|
validate_metadata(metadata)?;
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -550,7 +550,7 @@ pub async fn get_object(
|
|||||||
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// 5. Get storage layer
|
// 5. Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ pub async fn head_object(
|
|||||||
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// 5. Get storage layer
|
// 5. Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -666,7 +666,7 @@ pub async fn delete_object(account: &str, container: &str, object: &str, credent
|
|||||||
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// 5. Get storage layer
|
// 5. Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -729,7 +729,7 @@ pub async fn update_object_metadata(
|
|||||||
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
let bucket = mapper.swift_to_s3_bucket(container, &project_id);
|
||||||
|
|
||||||
// 5. Get storage layer
|
// 5. Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -853,7 +853,7 @@ pub async fn copy_object(
|
|||||||
let dst_bucket = mapper.swift_to_s3_bucket(dst_container, &dst_project_id);
|
let dst_bucket = mapper.swift_to_s3_bucket(dst_container, &dst_project_id);
|
||||||
|
|
||||||
// 6. Get storage layer
|
// 6. Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,30 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use rustfs_ecstore::store_api::{
|
use rustfs_ecstore::{
|
||||||
GetObjectReader as EcstoreGetObjectReader, ObjectInfo as EcstoreObjectInfo, ObjectOptions as EcstoreObjectOptions,
|
bucket::{metadata::BucketMetadata, metadata_sys},
|
||||||
PutObjReader as EcstorePutObjReader,
|
error::Result as EcstoreResult,
|
||||||
|
store::ECStore,
|
||||||
|
store_api::{
|
||||||
|
GetObjectReader as EcstoreGetObjectReader, ObjectInfo as EcstoreObjectInfo, ObjectOptions as EcstoreObjectOptions,
|
||||||
|
PutObjReader as EcstorePutObjReader,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type SwiftGetObjectReader = EcstoreGetObjectReader;
|
pub type SwiftGetObjectReader = EcstoreGetObjectReader;
|
||||||
pub type SwiftObjectInfo = EcstoreObjectInfo;
|
pub type SwiftObjectInfo = EcstoreObjectInfo;
|
||||||
pub type SwiftObjectOptions = EcstoreObjectOptions;
|
pub type SwiftObjectOptions = EcstoreObjectOptions;
|
||||||
pub type SwiftPutObjReader = EcstorePutObjReader;
|
pub type SwiftPutObjReader = EcstorePutObjReader;
|
||||||
|
|
||||||
|
pub fn resolve_swift_object_store_handle() -> Option<Arc<ECStore>> {
|
||||||
|
rustfs_ecstore::resolve_object_store_handle()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_swift_bucket_metadata(bucket: &str) -> EcstoreResult<Arc<BucketMetadata>> {
|
||||||
|
metadata_sys::get(bucket).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_swift_bucket_metadata(bucket: String, metadata: BucketMetadata) -> EcstoreResult<()> {
|
||||||
|
metadata_sys::set_bucket_metadata(bucket, metadata).await
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,9 +54,9 @@
|
|||||||
use super::account::validate_account_access;
|
use super::account::validate_account_access;
|
||||||
use super::container::ContainerMapper;
|
use super::container::ContainerMapper;
|
||||||
use super::object::{ObjectKeyMapper, SwiftObjectOptions as ObjectOptions, head_object};
|
use super::object::{ObjectKeyMapper, SwiftObjectOptions as ObjectOptions, head_object};
|
||||||
|
use super::storage_compat::resolve_swift_object_store_handle;
|
||||||
use super::{SwiftError, SwiftResult};
|
use super::{SwiftError, SwiftResult};
|
||||||
use rustfs_credentials::Credentials;
|
use rustfs_credentials::Credentials;
|
||||||
use rustfs_ecstore::resolve_object_store_handle;
|
|
||||||
use rustfs_storage_api::{ListOperations as _, ObjectOperations as _};
|
use rustfs_storage_api::{ListOperations as _, ObjectOperations as _};
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
@@ -197,7 +197,7 @@ pub async fn archive_current_version(
|
|||||||
let version_key = ObjectKeyMapper::swift_to_s3_key(&version_name)?;
|
let version_key = ObjectKeyMapper::swift_to_s3_key(&version_name)?;
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ pub async fn restore_previous_version(
|
|||||||
let version_key = ObjectKeyMapper::swift_to_s3_key(newest_version)?;
|
let version_key = ObjectKeyMapper::swift_to_s3_key(newest_version)?;
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -476,7 +476,7 @@ pub async fn list_object_versions(
|
|||||||
let archive_bucket = mapper.swift_to_s3_bucket(archive_container, &project_id);
|
let archive_bucket = mapper.swift_to_s3_bucket(archive_container, &project_id);
|
||||||
|
|
||||||
// Get storage layer
|
// Get storage layer
|
||||||
let Some(store) = resolve_object_store_handle() else {
|
let Some(store) = resolve_swift_object_store_handle() else {
|
||||||
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
return Err(SwiftError::InternalServerError("Storage layer not initialized".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -824,6 +824,26 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
diff hygiene, direct import scan, Rust risk scan, full pre-commit, and
|
diff hygiene, direct import scan, Rust risk scan, full pre-commit, and
|
||||||
required three-expert review passed.
|
required three-expert review passed.
|
||||||
|
|
||||||
|
- [x] `API-028` Clean Swift ECStore runtime boundary imports.
|
||||||
|
- Current branch: `overtrue/arch-swift-ecstore-boundaries`.
|
||||||
|
- Completed slice: move Swift account, container, object, and versioning
|
||||||
|
access to ECStore object-store resolver and bucket metadata get/set calls
|
||||||
|
behind the Swift-local `storage_compat` module.
|
||||||
|
- Acceptance: direct Swift module references to `rustfs_ecstore` for object
|
||||||
|
store resolution, bucket metadata reads, bucket metadata writes, and object
|
||||||
|
DTO aliases are limited to `swift::storage_compat`; Swift business modules
|
||||||
|
consume Swift-owned compatibility names.
|
||||||
|
- Must preserve: Swift account metadata tags, container metadata tags,
|
||||||
|
versioning location tags, ACL tag storage, object CRUD/copy/range behavior,
|
||||||
|
storage-not-initialized error mapping, and bucket metadata load/save error
|
||||||
|
mapping.
|
||||||
|
- Risk defense: this slice changes import ownership and thin wrapper
|
||||||
|
boundaries only; it does not move ECStore definitions, alter metadata
|
||||||
|
serialization, change Swift bucket naming, or adjust runtime control flow.
|
||||||
|
- Verification: focused Swift compile/tests, migration/layer guards,
|
||||||
|
formatting, diff hygiene, direct Swift import scan, Rust risk scan, full
|
||||||
|
pre-commit, and required three-expert review passed.
|
||||||
|
|
||||||
## Phase 8 Background Controller Tasks
|
## Phase 8 Background Controller Tasks
|
||||||
|
|
||||||
- [x] `BGC-001` Inventory background services.
|
- [x] `BGC-001` Inventory background services.
|
||||||
@@ -1093,61 +1113,46 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
## Next PRs
|
## Next PRs
|
||||||
|
|
||||||
1. `pure-move`/`consumer-migration`: continue larger cleanup slices with the
|
1. `pure-move`/`consumer-migration`: continue larger cleanup slices with the
|
||||||
loss-prevention guards active for public re-exports and remaining storage
|
loss-prevention guards active for remaining storage compatibility contracts
|
||||||
compatibility contracts.
|
such as scanner/heal runtime boundaries.
|
||||||
|
|
||||||
## Pre-Push Review Log
|
## Pre-Push Review Log
|
||||||
|
|
||||||
| Expert | Status | Notes |
|
| Expert | Status | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Quality/architecture | passed | Table catalog, IAM, admin zip, capacity, heal integration, scanner, Swift, S3 Select, and notify consumers now use local DTO compatibility aliases instead of raw ECStore `store_api` imports. |
|
| Quality/architecture | passed | Swift account, container, object, and versioning modules now use Swift-local storage compatibility wrappers for ECStore resolver and bucket metadata access. |
|
||||||
| Migration preservation | passed | ECStore remains the owner of object DTO/readers; alias boundaries preserve concrete associated types for storage traits, IAM config reads, zip preflight reads, scanner cache I/O, Swift/S3 Select reads, notify payloads, capacity assertions, and heal integration writes. |
|
| Migration preservation | passed | ECStore remains the owner of object-store resolution and bucket metadata persistence; Swift metadata tags, ACL tags, versioning tags, and object read/write/copy semantics are preserved. |
|
||||||
| Testing/verification | passed | Focused compile/tests, migration/layer guards, direct import scan, formatting, diff hygiene, Rust risk scan, and full `make pre-commit` passed. |
|
| Testing/verification | passed | Focused Swift compile/tests, migration/layer guards, direct Swift import scan, formatting, diff hygiene, Rust risk scan, and full `make pre-commit` passed. |
|
||||||
|
|
||||||
## Verification Notes
|
## Verification Notes
|
||||||
|
|
||||||
Passed before push:
|
Passed before push:
|
||||||
|
|
||||||
- `cargo check --tests -p rustfs -p rustfs-iam -p rustfs-heal`: passed.
|
- `cargo check --tests -p rustfs-protocols`: passed.
|
||||||
- `cargo check --tests -p rustfs-iam -p rustfs-heal -p rustfs-scanner -p
|
- `cargo test -p rustfs-protocols`: passed; 13 passed.
|
||||||
rustfs-protocols -p rustfs-s3select-api -p rustfs-notify`: passed.
|
- `rg -n 'rustfs_ecstore|resolve_object_store_handle|metadata_sys'
|
||||||
- `cargo test -p rustfs --lib table_catalog_store_trait`: passed; 2 passed.
|
crates/protocols/src/swift/*.rs`: remaining matches are deliberate Swift
|
||||||
- `cargo test -p rustfs --lib admin::handlers::object_zip_download::tests`:
|
compatibility boundary definitions.
|
||||||
passed; 28 passed.
|
|
||||||
- `cargo test -p rustfs --lib app::capacity_dirty_scope_test`: passed; 2
|
|
||||||
passed.
|
|
||||||
- `cargo test -p rustfs-iam store::object::tests`: passed; 8 passed.
|
|
||||||
- `cargo test -p rustfs-heal --test heal_integration_test`: passed; 5 passed.
|
|
||||||
- `cargo check --tests -p rustfs-scanner -p rustfs-protocols -p
|
|
||||||
rustfs-s3select-api -p rustfs-notify`: passed.
|
|
||||||
- `cargo test -p rustfs-scanner -p rustfs-protocols -p rustfs-s3select-api -p
|
|
||||||
rustfs-notify`: passed; notify 82 passed, protocols 13 passed, S3 Select 49
|
|
||||||
passed, scanner 151 passed plus lifecycle integration 1 passed and 14
|
|
||||||
ignored.
|
|
||||||
- `rg -n 'rustfs_ecstore::store_api|store_api::\{' rustfs/src crates --glob
|
|
||||||
'!crates/ecstore/**' --glob '*.rs'`: remaining matches are deliberate
|
|
||||||
boundary alias definitions in RustFS storage and crate-local compat modules.
|
|
||||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||||
- `cargo fmt --all --check`: passed.
|
- `cargo fmt --all --check`: passed.
|
||||||
- `git diff --check`: passed.
|
- `git diff --check`: passed.
|
||||||
- Rust risk scan: new hits are crate-local alias casts only; no new
|
- Rust risk scan: no new `unwrap`/`expect`, panic/todo markers, `unsafe`,
|
||||||
`unwrap`/`expect`, panic/todo markers, `unsafe`, process-spawning calls,
|
process-spawning calls, println/eprintln, relaxed ordering, or numeric casts
|
||||||
println/eprintln, or relaxed ordering in added Rust lines.
|
in added Rust lines.
|
||||||
- `make pre-commit`: passed.
|
- `make pre-commit`: passed.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- This slice is stacked on API-026 while `rustfs/rustfs#3566` is pending.
|
- This slice builds on the merged API-027 compatibility cleanup.
|
||||||
- Direct ECStore `store_api` references outside ECStore now remain only at
|
- Direct Swift ECStore resolver and bucket metadata access now remains only in
|
||||||
explicit alias boundary points.
|
the Swift compatibility boundary.
|
||||||
- The slice does not alter table catalog storage behavior, IAM config storage,
|
- The slice does not alter Swift account/container metadata behavior, object
|
||||||
admin zip download object reads, capacity dirty-disk behavior, heal
|
read/write/copy behavior, versioning behavior, ACL behavior, or ECStore
|
||||||
integration semantics, scanner cache I/O, Swift/S3 Select object reads,
|
definitions.
|
||||||
notification event payloads, or ECStore DTO definitions.
|
|
||||||
|
|
||||||
## Handoff Notes
|
## Handoff Notes
|
||||||
|
|
||||||
- Continue with larger consumer-migration batches; keep ECStore-owned
|
- Continue with larger consumer-migration batches around scanner/heal runtime
|
||||||
DTOs/readers/walk filters in ECStore until their concrete behavior is isolated
|
boundaries; keep ECStore-owned behavior in ECStore until concrete behavior is
|
||||||
enough for a pure-move slice.
|
isolated enough for a pure-move slice.
|
||||||
|
|||||||
Reference in New Issue
Block a user