use axum::{Json, extract::Query, http::StatusCode, response::IntoResponse};
use super::{
ErrorResponse, RequestCtx, SiteHeader, resolve_xnames_from_request,
serialize_or_500, to_handler_error,
};
use crate::service;
pub use manta_shared::types::api::queries::KernelParametersQuery;
#[utoipa::path(get, path = "/kernel-parameters", tag = "kernel-parameters",
params(KernelParametersQuery, SiteHeader),
security(("bearerAuth" = [])),
responses(
(status = 200, description = "Kernel parameters", body = Vec<manta_backend_dispatcher::types::bss::BootParameters>),
(status = 401, description = "Unauthorized", body = ErrorResponse),
(status = 500, description = "Internal error", body = ErrorResponse),
)
)]
#[tracing::instrument(skip_all)]
pub async fn get_kernel_parameters(
ctx: RequestCtx,
Query(q): Query<KernelParametersQuery>,
) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
let infra = ctx.infra();
let params = service::kernel_parameters::GetKernelParametersParams {
group_name: q.hsm_group,
nodes: q.nodes,
settings_group_name: None,
};
let kernel_params = service::kernel_parameters::get_kernel_parameters(
&infra, &ctx.token, ¶ms,
)
.await
.map_err(to_handler_error)?;
Ok(Json(kernel_params))
}
pub use manta_shared::types::api::kernel_parameters::{
ApplyKernelParametersRequest, KernelParamOp,
};
#[utoipa::path(post, path = "/kernel-parameters/apply", tag = "kernel-parameters",
params(SiteHeader),
request_body = ApplyKernelParametersRequest,
security(("bearerAuth" = [])),
responses(
// dry_run/real result union — kept as Value until the union shape is formalised
(status = 200, description = "Kernel parameters applied or preview", body = serde_json::Value),
(status = 400, description = "Bad request", body = ErrorResponse),
(status = 401, description = "Unauthorized", body = ErrorResponse),
(status = 500, description = "Internal error", body = ErrorResponse),
)
)]
#[tracing::instrument(skip_all)]
pub async fn apply_kernel_parameters(
ctx: RequestCtx,
Json(body): Json<ApplyKernelParametersRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
let infra = ctx.infra();
let xnames = resolve_xnames_from_request(
&infra,
&ctx.token,
body.xnames_expression.as_deref(),
body.hsm_group.as_deref(),
)
.await?;
tracing::info!(
"apply_kernel_parameters xnames={:?} op={:?} dry_run={}",
xnames,
body.operation,
body.dry_run
);
let operation = match body.operation {
KernelParamOp::Add => {
service::kernel_parameters::KernelParamOperation::Add {
params: &body.params,
overwrite: body.overwrite,
}
}
KernelParamOp::Apply => {
service::kernel_parameters::KernelParamOperation::Apply {
params: &body.params,
}
}
KernelParamOp::Delete => {
service::kernel_parameters::KernelParamOperation::Delete {
params: &body.params,
}
}
};
let changeset = service::kernel_parameters::prepare_kernel_params_changes(
&infra, &ctx.token, &xnames, &operation,
)
.await
.map_err(to_handler_error)?;
if body.dry_run {
return Ok((StatusCode::OK, Json(serialize_or_500(&changeset)?)));
}
let images_to_project = service::kernel_parameters::build_images_to_project(
&changeset,
body.project_sbps,
);
service::kernel_parameters::apply_kernel_params_changes(
&infra,
&ctx.token,
&changeset,
&images_to_project,
)
.await
.map_err(to_handler_error)?;
Ok((
StatusCode::OK,
Json(serde_json::json!({
"applied": true,
"has_changes": changeset.has_changes,
"xnames_to_reboot": changeset.xnames_to_reboot,
})),
))
}
pub use manta_shared::types::api::kernel_parameters::AddKernelParametersRequest;
#[utoipa::path(post, path = "/kernel-parameters/add", tag = "kernel-parameters",
params(SiteHeader),
request_body = AddKernelParametersRequest,
security(("bearerAuth" = [])),
responses(
// dry_run/real result union — kept as Value until the union shape is formalised
(status = 200, description = "Parameters added or preview", body = serde_json::Value),
(status = 400, description = "Bad request", body = ErrorResponse),
(status = 401, description = "Unauthorized", body = ErrorResponse),
(status = 500, description = "Internal error", body = ErrorResponse),
)
)]
#[tracing::instrument(skip_all)]
pub async fn add_kernel_parameters(
ctx: RequestCtx,
Json(body): Json<AddKernelParametersRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
let infra = ctx.infra();
let xnames = resolve_xnames_from_request(
&infra,
&ctx.token,
body.xnames_expression.as_deref(),
body.hsm_group.as_deref(),
)
.await?;
tracing::info!(
"add_kernel_parameters xnames={:?} dry_run={}",
xnames,
body.dry_run
);
let operation = service::kernel_parameters::KernelParamOperation::Add {
params: &body.params,
overwrite: body.overwrite,
};
let changeset = service::kernel_parameters::prepare_kernel_params_changes(
&infra, &ctx.token, &xnames, &operation,
)
.await
.map_err(to_handler_error)?;
if body.dry_run {
return Ok((StatusCode::OK, Json(serialize_or_500(&changeset)?)));
}
let images_to_project = service::kernel_parameters::build_images_to_project(
&changeset,
body.project_sbps,
);
service::kernel_parameters::apply_kernel_params_changes(
&infra,
&ctx.token,
&changeset,
&images_to_project,
)
.await
.map_err(to_handler_error)?;
Ok((
StatusCode::OK,
Json(serde_json::json!({
"applied": true,
"has_changes": changeset.has_changes,
"xnames_to_reboot": changeset.xnames_to_reboot,
})),
))
}
pub use manta_shared::types::api::kernel_parameters::DeleteKernelParametersRequest;
#[utoipa::path(delete, path = "/kernel-parameters", tag = "kernel-parameters",
params(SiteHeader),
request_body = DeleteKernelParametersRequest,
security(("bearerAuth" = [])),
responses(
// dry_run/real result union — kept as Value until the union shape is formalised
(status = 200, description = "Parameters removed or preview", body = serde_json::Value),
(status = 400, description = "Bad request", body = ErrorResponse),
(status = 401, description = "Unauthorized", body = ErrorResponse),
(status = 500, description = "Internal error", body = ErrorResponse),
)
)]
#[tracing::instrument(skip_all)]
pub async fn delete_kernel_parameters(
ctx: RequestCtx,
Json(body): Json<DeleteKernelParametersRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
let infra = ctx.infra();
let xnames = resolve_xnames_from_request(
&infra,
&ctx.token,
body.xnames_expression.as_deref(),
body.hsm_group.as_deref(),
)
.await?;
tracing::info!(
"delete_kernel_parameters xnames={:?} dry_run={}",
xnames,
body.dry_run
);
let operation = service::kernel_parameters::KernelParamOperation::Delete {
params: &body.params,
};
let changeset = service::kernel_parameters::prepare_kernel_params_changes(
&infra, &ctx.token, &xnames, &operation,
)
.await
.map_err(to_handler_error)?;
if body.dry_run {
return Ok((StatusCode::OK, Json(serialize_or_500(&changeset)?)));
}
service::kernel_parameters::apply_kernel_params_changes(
&infra,
&ctx.token,
&changeset,
&std::collections::HashMap::new(),
)
.await
.map_err(to_handler_error)?;
Ok((
StatusCode::OK,
Json(serde_json::json!({
"applied": true,
"has_changes": changeset.has_changes,
"xnames_to_reboot": changeset.xnames_to_reboot,
})),
))
}