manta_server/server/handlers/
redfish_endpoints.rs

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