refactor(storage): extract object-lock response builders from ecfs (#1906)

This commit is contained in:
安正超
2026-02-22 12:27:07 +08:00
committed by GitHub
parent 094e6a7319
commit 4a6e81d427
3 changed files with 141 additions and 24 deletions
+10 -24
View File
@@ -31,6 +31,10 @@ use crate::storage::s3_api::bucket::{
use crate::storage::s3_api::multipart::{
build_list_multipart_uploads_output, build_list_parts_output, parse_list_multipart_uploads_params, parse_list_parts_params,
};
use crate::storage::s3_api::object_lock::{
build_get_object_legal_hold_output, build_get_object_lock_configuration_output, build_get_object_retention_output,
build_put_object_legal_hold_output, build_put_object_retention_output,
};
use crate::storage::s3_api::response::{
access_denied_error, map_abort_multipart_upload_error, not_initialized_error, s3_response,
};
@@ -2978,22 +2982,12 @@ impl S3 for FS {
s3_error!(InternalError, "{}", e.to_string())
})?;
let legal_hold = object_info
let legal_hold_status = object_info
.user_defined
.get(AMZ_OBJECT_LOCK_LEGAL_HOLD_LOWER)
.map(|v| v.as_str().to_string());
let status = if let Some(v) = legal_hold {
v
} else {
ObjectLockLegalHoldStatus::OFF.to_string()
};
let output = GetObjectLegalHoldOutput {
legal_hold: Some(ObjectLockLegalHold {
status: Some(ObjectLockLegalHoldStatus::from(status)),
}),
};
let output = build_get_object_legal_hold_output(legal_hold_status);
let version_id = req.input.version_id.clone().unwrap_or_else(|| Uuid::new_v4().to_string());
helper = helper.object(object_info).version_id(version_id);
@@ -3029,9 +3023,7 @@ impl S3 for FS {
// warn!("object_lock_configuration {:?}", &object_lock_configuration);
Ok(s3_response(GetObjectLockConfigurationOutput {
object_lock_configuration,
}))
Ok(s3_response(build_get_object_lock_configuration_output(object_lock_configuration)))
}
async fn get_object_retention(
@@ -3070,9 +3062,7 @@ impl S3 for FS {
.and_then(|v| OffsetDateTime::parse(v.as_str(), &Rfc3339).ok())
.map(Timestamp::from);
let output = GetObjectRetentionOutput {
retention: Some(ObjectLockRetention { mode, retain_until_date }),
};
let output = build_get_object_retention_output(mode, retain_until_date);
let version_id = req.input.version_id.clone().unwrap_or_default();
helper = helper.object(object_info).version_id(version_id);
@@ -4118,9 +4108,7 @@ impl S3 for FS {
s3_error!(InternalError, "{}", e.to_string())
})?;
let output = PutObjectLegalHoldOutput {
request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
};
let output = build_put_object_legal_hold_output();
let version_id = req.input.version_id.clone().unwrap_or_default();
helper = helper.object(info).version_id(version_id);
@@ -4259,9 +4247,7 @@ impl S3 for FS {
s3_error!(InternalError, "{}", e.to_string())
})?;
let output = PutObjectRetentionOutput {
request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
};
let output = build_put_object_retention_output();
let version_id = req.input.version_id.clone().unwrap_or_else(|| Uuid::new_v4().to_string());
helper = helper.object(object_info).version_id(version_id);
+1
View File
@@ -22,6 +22,7 @@ pub(crate) mod bucket;
pub(crate) mod common;
pub(crate) mod encryption {}
pub(crate) mod multipart;
pub(crate) mod object_lock;
/// Object helper facade placeholder.
///
/// Read-path helpers shared across storage components should live in neutral
+130
View File
@@ -0,0 +1,130 @@
// 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 s3s::dto::{
GetObjectLegalHoldOutput, GetObjectLockConfigurationOutput, GetObjectRetentionOutput, ObjectLockConfiguration,
ObjectLockLegalHold, ObjectLockLegalHoldStatus, ObjectLockRetention, ObjectLockRetentionMode, PutObjectLegalHoldOutput,
PutObjectRetentionOutput, RequestCharged, Timestamp,
};
pub(crate) fn build_get_object_legal_hold_output(legal_hold_status: Option<String>) -> GetObjectLegalHoldOutput {
let status = legal_hold_status.unwrap_or_else(|| ObjectLockLegalHoldStatus::OFF.to_string());
GetObjectLegalHoldOutput {
legal_hold: Some(ObjectLockLegalHold {
status: Some(ObjectLockLegalHoldStatus::from(status)),
}),
}
}
pub(crate) fn build_get_object_lock_configuration_output(
object_lock_configuration: Option<ObjectLockConfiguration>,
) -> GetObjectLockConfigurationOutput {
GetObjectLockConfigurationOutput {
object_lock_configuration,
}
}
pub(crate) fn build_get_object_retention_output(
mode: Option<ObjectLockRetentionMode>,
retain_until_date: Option<Timestamp>,
) -> GetObjectRetentionOutput {
GetObjectRetentionOutput {
retention: Some(ObjectLockRetention { mode, retain_until_date }),
}
}
pub(crate) fn build_put_object_legal_hold_output() -> PutObjectLegalHoldOutput {
PutObjectLegalHoldOutput {
request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
}
}
pub(crate) fn build_put_object_retention_output() -> PutObjectRetentionOutput {
PutObjectRetentionOutput {
request_charged: Some(RequestCharged::from_static(RequestCharged::REQUESTER)),
}
}
#[cfg(test)]
mod tests {
use super::{
build_get_object_legal_hold_output, build_get_object_lock_configuration_output, build_get_object_retention_output,
build_put_object_legal_hold_output, build_put_object_retention_output,
};
use s3s::dto::{
ObjectLockConfiguration, ObjectLockEnabled, ObjectLockLegalHoldStatus, ObjectLockRetentionMode, RequestCharged,
};
use time::OffsetDateTime;
#[test]
fn test_build_get_object_legal_hold_output_defaults_to_off_when_missing() {
let output = build_get_object_legal_hold_output(None);
let status = output
.legal_hold
.as_ref()
.and_then(|hold| hold.status.as_ref())
.map(ObjectLockLegalHoldStatus::as_str);
assert_eq!(status, Some(ObjectLockLegalHoldStatus::OFF));
}
#[test]
fn test_build_get_object_legal_hold_output_uses_input_status() {
let output = build_get_object_legal_hold_output(Some(ObjectLockLegalHoldStatus::ON.to_string()));
let status = output
.legal_hold
.as_ref()
.and_then(|hold| hold.status.as_ref())
.map(ObjectLockLegalHoldStatus::as_str);
assert_eq!(status, Some(ObjectLockLegalHoldStatus::ON));
}
#[test]
fn test_build_get_object_lock_configuration_output_preserves_field() {
let cfg = ObjectLockConfiguration {
object_lock_enabled: Some(ObjectLockEnabled::from_static(ObjectLockEnabled::ENABLED)),
..Default::default()
};
let output = build_get_object_lock_configuration_output(Some(cfg.clone()));
assert_eq!(output.object_lock_configuration, Some(cfg));
}
#[test]
fn test_build_get_object_retention_output_preserves_fields() {
let mode = Some(ObjectLockRetentionMode::from_static(ObjectLockRetentionMode::GOVERNANCE));
let retain_until_date = Some(OffsetDateTime::UNIX_EPOCH.into());
let output = build_get_object_retention_output(mode.clone(), retain_until_date.clone());
let retention = output.retention.expect("retention should be present");
assert_eq!(retention.mode, mode);
assert_eq!(retention.retain_until_date, retain_until_date);
}
#[test]
fn test_build_put_object_legal_hold_output_sets_request_charged() {
let output = build_put_object_legal_hold_output();
assert_eq!(
output.request_charged.as_ref().map(RequestCharged::as_str),
Some(RequestCharged::REQUESTER)
);
}
#[test]
fn test_build_put_object_retention_output_sets_request_charged() {
let output = build_put_object_retention_output();
assert_eq!(
output.request_charged.as_ref().map(RequestCharged::as_str),
Some(RequestCharged::REQUESTER)
);
}
}