publish bucket creation date in admin api and CLI

This commit is contained in:
Alex Auvolat 2025-04-17 10:29:23 +02:00
parent 2d1c073d2f
commit 2f21181ccb
4 changed files with 32 additions and 7 deletions

View File

@ -2280,6 +2280,7 @@
"type": "object",
"required": [
"id",
"created",
"globalAliases",
"websiteAccess",
"keys",
@ -2297,6 +2298,11 @@
"format": "int64",
"description": "Total number of bytes used by objects in this bucket"
},
"created": {
"type": "string",
"format": "date-time",
"description": "Bucket creation date"
},
"globalAliases": {
"type": "array",
"items": {
@ -2873,10 +2879,15 @@
"type": "object",
"required": [
"id",
"created",
"globalAliases",
"localAliases"
],
"properties": {
"created": {
"type": "string",
"format": "date-time"
},
"globalAliases": {
"type": "array",
"items": {

View File

@ -3,6 +3,7 @@ use std::convert::TryFrom;
use std::net::SocketAddr;
use std::sync::Arc;
use chrono::{DateTime, Utc};
use paste::paste;
use serde::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
@ -321,11 +322,11 @@ pub struct GetAdminTokenInfoResponse {
/// Identifier of the admin token (which is also a prefix of the full bearer token)
pub id: Option<String>,
/// Creation date
pub created: Option<chrono::DateTime<chrono::Utc>>,
pub created: Option<DateTime<Utc>>,
/// Name of the admin API token
pub name: String,
/// Expiration time and date, formatted according to RFC 3339
pub expiration: Option<chrono::DateTime<chrono::Utc>>,
pub expiration: Option<DateTime<Utc>>,
/// Whether this admin token is expired already
pub expired: bool,
/// Scope of the admin API token, a list of admin endpoint names (such as
@ -364,7 +365,7 @@ pub struct UpdateAdminTokenRequestBody {
/// Name of the admin API token
pub name: Option<String>,
/// Expiration time and date, formatted according to RFC 3339
pub expiration: Option<chrono::DateTime<chrono::Utc>>,
pub expiration: Option<DateTime<Utc>>,
/// Scope of the admin API token, a list of admin endpoint names (such as
/// `GetClusterStatus`, etc), or the special value `*` to allow all
/// admin endpoints. **WARNING:** Granting a scope of `CreateAdminToken` or
@ -759,6 +760,7 @@ pub struct ListBucketsResponse(pub Vec<ListBucketsResponseItem>);
#[serde(rename_all = "camelCase")]
pub struct ListBucketsResponseItem {
pub id: String,
pub created: DateTime<Utc>,
pub global_aliases: Vec<String>,
pub local_aliases: Vec<BucketLocalAlias>,
}
@ -788,6 +790,8 @@ pub struct GetBucketInfoRequest {
pub struct GetBucketInfoResponse {
/// Identifier of the bucket
pub id: String,
/// Bucket creation date
pub created: DateTime<Utc>,
/// List of global aliases for this bucket
pub global_aliases: Vec<String>,
/// Whether website acces is enabled for this bucket
@ -932,7 +936,7 @@ pub struct InspectObjectVersion {
/// Version ID
pub uuid: String,
/// Creation timestamp of this object version
pub timestamp: chrono::DateTime<chrono::Utc>,
pub timestamp: DateTime<Utc>,
/// Whether this object version was created with SSE-C encryption
pub encrypted: bool,
/// Whether this object version is still uploading

View File

@ -48,6 +48,8 @@ impl RequestHandler for ListBucketsRequest {
let state = b.state.as_option().unwrap();
ListBucketsResponseItem {
id: hex::encode(b.id),
created: DateTime::from_timestamp_millis(state.creation_date as i64)
.expect("invalid timestamp stored in db"),
global_aliases: state
.aliases
.items()
@ -677,6 +679,8 @@ async fn bucket_info_results(
let quotas = state.quotas.get();
let res = GetBucketInfoResponse {
id: hex::encode(bucket.id),
created: DateTime::from_timestamp_millis(state.creation_date as i64)
.expect("invalid timestamp stored in db"),
global_aliases: state
.aliases
.items()

View File

@ -1,6 +1,8 @@
//use bytesize::ByteSize;
use format_table::format_table;
use chrono::Local;
use garage_util::error::*;
use garage_api_admin::api::*;
@ -29,13 +31,16 @@ impl Cli {
}
pub async fn cmd_list_buckets(&self) -> Result<(), Error> {
let buckets = self.api_request(ListBucketsRequest).await?;
let mut buckets = self.api_request(ListBucketsRequest).await?;
let mut table = vec!["ID\tGlobal aliases\tLocal aliases".to_string()];
buckets.0.sort_by_key(|x| x.created);
let mut table = vec!["ID\tCreated\tGlobal aliases\tLocal aliases".to_string()];
for bucket in buckets.0.iter() {
table.push(format!(
"{:.16}\t{}\t{}",
"{:.16}\t{}\t{}\t{}",
bucket.id,
bucket.created.with_timezone(&Local).date_naive(),
table_list_abbr(&bucket.global_aliases),
table_list_abbr(
bucket
@ -484,6 +489,7 @@ fn print_bucket_info(bucket: &GetBucketInfoResponse) {
let mut info = vec![
format!("Bucket:\t{}", bucket.id),
format!("Created:\t{}", bucket.created.with_timezone(&Local)),
String::new(),
{
let size = bytesize::ByteSize::b(bucket.bytes as u64);