manta_server/server/handlers/
node.rs1use axum::{
13 Json,
14 extract::{Path, Query},
15 http::StatusCode,
16 response::IntoResponse,
17};
18
19use super::{ErrorResponse, RequestCtx, SiteHeader, to_handler_error};
20use crate::server::audit::AuditNote;
21use crate::service;
22
23pub use manta_shared::types::api::queries::NodesQuery;
28
29#[utoipa::path(get, path = "/nodes", tag = "nodes",
31 params(NodesQuery, SiteHeader),
32 security(("bearerAuth" = [])),
33 responses(
34 (status = 200, description = "Node details", body = Vec<manta_shared::types::dto::NodeDetails>),
35 (status = 400, description = "Bad request", body = ErrorResponse),
36 (status = 401, description = "Unauthorized", body = ErrorResponse),
37 (status = 500, description = "Internal error", body = ErrorResponse),
38 )
39)]
40#[tracing::instrument(skip_all)]
41pub async fn get_nodes(
42 ctx: RequestCtx,
43 Query(q): Query<NodesQuery>,
44) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
45 let infra = ctx.infra();
46
47 let params = service::node::GetNodesParams {
48 host_expression: q.xname,
49 include_siblings: q.include_siblings.unwrap_or(false),
50 status_filter: q.status,
51 };
52
53 let nodes = service::node::get_nodes(&infra, &ctx.token, ¶ms)
54 .await
55 .map_err(to_handler_error)?;
56
57 Ok(Json(nodes))
58}
59
60#[utoipa::path(delete, path = "/nodes/{id}", tag = "nodes",
66 params(("id" = String, Path, description = "Node xname or NID"), SiteHeader),
67 security(("bearerAuth" = [])),
68 responses(
69 (status = 204, description = "Node removed"),
70 (status = 401, description = "Unauthorized", body = ErrorResponse),
71 (status = 404, description = "Not found", body = ErrorResponse),
72 (status = 500, description = "Internal error", body = ErrorResponse),
73 )
74)]
75#[tracing::instrument(skip_all)]
76pub async fn delete_node(
77 ctx: RequestCtx,
78 note: AuditNote,
79 Path(id): Path<String>,
80) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
81 note.action("node.delete").target("node", &id);
82
83 tracing::info!("delete_node id={}", id);
84 let infra = ctx.infra();
85
86 service::node::delete_node(&infra, &ctx.token, &id)
87 .await
88 .map_err(to_handler_error)?;
89
90 Ok(StatusCode::NO_CONTENT)
91}
92
93pub use manta_shared::types::api::node::AddNodeRequest;
98
99#[utoipa::path(post, path = "/nodes", tag = "nodes",
101 params(SiteHeader),
102 request_body = AddNodeRequest,
103 security(("bearerAuth" = [])),
104 responses(
105 (status = 201, description = "Node registered", body = manta_shared::types::api::responses::AddNodeResponse),
106 (status = 400, description = "Bad request", body = ErrorResponse),
107 (status = 401, description = "Unauthorized", body = ErrorResponse),
108 (status = 500, description = "Internal error", body = ErrorResponse),
109 )
110)]
111#[tracing::instrument(skip_all)]
112pub async fn add_node(
113 ctx: RequestCtx,
114 note: AuditNote,
115 Json(body): Json<AddNodeRequest>,
116) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
117 note
118 .action("node.add")
119 .target("node", &body.id)
120 .target("group", &body.group)
121 .detail("enabled", body.enabled);
122
123 tracing::info!("add_node id={} group={}", body.id, body.group);
124 let infra = ctx.infra();
125
126 service::node::add_node(
127 &infra,
128 &ctx.token,
129 &body.id,
130 &body.group,
131 body.enabled,
132 body.arch,
133 None, )
135 .await
136 .map_err(to_handler_error)?;
137
138 Ok((
139 StatusCode::CREATED,
140 Json(serde_json::json!({ "id": body.id })),
141 ))
142}