Skip to content

Commit eda9b97

Browse files
committed
Support Bundle: Add user comment support
1 parent 643eb74 commit eda9b97

File tree

19 files changed

+385
-3
lines changed

19 files changed

+385
-3
lines changed

dev-tools/omdb/src/bin/omdb/nexus.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4009,6 +4009,7 @@ async fn cmd_nexus_support_bundles_list(
40094009
reason_for_creation: String,
40104010
reason_for_failure: String,
40114011
state: String,
4012+
user_comment: String,
40124013
}
40134014
let rows = support_bundles.into_iter().map(|sb| SupportBundleInfo {
40144015
id: *sb.id,
@@ -4018,6 +4019,7 @@ async fn cmd_nexus_support_bundles_list(
40184019
.reason_for_failure
40194020
.unwrap_or_else(|| "-".to_string()),
40204021
state: format!("{:?}", sb.state),
4022+
user_comment: sb.user_comment.unwrap_or_else(|| "-".to_string()),
40214023
});
40224024
let table = tabled::Table::new(rows)
40234025
.with(tabled::settings::Style::empty())

nexus/db-model/src/schema_versions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock};
1616
///
1717
/// This must be updated when you change the database schema. Refer to
1818
/// schema/crdb/README.adoc in the root of this repository for details.
19-
pub const SCHEMA_VERSION: Version = Version::new(161, 0, 0);
19+
pub const SCHEMA_VERSION: Version = Version::new(162, 0, 0);
2020

2121
/// List of all past database schema versions, in *reverse* order
2222
///
@@ -28,6 +28,7 @@ static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = LazyLock::new(|| {
2828
// | leaving the first copy as an example for the next person.
2929
// v
3030
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
31+
KnownVersion::new(162, "bundle-user-comment"),
3132
KnownVersion::new(161, "inv_cockroachdb_status"),
3233
KnownVersion::new(160, "tuf-trust-root"),
3334
KnownVersion::new(159, "sled-config-desired-host-phase-2"),

nexus/db-model/src/support_bundle.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub struct SupportBundle {
9595
pub zpool_id: DbTypedUuid<ZpoolKind>,
9696
pub dataset_id: DbTypedUuid<DatasetKind>,
9797
pub assigned_nexus: Option<DbTypedUuid<OmicronZoneKind>>,
98+
pub user_comment: Option<String>,
9899
}
99100

100101
impl SupportBundle {
@@ -113,6 +114,7 @@ impl SupportBundle {
113114
zpool_id: zpool_id.into(),
114115
dataset_id: dataset_id.into(),
115116
assigned_nexus: Some(nexus_id.into()),
117+
user_comment: None,
116118
}
117119
}
118120

@@ -128,6 +130,7 @@ impl From<SupportBundle> for SupportBundleView {
128130
time_created: bundle.time_created,
129131
reason_for_creation: bundle.reason_for_creation,
130132
reason_for_failure: bundle.reason_for_failure,
133+
user_comment: bundle.user_comment,
131134
state: bundle.state.into(),
132135
}
133136
}

nexus/db-queries/src/db/datastore/support_bundle.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,42 @@ impl DataStore {
433433
}
434434
}
435435

436+
/// Updates the user comment of a support bundle.
437+
///
438+
/// Returns:
439+
/// - "Ok" if the bundle was updated successfully.
440+
/// - "Err::InvalidRequest" if the comment exceeds the maximum length.
441+
pub async fn support_bundle_update_user_comment(
442+
&self,
443+
opctx: &OpContext,
444+
authz_bundle: &authz::SupportBundle,
445+
user_comment: Option<String>,
446+
) -> Result<(), Error> {
447+
opctx.authorize(authz::Action::Modify, authz_bundle).await?;
448+
449+
if let Some(ref comment) = user_comment {
450+
if comment.len() > 4096 {
451+
return Err(Error::invalid_request(
452+
"User comment cannot exceed 4096 bytes",
453+
));
454+
}
455+
}
456+
457+
use nexus_db_schema::schema::support_bundle::dsl;
458+
459+
let id = authz_bundle.id().into_untyped_uuid();
460+
let conn = self.pool_connection_authorized(opctx).await?;
461+
diesel::update(dsl::support_bundle)
462+
.filter(dsl::id.eq(id))
463+
.set(dsl::user_comment.eq(user_comment))
464+
.execute_async(&*conn)
465+
.await
466+
.map(|_rows_modified| ())
467+
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
468+
469+
Ok(())
470+
}
471+
436472
/// Deletes a support bundle.
437473
///
438474
/// This should only be invoked after all storage for the support bundle has

nexus/db-schema/src/schema.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,7 @@ table! {
14701470
dataset_id -> Uuid,
14711471

14721472
assigned_nexus -> Nullable<Uuid>,
1473+
user_comment -> Nullable<Text>,
14731474
}
14741475
}
14751476

nexus/external-api/output/nexus_tags.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ support_bundle_head HEAD /experimental/v1/system/suppor
6262
support_bundle_head_file HEAD /experimental/v1/system/support-bundles/{bundle_id}/download/{file}
6363
support_bundle_index GET /experimental/v1/system/support-bundles/{bundle_id}/index
6464
support_bundle_list GET /experimental/v1/system/support-bundles
65+
support_bundle_update PUT /experimental/v1/system/support-bundles/{bundle_id}
6566
support_bundle_view GET /experimental/v1/system/support-bundles/{bundle_id}
6667
system_update_get_repository GET /v1/system/update/repository/{system_version}
6768
system_update_put_repository PUT /v1/system/update/repository

nexus/external-api/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,6 +3335,18 @@ pub trait NexusExternalApi {
33353335
path_params: Path<params::SupportBundlePath>,
33363336
) -> Result<HttpResponseDeleted, HttpError>;
33373337

3338+
/// Update a support bundle
3339+
#[endpoint {
3340+
method = PUT,
3341+
path = "/experimental/v1/system/support-bundles/{bundle_id}",
3342+
tags = ["experimental"], // system/support-bundles: only one tag is allowed
3343+
}]
3344+
async fn support_bundle_update(
3345+
rqctx: RequestContext<Self::Context>,
3346+
path_params: Path<params::SupportBundlePath>,
3347+
body: TypedBody<params::SupportBundleUpdate>,
3348+
) -> Result<HttpResponseOk<shared::SupportBundleInfo>, HttpError>;
3349+
33383350
// Probes (experimental)
33393351

33403352
/// List instrumentation probes

nexus/internal-api/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,17 @@ pub trait NexusInternalApi {
677677
path_params: Path<params::SupportBundlePath>,
678678
) -> Result<HttpResponseDeleted, HttpError>;
679679

680+
/// Update a support bundle
681+
#[endpoint {
682+
method = PUT,
683+
path = "/experimental/v1/system/support-bundles/{bundle_id}",
684+
}]
685+
async fn support_bundle_update(
686+
rqctx: RequestContext<Self::Context>,
687+
path_params: Path<params::SupportBundlePath>,
688+
body: TypedBody<params::SupportBundleUpdate>,
689+
) -> Result<HttpResponseOk<shared::SupportBundleInfo>, HttpError>;
690+
680691
/// Get all the probes associated with a given sled.
681692
#[endpoint {
682693
method = GET,

nexus/src/app/support_bundles.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,27 @@ impl super::Nexus {
224224
.await?;
225225
Ok(())
226226
}
227+
228+
pub async fn support_bundle_update_user_comment(
229+
&self,
230+
opctx: &OpContext,
231+
id: SupportBundleUuid,
232+
user_comment: Option<String>,
233+
) -> LookupResult<SupportBundle> {
234+
let (authz_bundle, ..) = LookupPath::new(opctx, &self.db_datastore)
235+
.support_bundle(id)
236+
.lookup_for(authz::Action::Modify)
237+
.await?;
238+
239+
self.db_datastore
240+
.support_bundle_update_user_comment(
241+
&opctx,
242+
&authz_bundle,
243+
user_comment,
244+
)
245+
.await?;
246+
247+
// Return the updated bundle
248+
self.support_bundle_view(opctx, id).await
249+
}
227250
}

nexus/src/external_api/http_entrypoints.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7493,6 +7493,37 @@ impl NexusExternalApi for NexusExternalApiImpl {
74937493
.await
74947494
}
74957495

7496+
async fn support_bundle_update(
7497+
rqctx: RequestContext<Self::Context>,
7498+
path_params: Path<params::SupportBundlePath>,
7499+
body: TypedBody<params::SupportBundleUpdate>,
7500+
) -> Result<HttpResponseOk<shared::SupportBundleInfo>, HttpError> {
7501+
let apictx = rqctx.context();
7502+
let handler = async {
7503+
let nexus = &apictx.context.nexus;
7504+
let path = path_params.into_inner();
7505+
let update = body.into_inner();
7506+
7507+
let opctx =
7508+
crate::context::op_context_for_external_api(&rqctx).await?;
7509+
7510+
let bundle = nexus
7511+
.support_bundle_update_user_comment(
7512+
&opctx,
7513+
SupportBundleUuid::from_untyped_uuid(path.bundle_id),
7514+
update.user_comment,
7515+
)
7516+
.await?;
7517+
7518+
Ok(HttpResponseOk(bundle.into()))
7519+
};
7520+
apictx
7521+
.context
7522+
.external_latencies
7523+
.instrument_dropshot_handler(&rqctx, handler)
7524+
.await
7525+
}
7526+
74967527
async fn probe_list(
74977528
rqctx: RequestContext<ApiContext>,
74987529
query_params: Query<PaginatedByNameOrId<params::ProjectSelector>>,

0 commit comments

Comments
 (0)