From 2b42d0e9eba874261cfe04e8dada79942d9b9633 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Wed, 27 Nov 2024 16:47:23 -0800 Subject: [PATCH] API updates pulled from 7187 as I built it --- clients/sled-agent-client/src/lib.rs | 3 + common/src/api/external/mod.rs | 18 +++ nexus/external-api/output/nexus_tags.txt | 1 + nexus/external-api/src/lib.rs | 17 ++- nexus/src/external_api/http_entrypoints.rs | 30 ++++- nexus/types/src/external_api/params.rs | 2 +- openapi/nexus.json | 145 ++++++++++++++++++--- sled-agent/api/src/lib.rs | 19 +-- 8 files changed, 196 insertions(+), 39 deletions(-) diff --git a/clients/sled-agent-client/src/lib.rs b/clients/sled-agent-client/src/lib.rs index f2eb957650..f818f241fa 100644 --- a/clients/sled-agent-client/src/lib.rs +++ b/clients/sled-agent-client/src/lib.rs @@ -75,12 +75,15 @@ progenitor::generate_api!( RouterVersion = omicron_common::api::internal::shared::RouterVersion, SledRole = nexus_sled_agent_shared::inventory::SledRole, SourceNatConfig = omicron_common::api::internal::shared::SourceNatConfig, + SupportBundleGetQueryParams = omicron_common::api::external::SupportBundleGetQueryParams, + SupportBundleQueryType = omicron_common::api::external::SupportBundleQueryType, SwitchLocation = omicron_common::api::external::SwitchLocation, TypedUuidForDatasetKind = omicron_uuid_kinds::DatasetUuid, TypedUuidForInstanceKind = omicron_uuid_kinds::InstanceUuid, TypedUuidForOmicronZoneKind = omicron_uuid_kinds::OmicronZoneUuid, TypedUuidForPropolisKind = omicron_uuid_kinds::PropolisUuid, TypedUuidForSledKind = omicron_uuid_kinds::SledUuid, + TypedUuidForSupportBundleKind = omicron_uuid_kinds::SupportBundleUuid, TypedUuidForZpoolKind = omicron_uuid_kinds::ZpoolUuid, Vni = omicron_common::api::external::Vni, ZpoolKind = omicron_common::zpool_name::ZpoolKind, diff --git a/common/src/api/external/mod.rs b/common/src/api/external/mod.rs index 38a9de0564..6db4d5c189 100644 --- a/common/src/api/external/mod.rs +++ b/common/src/api/external/mod.rs @@ -3090,6 +3090,24 @@ pub enum ImportExportPolicy { Allow(Vec), } +/// Query parameters for reading the support bundle +#[derive(Deserialize, Serialize, JsonSchema)] +pub struct SupportBundleGetQueryParams { + pub query_type: SupportBundleQueryType, +} + +/// Describes the type of access to the support bundle +#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum SupportBundleQueryType { + /// Access the whole support bundle + Whole, + /// Access the names of all files within the support bundle + Index, + /// Access a specific file within the support bundle + Path { file_path: String }, +} + #[cfg(test)] mod test { use serde::Deserialize; diff --git a/nexus/external-api/output/nexus_tags.txt b/nexus/external-api/output/nexus_tags.txt index 0526a10b33..11e942496e 100644 --- a/nexus/external-api/output/nexus_tags.txt +++ b/nexus/external-api/output/nexus_tags.txt @@ -33,6 +33,7 @@ probe_view GET /experimental/v1/probes/{probe support_bundle_create POST /experimental/v1/system/support-bundles support_bundle_delete DELETE /experimental/v1/system/support-bundles/{support_bundle} support_bundle_download GET /experimental/v1/system/support-bundles/{support_bundle}/download +support_bundle_head HEAD /experimental/v1/system/support-bundles/{support_bundle}/download support_bundle_list GET /experimental/v1/system/support-bundles support_bundle_view GET /experimental/v1/system/support-bundles/{support_bundle} diff --git a/nexus/external-api/src/lib.rs b/nexus/external-api/src/lib.rs index 2860db740e..4c65825396 100644 --- a/nexus/external-api/src/lib.rs +++ b/nexus/external-api/src/lib.rs @@ -2793,6 +2793,19 @@ pub trait NexusExternalApi { async fn support_bundle_download( rqctx: RequestContext, path_params: Path, + body: TypedBody, + ) -> Result, HttpError>; + + /// Download the metadata of a single support bundle + #[endpoint { + method = HEAD, + path = "/experimental/v1/system/support-bundles/{support_bundle}/download", + tags = ["hidden"], // system/support-bundles: only one tag is allowed + }] + async fn support_bundle_head( + rqctx: RequestContext, + path_params: Path, + body: TypedBody, ) -> Result, HttpError>; /// Create a new support bundle @@ -2803,7 +2816,7 @@ pub trait NexusExternalApi { }] async fn support_bundle_create( rqctx: RequestContext, - ) -> Result, HttpError>; + ) -> Result, HttpError>; /// Delete an existing support bundle /// @@ -2817,7 +2830,7 @@ pub trait NexusExternalApi { async fn support_bundle_delete( rqctx: RequestContext, path_params: Path, - ) -> Result, HttpError>; + ) -> Result; // Probes (experimental) diff --git a/nexus/src/external_api/http_entrypoints.rs b/nexus/src/external_api/http_entrypoints.rs index 004a3482c5..bab84e8c38 100644 --- a/nexus/src/external_api/http_entrypoints.rs +++ b/nexus/src/external_api/http_entrypoints.rs @@ -81,6 +81,7 @@ use omicron_common::api::external::NameOrId; use omicron_common::api::external::Probe; use omicron_common::api::external::RouterRoute; use omicron_common::api::external::RouterRouteKind; +use omicron_common::api::external::SupportBundleGetQueryParams; use omicron_common::api::external::SwitchPort; use omicron_common::api::external::SwitchPortSettings; use omicron_common::api::external::SwitchPortSettingsView; @@ -6049,6 +6050,31 @@ impl NexusExternalApi for NexusExternalApiImpl { async fn support_bundle_download( rqctx: RequestContext, _path_params: Path, + _body: TypedBody, + ) -> Result, HttpError> { + let apictx = rqctx.context(); + let handler = async { + let nexus = &apictx.context.nexus; + + let opctx = + crate::context::op_context_for_external_api(&rqctx).await?; + + Err(nexus + .unimplemented_todo(&opctx, crate::app::Unimpl::Public) + .await + .into()) + }; + apictx + .context + .external_latencies + .instrument_dropshot_handler(&rqctx, handler) + .await + } + + async fn support_bundle_head( + rqctx: RequestContext, + _path_params: Path, + _body: TypedBody, ) -> Result, HttpError> { let apictx = rqctx.context(); let handler = async { @@ -6071,7 +6097,7 @@ impl NexusExternalApi for NexusExternalApiImpl { async fn support_bundle_create( rqctx: RequestContext, - ) -> Result, HttpError> { + ) -> Result, HttpError> { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; @@ -6094,7 +6120,7 @@ impl NexusExternalApi for NexusExternalApiImpl { async fn support_bundle_delete( rqctx: RequestContext, _path_params: Path, - ) -> Result, HttpError> { + ) -> Result { let apictx = rqctx.context(); let handler = async { let nexus = &apictx.context.nexus; diff --git a/nexus/types/src/external_api/params.rs b/nexus/types/src/external_api/params.rs index 0929b2c04b..4a4af8b052 100644 --- a/nexus/types/src/external_api/params.rs +++ b/nexus/types/src/external_api/params.rs @@ -89,8 +89,8 @@ path_param!(SshKeyPath, ssh_key, "SSH key"); path_param!(AddressLotPath, address_lot, "address lot"); path_param!(ProbePath, probe, "probe"); path_param!(CertificatePath, certificate, "certificate"); -path_param!(SupportBundlePath, support_bundle, "support bundle"); +id_path_param!(SupportBundlePath, support_bundle, "support bundle"); id_path_param!(GroupPath, group_id, "group"); // TODO: The hardware resources should be represented by its UUID or a hardware diff --git a/openapi/nexus.json b/openapi/nexus.json index c9da9dac5a..fe91ff98e3 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -366,8 +366,8 @@ "summary": "Create a new support bundle", "operationId": "support_bundle_create", "responses": { - "200": { - "description": "successful operation", + "201": { + "description": "successful creation", "content": { "application/json": { "schema": { @@ -396,10 +396,11 @@ { "in": "path", "name": "support_bundle", - "description": "Name or ID of the support bundle", + "description": "ID of the support bundle", "required": true, "schema": { - "$ref": "#/components/schemas/NameOrId" + "type": "string", + "format": "uuid" } } ], @@ -433,23 +434,17 @@ { "in": "path", "name": "support_bundle", - "description": "Name or ID of the support bundle", + "description": "ID of the support bundle", "required": true, "schema": { - "$ref": "#/components/schemas/NameOrId" + "type": "string", + "format": "uuid" } } ], "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SupportBundleInfo" - } - } - } + "204": { + "description": "successful deletion" }, "4XX": { "$ref": "#/components/responses/Error" @@ -471,13 +466,63 @@ { "in": "path", "name": "support_bundle", - "description": "Name or ID of the support bundle", + "description": "ID of the support bundle", "required": true, "schema": { - "$ref": "#/components/schemas/NameOrId" + "type": "string", + "format": "uuid" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SupportBundleGetQueryParams" + } + } + }, + "required": true + }, + "responses": { + "default": { + "description": "", + "content": { + "*/*": { + "schema": {} + } + } + } + } + }, + "head": { + "tags": [ + "hidden" + ], + "summary": "Download the metadata of a single support bundle", + "operationId": "support_bundle_head", + "parameters": [ + { + "in": "path", + "name": "support_bundle", + "description": "ID of the support bundle", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SupportBundleGetQueryParams" + } + } + }, + "required": true + }, "responses": { "default": { "description": "", @@ -20199,6 +20244,18 @@ "items" ] }, + "SupportBundleGetQueryParams": { + "description": "Query parameters for reading the support bundle", + "type": "object", + "properties": { + "query_type": { + "$ref": "#/components/schemas/SupportBundleQueryType" + } + }, + "required": [ + "query_type" + ] + }, "SupportBundleInfo": { "type": "object", "properties": { @@ -20248,6 +20305,60 @@ "items" ] }, + "SupportBundleQueryType": { + "description": "Describes the type of access to the support bundle", + "oneOf": [ + { + "description": "Access the whole support bundle", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "whole" + ] + } + }, + "required": [ + "type" + ] + }, + { + "description": "Access the names of all files within the support bundle", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "index" + ] + } + }, + "required": [ + "type" + ] + }, + { + "description": "Access a specific file within the support bundle", + "type": "object", + "properties": { + "file_path": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "path" + ] + } + }, + "required": [ + "file_path", + "type" + ] + } + ] + }, "SupportBundleState": { "oneOf": [ { diff --git a/sled-agent/api/src/lib.rs b/sled-agent/api/src/lib.rs index 634640079a..be0dbdf1d8 100644 --- a/sled-agent/api/src/lib.rs +++ b/sled-agent/api/src/lib.rs @@ -702,23 +702,8 @@ pub struct SupportBundleGetHeaders { range: String, } -/// Query parameters for reading the support bundle -#[derive(Deserialize, Serialize, JsonSchema)] -pub struct SupportBundleGetQueryParams { - pub query_type: SupportBundleQueryType, -} - -/// Describes the type of access to the support bundle -#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)] -#[serde(tag = "type", rename_all = "snake_case")] -pub enum SupportBundleQueryType { - /// Access the whole support bundle - Whole, - /// Access the names of all files within the support bundle - Index, - /// Access a specific file within the support bundle - Path { file_path: String }, -} +pub use omicron_common::api::external::SupportBundleGetQueryParams; +pub use omicron_common::api::external::SupportBundleQueryType; #[derive(Deserialize, Debug, Serialize, JsonSchema, PartialEq)] #[serde(rename_all = "snake_case")]