manta_server/server/handlers/
hardware.rs

1//! Hardware inventory queries.
2
3use axum::{Json, extract::Query, http::StatusCode, response::IntoResponse};
4
5use super::{ErrorResponse, RequestCtx, SiteHeader, to_handler_error};
6use crate::service;
7
8// ---------------------------------------------------------------------------
9// GET /api/v1/groups/hardware (canonical) and /hardware-clusters (deprecated)
10// ---------------------------------------------------------------------------
11
12pub use manta_shared::types::api::queries::{
13  HardwareClusterQuery, HardwareNodesListQuery,
14};
15
16/// GET /groups/hardware — summarize hardware components per node for a group.
17#[utoipa::path(get, path = "/groups/hardware", tag = "groups",
18  params(HardwareClusterQuery, SiteHeader),
19  security(("bearerAuth" = [])),
20  responses(
21    // Response wraps NodeSummary from manta-backend-dispatcher (third-party,
22    // no ToSchema) — kept as Value until upstream derives it.
23    (status = 200, description = "Hardware summary for group nodes", body = serde_json::Value),
24    (status = 401, description = "Unauthorized",                      body = ErrorResponse),
25    (status = 500, description = "Internal error",                    body = ErrorResponse),
26  )
27)]
28#[tracing::instrument(skip_all)]
29pub async fn get_groups_hardware(
30  ctx: RequestCtx,
31  Query(q): Query<HardwareClusterQuery>,
32) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
33  let infra = ctx.infra();
34
35  let params = service::hardware::GetHardwareClusterParams {
36    group_name: q.hsm_group,
37    settings_hsm_group_name: None,
38  };
39
40  let result =
41    service::hardware::get_hardware_cluster(&infra, &ctx.token, &params)
42      .await
43      .map_err(to_handler_error)?;
44
45  Ok(Json(serde_json::json!({
46    "hsm_group_name": result.hsm_group_name,
47    "node_summaries": result.node_summaries,
48  })))
49}
50
51/// DEPRECATED alias for `GET /groups/hardware`. Logs a server-side
52/// warning and delegates to the canonical handler. Old path kept for
53/// one release.
54#[utoipa::path(get, path = "/hardware-clusters", tag = "hardware",
55  params(HardwareClusterQuery, SiteHeader),
56  security(("bearerAuth" = [])),
57  responses(
58    // Alias for the canonical handler — same NodeSummary third-party
59    // shape, kept as Value for the same reason.
60    (status = 200, description = "[DEPRECATED] use /groups/hardware — hardware summary for group nodes", body = serde_json::Value),
61    (status = 401, description = "Unauthorized",                                                          body = ErrorResponse),
62    (status = 500, description = "Internal error",                                                        body = ErrorResponse),
63  )
64)]
65#[tracing::instrument(skip_all)]
66pub async fn get_hardware_clusters_deprecated(
67  ctx: RequestCtx,
68  q: Query<HardwareClusterQuery>,
69) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
70  tracing::warn!(
71    "deprecated endpoint: GET /hardware-clusters — use /groups/hardware instead"
72  );
73  get_groups_hardware(ctx, q).await
74}
75
76// ---------------------------------------------------------------------------
77// GET /api/v1/hardware-nodes-list
78// ---------------------------------------------------------------------------
79
80/// GET /hardware-nodes-list — hardware details for an explicit list of xnames.
81#[utoipa::path(get, path = "/hardware-nodes-list", tag = "hardware",
82  params(HardwareNodesListQuery, SiteHeader),
83  security(("bearerAuth" = [])),
84  responses(
85    // Response wraps NodeSummary from manta-backend-dispatcher (third-party,
86    // no ToSchema) — kept as Value until upstream derives it.
87    (status = 200, description = "Hardware details for specified nodes", body = serde_json::Value),
88    (status = 400, description = "Bad request",                          body = ErrorResponse),
89    (status = 401, description = "Unauthorized",                         body = ErrorResponse),
90    (status = 500, description = "Internal error",                       body = ErrorResponse),
91  )
92)]
93#[tracing::instrument(skip_all)]
94pub async fn get_hardware_nodes_list(
95  ctx: RequestCtx,
96  Query(q): Query<HardwareNodesListQuery>,
97) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
98  let infra = ctx.infra();
99
100  let params = service::hardware::GetHardwareNodesListParams {
101    host_expression: q.xnames,
102  };
103
104  let result =
105    service::hardware::get_hardware_nodes_list(&infra, &ctx.token, &params)
106      .await
107      .map_err(to_handler_error)?;
108
109  Ok(Json(serde_json::json!({
110    "node_summaries": result.node_summaries,
111  })))
112}
113
114// ===========================================================================
115// WRITE ENDPOINTS
116// ===========================================================================