manta_server/server/handlers/
hw_cluster.rs1use axum::{Json, extract::Path, http::StatusCode, response::IntoResponse};
13
14use super::{ErrorResponse, RequestCtx, SiteHeader, to_handler_error};
15use crate::service;
16
17pub use manta_shared::types::api::hw_cluster::{
18 AddHwComponentRequest, ApplyHwConfigurationRequest, DeleteHwComponentRequest,
19 HwClusterMode,
20};
21
22#[utoipa::path(post, path = "/hardware-clusters/{target}/members", tag = "hardware",
24 params(("target" = String, Path, description = "Target cluster name"), SiteHeader),
25 request_body = AddHwComponentRequest,
26 security(("bearerAuth" = [])),
27 responses(
28 (status = 200, description = "Members added or preview", body = serde_json::Value),
30 (status = 401, description = "Unauthorized", body = ErrorResponse),
31 (status = 500, description = "Internal error", body = ErrorResponse),
32 )
33)]
34#[tracing::instrument(skip_all)]
35pub async fn add_hw_component(
36 ctx: RequestCtx,
37 Path(target): Path<String>,
38 Json(body): Json<AddHwComponentRequest>,
39) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
40 tracing::info!(
41 "add_hw_component target={} parent={} dry_run={}",
42 target,
43 body.parent_cluster,
44 body.dry_run
45 );
46 let infra = ctx.infra();
47
48 service::authorization::validate_user_group_access(
49 &infra, &ctx.token, &target,
50 )
51 .await
52 .map_err(to_handler_error)?;
53 service::authorization::validate_user_group_access(
54 &infra,
55 &ctx.token,
56 &body.parent_cluster,
57 )
58 .await
59 .map_err(to_handler_error)?;
60
61 let result = crate::service::hw_cluster::add_hw_component(
62 &infra,
63 &ctx.token,
64 &target,
65 &body.parent_cluster,
66 &body.pattern,
67 body.dry_run,
68 body.create_hsm_group,
69 )
70 .await
71 .map_err(to_handler_error)?;
72
73 Ok(Json(serde_json::json!({
74 "dry_run": body.dry_run,
75 "nodes_moved": result.nodes_moved,
76 "target_cluster": target,
77 "target_nodes": result.target_nodes,
78 "parent_cluster": body.parent_cluster,
79 "parent_nodes": result.parent_nodes,
80 })))
81}
82
83#[utoipa::path(delete, path = "/hardware-clusters/{target}/members", tag = "hardware",
89 params(("target" = String, Path, description = "Target cluster name"), SiteHeader),
90 request_body = DeleteHwComponentRequest,
91 security(("bearerAuth" = [])),
92 responses(
93 (status = 200, description = "Members removed or preview", body = serde_json::Value),
95 (status = 401, description = "Unauthorized", body = ErrorResponse),
96 (status = 500, description = "Internal error", body = ErrorResponse),
97 )
98)]
99#[tracing::instrument(skip_all)]
100pub async fn delete_hw_component(
101 ctx: RequestCtx,
102 Path(target): Path<String>,
103 Json(body): Json<DeleteHwComponentRequest>,
104) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
105 tracing::info!(
106 "delete_hw_component target={} parent={} dry_run={}",
107 target,
108 body.parent_cluster,
109 body.dry_run
110 );
111 let infra = ctx.infra();
112
113 service::authorization::validate_user_group_access(
114 &infra, &ctx.token, &target,
115 )
116 .await
117 .map_err(to_handler_error)?;
118 service::authorization::validate_user_group_access(
119 &infra,
120 &ctx.token,
121 &body.parent_cluster,
122 )
123 .await
124 .map_err(to_handler_error)?;
125
126 let result = crate::service::hw_cluster::delete_hw_component(
127 &infra,
128 &ctx.token,
129 &target,
130 &body.parent_cluster,
131 &body.pattern,
132 body.dry_run,
133 body.delete_hsm_group,
134 )
135 .await
136 .map_err(to_handler_error)?;
137
138 Ok(Json(serde_json::json!({
139 "dry_run": body.dry_run,
140 "nodes_moved": result.nodes_moved,
141 "target_cluster": target,
142 "target_nodes": result.target_nodes,
143 "parent_cluster": body.parent_cluster,
144 "parent_nodes": result.parent_nodes,
145 })))
146}
147
148#[utoipa::path(post, path = "/hardware-clusters/{target}/configuration", tag = "hardware",
154 params(("target" = String, Path, description = "Target cluster name"), SiteHeader),
155 request_body = ApplyHwConfigurationRequest,
156 security(("bearerAuth" = [])),
157 responses(
158 (status = 200, description = "Configuration applied or preview", body = serde_json::Value),
160 (status = 401, description = "Unauthorized", body = ErrorResponse),
161 (status = 500, description = "Internal error", body = ErrorResponse),
162 )
163)]
164#[tracing::instrument(skip_all)]
165pub async fn apply_hw_configuration(
166 ctx: RequestCtx,
167 Path(target): Path<String>,
168 Json(body): Json<ApplyHwConfigurationRequest>,
169) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
170 tracing::info!(
171 "apply_hw_configuration target={} parent={} dry_run={}",
172 target,
173 body.parent_cluster,
174 body.dry_run
175 );
176 let infra = ctx.infra();
177
178 service::authorization::validate_user_group_access(
179 &infra, &ctx.token, &target,
180 )
181 .await
182 .map_err(to_handler_error)?;
183 service::authorization::validate_user_group_access(
184 &infra,
185 &ctx.token,
186 &body.parent_cluster,
187 )
188 .await
189 .map_err(to_handler_error)?;
190
191 let result = crate::service::hw_cluster::apply_hw_configuration(
192 &infra,
193 &ctx.token,
194 crate::service::hw_cluster::ApplyHwConfigurationParams {
195 mode: body.mode,
196 target_group_name: &target,
197 parent_group_name: &body.parent_cluster,
198 pattern: &body.pattern,
199 dryrun: body.dry_run,
200 create_target_group: body.create_target_hsm_group,
201 delete_empty_parent_group: body.delete_empty_parent_hsm_group,
202 },
203 )
204 .await
205 .map_err(to_handler_error)?;
206
207 Ok(Json(serde_json::json!({
208 "dry_run": body.dry_run,
209 "target_cluster": target,
210 "target_nodes": result.target_nodes,
211 "parent_cluster": body.parent_cluster,
212 "parent_nodes": result.parent_nodes,
213 })))
214}