manta_server/server/handlers/
redfish_endpoints.rs

1//! HSM Redfish-endpoint CRUD handlers.
2//!
3//! - `GET    /api/v1/redfish-endpoints`        → [`get_redfish_endpoints`]
4//! - `POST   /api/v1/redfish-endpoints`        → [`add_redfish_endpoint`]
5//! - `PUT    /api/v1/redfish-endpoints`        → [`update_redfish_endpoint`]
6//! - `DELETE /api/v1/redfish-endpoints/{id}`   → [`delete_redfish_endpoint`]
7//!
8//! All wrap `crate::service::redfish::*`.
9
10use axum::{
11  Json,
12  extract::{Path, Query},
13  http::StatusCode,
14  response::IntoResponse,
15};
16
17use super::{ErrorResponse, RequestCtx, SiteHeader, to_handler_error};
18use crate::service;
19use manta_shared::types::api::redfish_endpoints::{
20  GetRedfishEndpointsParams, UpdateRedfishEndpointParams,
21};
22
23// ---------------------------------------------------------------------------
24// GET /api/v1/redfish-endpoints
25// ---------------------------------------------------------------------------
26
27pub use manta_shared::types::api::queries::RedfishEndpointsQuery;
28
29/// GET /redfish-endpoints — list HSM Redfish endpoints with optional filters.
30#[utoipa::path(get, path = "/redfish-endpoints", tag = "redfish-endpoints",
31  params(RedfishEndpointsQuery, SiteHeader),
32  security(("bearerAuth" = [])),
33  responses(
34    // RedfishEndpointArray lives in manta-backend-dispatcher (third-party,
35    // no ToSchema) — kept as Value until upstream derives it.
36    (status = 200, description = "List of Redfish endpoints", body = serde_json::Value),
37    (status = 401, description = "Unauthorized",              body = ErrorResponse),
38    (status = 500, description = "Internal error",            body = ErrorResponse),
39  )
40)]
41#[tracing::instrument(skip_all)]
42pub async fn get_redfish_endpoints(
43  ctx: RequestCtx,
44  Query(q): Query<RedfishEndpointsQuery>,
45) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
46  let infra = ctx.infra();
47
48  let params = GetRedfishEndpointsParams {
49    id: q.id,
50    fqdn: q.fqdn,
51    uuid: q.uuid,
52    macaddr: q.macaddr,
53    ipaddress: q.ipaddress,
54  };
55
56  let endpoints =
57    service::redfish::get_redfish_endpoints(&infra, &ctx.token, &params)
58      .await
59      .map_err(to_handler_error)?;
60
61  Ok(Json(endpoints))
62}
63
64// ---------------------------------------------------------------------------
65// DELETE /api/v1/redfish-endpoints/{id}
66// ---------------------------------------------------------------------------
67
68/// DELETE /redfish-endpoints/{id} — remove a Redfish endpoint from HSM.
69#[utoipa::path(delete, path = "/redfish-endpoints/{id}", tag = "redfish-endpoints",
70  params(("id" = String, Path, description = "BMC xname"), SiteHeader),
71  security(("bearerAuth" = [])),
72  responses(
73    (status = 204, description = "Endpoint removed"),
74    (status = 401, description = "Unauthorized",   body = ErrorResponse),
75    (status = 404, description = "Not found",      body = ErrorResponse),
76    (status = 500, description = "Internal error", body = ErrorResponse),
77  )
78)]
79#[tracing::instrument(skip_all)]
80pub async fn delete_redfish_endpoint(
81  ctx: RequestCtx,
82  Path(id): Path<String>,
83) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
84  tracing::info!("delete_redfish_endpoint id={}", id);
85  let infra = ctx.infra();
86
87  service::redfish::delete_redfish_endpoint(&infra, &ctx.token, &id)
88    .await
89    .map_err(to_handler_error)?;
90
91  Ok(StatusCode::NO_CONTENT)
92}
93
94// ---------------------------------------------------------------------------
95// POST /api/v1/redfish-endpoints
96// ---------------------------------------------------------------------------
97
98/// POST /redfish-endpoints — register a new Redfish endpoint in HSM.
99#[utoipa::path(post, path = "/redfish-endpoints", tag = "redfish-endpoints",
100  params(SiteHeader),
101  request_body = UpdateRedfishEndpointParams,
102  security(("bearerAuth" = [])),
103  responses(
104    (status = 201, description = "Endpoint registered",  body = manta_shared::types::api::responses::CreatedResponse),
105    (status = 401, description = "Unauthorized",          body = ErrorResponse),
106    (status = 500, description = "Internal error",        body = ErrorResponse),
107  )
108)]
109#[tracing::instrument(skip_all)]
110pub async fn add_redfish_endpoint(
111  ctx: RequestCtx,
112  Json(params): Json<UpdateRedfishEndpointParams>,
113) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
114  tracing::info!("add_redfish_endpoint");
115  let infra = ctx.infra();
116
117  service::redfish::add_redfish_endpoint(&infra, &ctx.token, params)
118    .await
119    .map_err(to_handler_error)?;
120
121  Ok((
122    StatusCode::CREATED,
123    Json(serde_json::json!({ "created": true })),
124  ))
125}
126
127// ---------------------------------------------------------------------------
128// PUT /api/v1/redfish-endpoints
129// ---------------------------------------------------------------------------
130
131/// PUT /redfish-endpoints — update an existing Redfish endpoint's properties.
132#[utoipa::path(put, path = "/redfish-endpoints", tag = "redfish-endpoints",
133  params(SiteHeader),
134  request_body = UpdateRedfishEndpointParams,
135  security(("bearerAuth" = [])),
136  responses(
137    (status = 204, description = "Endpoint updated"),
138    (status = 401, description = "Unauthorized",   body = ErrorResponse),
139    (status = 500, description = "Internal error", body = ErrorResponse),
140  )
141)]
142#[tracing::instrument(skip_all)]
143pub async fn update_redfish_endpoint(
144  ctx: RequestCtx,
145  Json(params): Json<UpdateRedfishEndpointParams>,
146) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
147  tracing::info!("update_redfish_endpoint");
148  let infra = ctx.infra();
149
150  service::redfish::update_redfish_endpoint(&infra, &ctx.token, params)
151    .await
152    .map_err(to_handler_error)?;
153
154  Ok(StatusCode::NO_CONTENT)
155}