manta_server/server/handlers/
hardware.rs

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