manta_server/server/handlers/
node.rs1use axum::{
4 Json,
5 extract::{Path, Query},
6 http::StatusCode,
7 response::IntoResponse,
8};
9use serde::Deserialize;
10use utoipa::{IntoParams, ToSchema};
11
12use super::{ErrorResponse, RequestCtx, SiteHeader, to_handler_error};
13use crate::service;
14
15#[derive(Deserialize, IntoParams)]
21pub struct NodesQuery {
22 pub xname: String,
25 pub include_siblings: Option<bool>,
27 pub status: Option<String>,
29}
30
31#[utoipa::path(get, path = "/nodes", tag = "nodes",
33 params(NodesQuery, SiteHeader),
34 security(("bearerAuth" = [])),
35 responses(
36 (status = 200, description = "Node details", body = serde_json::Value),
37 (status = 400, description = "Bad request", body = ErrorResponse),
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_nodes(
44 ctx: RequestCtx,
45 Query(q): Query<NodesQuery>,
46) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
47 let infra = ctx.infra();
48
49 let params = service::node::GetNodesParams {
50 xname: q.xname,
51 include_siblings: q.include_siblings.unwrap_or(false),
52 status_filter: q.status,
53 };
54
55 let nodes = service::node::get_nodes(&infra, &ctx.token, ¶ms)
56 .await
57 .map_err(to_handler_error)?;
58
59 Ok(Json(nodes))
60}
61
62#[utoipa::path(delete, path = "/nodes/{id}", tag = "nodes",
68 params(("id" = String, Path, description = "Node xname or NID"), SiteHeader),
69 security(("bearerAuth" = [])),
70 responses(
71 (status = 204, description = "Node removed"),
72 (status = 401, description = "Unauthorized", body = ErrorResponse),
73 (status = 404, description = "Not found", body = ErrorResponse),
74 (status = 500, description = "Internal error", body = ErrorResponse),
75 )
76)]
77#[tracing::instrument(skip_all)]
78pub async fn delete_node(
79 ctx: RequestCtx,
80 Path(id): Path<String>,
81) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
82 tracing::info!("delete_node id={}", id);
83 let infra = ctx.infra();
84
85 service::node::delete_node(&infra, &ctx.token, &id)
86 .await
87 .map_err(to_handler_error)?;
88
89 Ok(StatusCode::NO_CONTENT)
90}
91
92#[derive(Deserialize, ToSchema)]
98pub struct AddNodeRequest {
99 pub id: String,
101 pub group: String,
103 #[serde(default)]
107 pub enabled: bool,
108 pub arch: Option<String>,
110}
111
112#[utoipa::path(post, path = "/nodes", tag = "nodes",
114 params(SiteHeader),
115 request_body = AddNodeRequest,
116 security(("bearerAuth" = [])),
117 responses(
118 (status = 201, description = "Node registered", body = serde_json::Value),
119 (status = 400, description = "Bad request", body = ErrorResponse),
120 (status = 401, description = "Unauthorized", body = ErrorResponse),
121 (status = 500, description = "Internal error", body = ErrorResponse),
122 )
123)]
124#[tracing::instrument(skip_all)]
125pub async fn add_node(
126 ctx: RequestCtx,
127 Json(body): Json<AddNodeRequest>,
128) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
129 tracing::info!("add_node id={} group={}", body.id, body.group);
130 let infra = ctx.infra();
131
132 service::node::add_node(
133 &infra,
134 &ctx.token,
135 &body.id,
136 &body.group,
137 body.enabled,
138 body.arch,
139 None, )
141 .await
142 .map_err(to_handler_error)?;
143
144 Ok((
145 StatusCode::CREATED,
146 Json(serde_json::json!({ "id": body.id })),
147 ))
148}