mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 00:26:53 +00:00
feat(storage-api): add bucket DTO contract (#3314)
* feat(storage-api): add bucket DTO contract * ci(build): increase workflow timeout to 90 minutes --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -40,6 +40,7 @@ rustfs-utils = { workspace = true, features = ["full"] }
|
||||
rustfs-rio.workspace = true
|
||||
rustfs-rio-v2 = { workspace = true, optional = true }
|
||||
rustfs-signer.workspace = true
|
||||
rustfs-storage-api.workspace = true
|
||||
rustfs-tls-runtime.workspace = true
|
||||
rustfs-checksums.workspace = true
|
||||
rustfs-config = { workspace = true, features = ["constants", "notify", "audit"] }
|
||||
@@ -51,7 +52,6 @@ rustfs-kms.workspace = true
|
||||
rustfs-s3-types = { workspace = true }
|
||||
rustfs-data-usage.workspace = true
|
||||
rustfs-object-capacity.workspace = true
|
||||
rustfs-storage-api.workspace = true
|
||||
async-trait.workspace = true
|
||||
bytes.workspace = true
|
||||
byteorder = { workspace = true }
|
||||
|
||||
@@ -39,7 +39,6 @@ use rustfs_utils::CompressionAlgorithm;
|
||||
use rustfs_utils::http::headers::AMZ_OBJECT_TAGGING;
|
||||
use rustfs_utils::http::{AMZ_BUCKET_REPLICATION_STATUS, AMZ_RESTORE, AMZ_STORAGE_CLASS};
|
||||
use rustfs_utils::path::decode_dir_object;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::io::Cursor;
|
||||
|
||||
@@ -11,6 +11,8 @@ use rustfs_kms::{service_manager::get_global_encryption_service, types::ObjectEn
|
||||
use rustfs_utils::http::{SSEC_ALGORITHM_HEADER, SSEC_KEY_HEADER, SSEC_KEY_MD5_HEADER};
|
||||
use rustfs_utils::path::path_join_buf;
|
||||
#[cfg(feature = "rio-v2")]
|
||||
use serde::Deserialize;
|
||||
#[cfg(feature = "rio-v2")]
|
||||
use sha2::Sha256;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
|
||||
@@ -1,29 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct MakeBucketOptions {
|
||||
pub lock_enabled: bool,
|
||||
pub versioning_enabled: bool,
|
||||
pub force_create: bool, // Create buckets even if they are already created.
|
||||
pub created_at: Option<OffsetDateTime>, // only for site replication
|
||||
pub no_lock: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
pub enum SRBucketDeleteOp {
|
||||
#[default]
|
||||
NoOp,
|
||||
MarkDelete,
|
||||
Purge,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DeleteBucketOptions {
|
||||
pub no_lock: bool,
|
||||
pub no_recreate: bool,
|
||||
pub force: bool, // Force deletion
|
||||
pub srdelete_op: SRBucketDeleteOp,
|
||||
}
|
||||
// RUSTFS_COMPAT_TODO(API-003): keep old ecstore::store_api bucket DTO import paths while storage API consumers migrate. Remove after all consumers import these DTOs from rustfs_storage_api.
|
||||
pub use rustfs_storage_api::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct HTTPPreconditions {
|
||||
@@ -225,22 +203,6 @@ fn is_modified_since(mod_time: &OffsetDateTime, given_time: &OffsetDateTime) ->
|
||||
mod_secs > given_secs
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct BucketOptions {
|
||||
pub deleted: bool, // true only when site replication is enabled
|
||||
pub cached: bool, // true only when we are requesting a cached response instead of hitting the disk for example ListBuckets() call.
|
||||
pub no_metadata: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct BucketInfo {
|
||||
pub name: String,
|
||||
pub created: Option<OffsetDateTime>,
|
||||
pub deleted: Option<OffsetDateTime>,
|
||||
pub versioning: bool,
|
||||
pub object_locking: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct MultipartUploadResult {
|
||||
pub upload_id: String,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2024 RustFS Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use rustfs_ecstore::store_api::{
|
||||
BucketInfo as EcstoreBucketInfo, BucketOptions as EcstoreBucketOptions, MakeBucketOptions as EcstoreMakeBucketOptions,
|
||||
};
|
||||
use rustfs_storage_api::{
|
||||
BucketInfo as ApiBucketInfo, BucketOptions as ApiBucketOptions, MakeBucketOptions as ApiMakeBucketOptions,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn old_store_api_bucket_dto_path_reexports_storage_api_types() {
|
||||
let ecstore_bucket: EcstoreBucketInfo = ApiBucketInfo {
|
||||
name: "photos".to_owned(),
|
||||
versioning: true,
|
||||
..Default::default()
|
||||
};
|
||||
let api_bucket: ApiBucketInfo = ecstore_bucket;
|
||||
|
||||
let ecstore_make: EcstoreMakeBucketOptions = ApiMakeBucketOptions::default();
|
||||
let api_options: ApiBucketOptions = EcstoreBucketOptions::default();
|
||||
|
||||
assert_eq!(api_bucket.name, "photos");
|
||||
assert!(api_bucket.versioning);
|
||||
assert!(!ecstore_make.lock_enabled);
|
||||
assert!(!api_options.no_metadata);
|
||||
}
|
||||
@@ -27,5 +27,12 @@ categories = ["web-programming", "development-tools", "filesystem"]
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
time.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2024 RustFS Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct MakeBucketOptions {
|
||||
pub lock_enabled: bool,
|
||||
pub versioning_enabled: bool,
|
||||
pub force_create: bool,
|
||||
pub created_at: Option<OffsetDateTime>,
|
||||
pub no_lock: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
pub enum SRBucketDeleteOp {
|
||||
#[default]
|
||||
NoOp,
|
||||
MarkDelete,
|
||||
Purge,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DeleteBucketOptions {
|
||||
pub no_lock: bool,
|
||||
pub no_recreate: bool,
|
||||
pub force: bool,
|
||||
pub srdelete_op: SRBucketDeleteOp,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct BucketOptions {
|
||||
pub deleted: bool,
|
||||
pub cached: bool,
|
||||
pub no_metadata: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct BucketInfo {
|
||||
pub name: String,
|
||||
pub created: Option<OffsetDateTime>,
|
||||
pub deleted: Option<OffsetDateTime>,
|
||||
pub versioning: bool,
|
||||
pub object_locking: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn bucket_info_serializes_with_existing_fields() {
|
||||
let bucket = BucketInfo {
|
||||
name: "photos".to_owned(),
|
||||
created: Some(OffsetDateTime::UNIX_EPOCH),
|
||||
deleted: None,
|
||||
versioning: true,
|
||||
object_locking: false,
|
||||
};
|
||||
|
||||
let encoded = serde_json::to_string(&bucket).expect("serialize BucketInfo to JSON");
|
||||
let decoded: BucketInfo = serde_json::from_str(&encoded).expect("deserialize BucketInfo from JSON");
|
||||
|
||||
assert_eq!(decoded.name, "photos");
|
||||
assert_eq!(decoded.created, Some(OffsetDateTime::UNIX_EPOCH));
|
||||
assert!(decoded.versioning);
|
||||
assert!(!decoded.object_locking);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_bucket_options_preserve_false_flags() {
|
||||
let opts = BucketOptions::default();
|
||||
|
||||
assert!(!opts.deleted);
|
||||
assert!(!opts.cached);
|
||||
assert!(!opts.no_metadata);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_delete_bucket_options_use_noop_site_replication() {
|
||||
let opts = DeleteBucketOptions::default();
|
||||
|
||||
assert_eq!(opts.srdelete_op, SRBucketDeleteOp::NoOp);
|
||||
assert!(!opts.no_lock);
|
||||
assert!(!opts.no_recreate);
|
||||
assert!(!opts.force);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
//! Storage API contracts for RustFS.
|
||||
|
||||
pub mod bucket;
|
||||
pub mod error;
|
||||
|
||||
pub use bucket::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};
|
||||
pub use error::{StorageErrorCode, StorageResult};
|
||||
|
||||
Reference in New Issue
Block a user