fix(admin): include accountinfo bucket quota

Expose accountinfo bucket quota only when a bucket quota is configured while preserving the existing response shape for buckets without quotas.
This commit is contained in:
Zhengchao An
2026-07-09 04:52:52 +08:00
committed by GitHub
parent e468648f0f
commit 2dfad181a0
2 changed files with 26 additions and 1 deletions
+18
View File
@@ -423,6 +423,8 @@ pub struct BucketDetails {
pub versioning_suspended: bool, pub versioning_suspended: bool,
pub locking: bool, pub locking: bool,
pub replication: bool, pub replication: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quota: Option<u64>,
// pub tagging: Option<Tagging>, // pub tagging: Option<Tagging>,
} }
@@ -1036,6 +1038,7 @@ mod tests {
versioning_suspended: false, versioning_suspended: false,
locking: true, locking: true,
replication: false, replication: false,
quota: None,
}), }),
prefix_usage, prefix_usage,
created: Some(now), created: Some(now),
@@ -1064,12 +1067,27 @@ mod tests {
versioning_suspended: false, versioning_suspended: false,
locking: true, locking: true,
replication: true, replication: true,
quota: Some(1024),
}; };
assert!(details.versioning); assert!(details.versioning);
assert!(!details.versioning_suspended); assert!(!details.versioning_suspended);
assert!(details.locking); assert!(details.locking);
assert!(details.replication); assert!(details.replication);
assert_eq!(details.quota, Some(1024));
}
#[test]
fn bucket_details_serializes_quota_only_when_configured() {
let with_quota = BucketDetails {
quota: Some(1024),
..Default::default()
};
let value = serde_json::to_value(with_quota).expect("bucket details should serialize");
assert_eq!(value["quota"], 1024);
let without_quota = serde_json::to_value(BucketDetails::default()).expect("bucket details should serialize");
assert!(without_quota.get("quota").is_none());
} }
#[test] #[test]
+8 -1
View File
@@ -104,6 +104,13 @@ async fn bucket_replication_enabled(bucket: &str) -> bool {
.is_some_and(|(config, _)| replication_config_enabled(&config)) .is_some_and(|(config, _)| replication_config_enabled(&config))
} }
async fn bucket_quota_limit(bucket: &str) -> Option<u64> {
metadata_sys::get_quota_config(bucket)
.await
.ok()
.and_then(|(config, _)| config.get_quota_limit())
}
#[async_trait::async_trait] #[async_trait::async_trait]
impl Operation for AccountInfoHandler { impl Operation for AccountInfoHandler {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> { async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
@@ -258,7 +265,6 @@ impl Operation for AccountInfoHandler {
for bucket in buckets.iter() { for bucket in buckets.iter() {
let (rd, wr) = is_allow(bucket.name.clone()).await; let (rd, wr) = is_allow(bucket.name.clone()).await;
if rd || wr { if rd || wr {
// TODO: BucketQuotaSys
let mut bucket_info = rustfs_madmin::BucketAccessInfo { let mut bucket_info = rustfs_madmin::BucketAccessInfo {
name: bucket.name.clone(), name: bucket.name.clone(),
details: Some(rustfs_madmin::BucketDetails { details: Some(rustfs_madmin::BucketDetails {
@@ -266,6 +272,7 @@ impl Operation for AccountInfoHandler {
versioning_suspended: BucketVersioningSys::suspended(bucket.name.as_str()).await, versioning_suspended: BucketVersioningSys::suspended(bucket.name.as_str()).await,
locking: bucket_locking_enabled(bucket.name.as_str()).await, locking: bucket_locking_enabled(bucket.name.as_str()).await,
replication: bucket_replication_enabled(bucket.name.as_str()).await, replication: bucket_replication_enabled(bucket.name.as_str()).await,
quota: bucket_quota_limit(bucket.name.as_str()).await,
}), }),
created: bucket.created, created: bucket.created,
access: rustfs_madmin::AccountAccess { read: rd, write: wr }, access: rustfs_madmin::AccountAccess { read: rd, write: wr },