Skip to main content

manta_server/server/handlers/
redfish_endpoints.rs

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