From 5e7307cbf36215e4071978dbf6815b97acd3c8bc Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Sun, 6 Apr 2025 14:19:48 +0200 Subject: [PATCH] admin api: add comments for InspectObject --- doc/api/garage-admin-v2.json | 51 +++++++++++++++++++++++++----------- src/api/admin/api.rs | 19 ++++++++++++++ src/api/admin/bucket.rs | 2 +- src/api/admin/error.rs | 8 +++++- src/api/admin/openapi.rs | 8 ++++++ 5 files changed, 71 insertions(+), 17 deletions(-) diff --git a/doc/api/garage-admin-v2.json b/doc/api/garage-admin-v2.json index a7bea179..7819a0a6 100644 --- a/doc/api/garage-admin-v2.json +++ b/doc/api/garage-admin-v2.json @@ -1059,7 +1059,7 @@ "tags": [ "Bucket" ], - "description": "\nReturns detailed information about an object in a bucket, including its internal state in Garage.\n ", + "description": "\nReturns detailed information about an object in a bucket, including its internal state in Garage.\n\nThis API call can be used to list the data blocks referenced by an object,\nas well as to view metadata associated to the object.\n\nThis call may return a list of more than one version for the object, for instance in the\ncase where there is a currently stored version of the object, and a newer version whose\nupload is in progress and not yet finished.\n ", "operationId": "InspectObject", "parameters": [ { @@ -1090,6 +1090,9 @@ } } }, + "404": { + "description": "Object not found" + }, "500": { "description": "Internal server error" } @@ -2623,21 +2626,25 @@ ], "properties": { "hash": { - "type": "string" + "type": "string", + "description": "Hash (blake2 sum) of the block's data" }, "offset": { "type": "integer", "format": "int64", + "description": "Offset of this block within the part", "minimum": 0 }, "partNumber": { "type": "integer", "format": "int64", + "description": "Part number of the part containing this block, for multipart uploads", "minimum": 0 }, "size": { "type": "integer", "format": "int64", + "description": "Length of the blocks's data", "minimum": 0 } } @@ -2651,16 +2658,19 @@ ], "properties": { "bucketId": { - "type": "string" + "type": "string", + "description": "ID of the bucket containing the inspected object" }, "key": { - "type": "string" + "type": "string", + "description": "Key of the inspected object" }, "versions": { "type": "array", "items": { "$ref": "#/components/schemas/InspectObjectVersion" - } + }, + "description": "List of versions currently stored for this object" } } }, @@ -2677,25 +2687,30 @@ ], "properties": { "aborted": { - "type": "boolean" + "type": "boolean", + "description": "Whether this is an aborted upload" }, "blocks": { "type": "array", "items": { "$ref": "#/components/schemas/InspectObjectBlock" - } + }, + "description": "List of data blocks for this object version" }, "deleteMarker": { - "type": "boolean" + "type": "boolean", + "description": "Whether this version is a delete marker (a tombstone indicating that a previous version of\nthe object has been deleted)" }, "encrypted": { - "type": "boolean" + "type": "boolean", + "description": "Whether this object version was created with SSE-C encryption" }, "etag": { "type": [ "string", "null" - ] + ], + "description": "Etag of this object version" }, "headers": { "type": "array", @@ -2710,10 +2725,12 @@ "type": "string" } ] - } + }, + "description": "Metadata (HTTP headers) associated with this object version" }, "inline": { - "type": "boolean" + "type": "boolean", + "description": "Whether the object's data is stored inline (for small objects)" }, "size": { "type": [ @@ -2721,17 +2738,21 @@ "null" ], "format": "int64", + "description": "Size of the object, in bytes", "minimum": 0 }, "timestamp": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "Creation timestamp of this object version" }, "uploading": { - "type": "boolean" + "type": "boolean", + "description": "Whether this object version is still uploading" }, "uuid": { - "type": "string" + "type": "string", + "description": "Version ID" } } }, diff --git a/src/api/admin/api.rs b/src/api/admin/api.rs index 97f4583b..ffb9456b 100644 --- a/src/api/admin/api.rs +++ b/src/api/admin/api.rs @@ -918,25 +918,40 @@ pub struct InspectObjectRequest { #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct InspectObjectResponse { + /// ID of the bucket containing the inspected object pub bucket_id: String, + /// Key of the inspected object pub key: String, + /// List of versions currently stored for this object pub versions: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Default)] #[serde(rename_all = "camelCase")] pub struct InspectObjectVersion { + /// Version ID pub uuid: String, + /// Creation timestamp of this object version pub timestamp: chrono::DateTime, + /// Whether this object version was created with SSE-C encryption pub encrypted: bool, + /// Whether this object version is still uploading pub uploading: bool, + /// Whether this is an aborted upload pub aborted: bool, + /// Whether this version is a delete marker (a tombstone indicating that a previous version of + /// the object has been deleted) pub delete_marker: bool, + /// Whether the object's data is stored inline (for small objects) pub inline: bool, + /// Size of the object, in bytes pub size: Option, + /// Etag of this object version pub etag: Option, + /// Metadata (HTTP headers) associated with this object version #[serde(default, skip_serializing_if = "Vec::is_empty")] pub headers: Vec<(String, String)>, + /// List of data blocks for this object version #[serde(default, skip_serializing_if = "Vec::is_empty")] pub blocks: Vec, } @@ -944,9 +959,13 @@ pub struct InspectObjectVersion { #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct InspectObjectBlock { + /// Part number of the part containing this block, for multipart uploads pub part_number: u64, + /// Offset of this block within the part pub offset: u64, + /// Hash (blake2 sum) of the block's data pub hash: String, + /// Length of the blocks's data pub size: u64, } diff --git a/src/api/admin/bucket.rs b/src/api/admin/bucket.rs index d825dfb4..af26200b 100644 --- a/src/api/admin/bucket.rs +++ b/src/api/admin/bucket.rs @@ -365,7 +365,7 @@ impl RequestHandler for InspectObjectRequest { .object_table .get(&bucket_id, &self.key) .await? - .ok_or_else(|| Error::bad_request("object not found"))?; + .ok_or_else(|| Error::NoSuchKey)?; let mut versions = vec![]; for obj_ver in object.versions().iter() { diff --git a/src/api/admin/error.rs b/src/api/admin/error.rs index f12a936e..8fbbc895 100644 --- a/src/api/admin/error.rs +++ b/src/api/admin/error.rs @@ -37,6 +37,10 @@ pub enum Error { #[error(display = "Worker not found: {}", _0)] NoSuchWorker(u64), + /// The object requested don't exists + #[error(display = "Key not found")] + NoSuchKey, + /// In Import key, the key already exists #[error( display = "Key {} already exists in data store. Even if it is deleted, we can't let you create a new key with the same ID. Sorry.", @@ -69,6 +73,7 @@ impl Error { Error::NoSuchWorker(_) => "NoSuchWorker", Error::NoSuchBlock(_) => "NoSuchBlock", Error::KeyAlreadyExists(_) => "KeyAlreadyExists", + Error::NoSuchKey => "NoSuchKey", } } } @@ -81,7 +86,8 @@ impl ApiError for Error { Error::NoSuchAdminToken(_) | Error::NoSuchAccessKey(_) | Error::NoSuchWorker(_) - | Error::NoSuchBlock(_) => StatusCode::NOT_FOUND, + | Error::NoSuchBlock(_) + | Error::NoSuchKey => StatusCode::NOT_FOUND, Error::KeyAlreadyExists(_) => StatusCode::CONFLICT, } } diff --git a/src/api/admin/openapi.rs b/src/api/admin/openapi.rs index 6e9cb5e1..f1b90676 100644 --- a/src/api/admin/openapi.rs +++ b/src/api/admin/openapi.rs @@ -514,10 +514,18 @@ fn CleanupIncompleteUploads() -> () {} tag = "Bucket", description = " Returns detailed information about an object in a bucket, including its internal state in Garage. + +This API call can be used to list the data blocks referenced by an object, +as well as to view metadata associated to the object. + +This call may return a list of more than one version for the object, for instance in the +case where there is a currently stored version of the object, and a newer version whose +upload is in progress and not yet finished. ", params(InspectObjectRequest), responses( (status = 200, description = "Returns exhaustive information about the object", body = InspectObjectResponse), + (status = 404, description = "Object not found"), (status = 500, description = "Internal server error") ), )]