1use std::sync::Arc;
2use crate::DatabaseManager;
3use crate::models::deployment::Deployment;
4use super::super::db::queries as db;
5use rocket::http::Status;
6use rocket::serde::json::{json, Json, Value};
7use rocket::{delete, get, post, put, State};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct CreateDeploymentRequest {
13 pub app_id: i64,
14 pub build_id: i64,
15 pub version: String,
16 pub deployment_strategy: String,
17 pub previous_deployment_id: Option<i64>,
18 pub canary_percentage: Option<i64>,
19 pub environment_variables: Option<serde_json::Value>,
20 pub annotations: Option<serde_json::Value>,
21 pub labels: Option<serde_json::Value>,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct UpdateDeploymentStatusRequest {
27 pub status: String,
28 pub error_message: Option<String>,
29}
30
31#[get("/platform/<platform_id>/deployments?<page>&<per_page>")]
33pub async fn list_deployments(
34 platform_id: i64,
35 page: Option<i64>,
36 per_page: Option<i64>,
37 db_manager: &State<Arc<DatabaseManager>>,
38) -> Result<Json<Value>, (Status, Json<Value>)> {
39 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
41 Ok(platform) => platform,
42 Err(_) => {
43 return Err((
44 Status::NotFound,
45 Json(json!({
46 "error": "Platform not found",
47 "message": format!("Platform with ID {} does not exist", platform_id)
48 }))
49 ));
50 }
51 };
52
53 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
55 Ok(pool) => pool,
56 Err(_) => {
57 return Err((
58 Status::InternalServerError,
59 Json(json!({
60 "error": "Database error",
61 "message": "Failed to connect to platform database"
62 }))
63 ));
64 }
65 };
66
67 match (page, per_page) {
68 (Some(p), Some(pp)) => {
69 let deployments = match db::deployment::list_deployments(&pool, p, pp).await {
70 Ok(deployments) => deployments,
71 Err(_) => {
72 return Err((
73 Status::InternalServerError,
74 Json(json!({
75 "error": "Database error",
76 "message": "Failed to retrieve deployments"
77 }))
78 ));
79 }
80 };
81
82 let total_count = match db::deployment::count_deployments(&pool).await {
83 Ok(count) => count,
84 Err(_) => {
85 return Err((
86 Status::InternalServerError,
87 Json(json!({
88 "error": "Database error",
89 "message": "Failed to count deployments"
90 }))
91 ));
92 }
93 };
94
95 let total_pages = (total_count as f64 / pp as f64).ceil() as i64;
96
97 let response = json!({
98 "deployments": deployments,
99 "pagination": {
100 "page": p,
101 "per_page": pp,
102 "total_count": total_count,
103 "total_pages": total_pages
104 }
105 });
106
107 Ok(Json(response))
108 }
109 _ => Err((
110 Status::BadRequest,
111 Json(json!({
112 "error": "Missing pagination parameters",
113 "message": "Please provide both 'page' and 'per_page' parameters"
114 }))
115 ))
116 }
117}
118
119#[get("/platform/<platform_id>/count/deployments")]
121pub async fn count_deployments(
122 platform_id: i64,
123 db_manager: &State<Arc<DatabaseManager>>
124) -> Result<Json<i64>, (Status, Json<Value>)> {
125 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
127 Ok(platform) => platform,
128 Err(_) => {
129 return Err((
130 Status::NotFound,
131 Json(json!({
132 "error": "Platform not found",
133 "message": format!("Platform with ID {} does not exist", platform_id)
134 }))
135 ));
136 }
137 };
138
139 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
141 Ok(pool) => pool,
142 Err(_) => {
143 return Err((
144 Status::InternalServerError,
145 Json(json!({
146 "error": "Database error",
147 "message": "Failed to connect to platform database"
148 }))
149 ));
150 }
151 };
152
153 match db::deployment::count_deployments(&pool).await {
154 Ok(count) => Ok(Json(count)),
155 Err(_) => Err((
156 Status::InternalServerError,
157 Json(json!({
158 "error": "Database error",
159 "message": "Failed to count deployments"
160 }))
161 )),
162 }
163}
164
165#[get("/platform/<platform_id>/deployments/<deployment_id>")]
167pub async fn get_deployment(
168 platform_id: i64,
169 deployment_id: i64,
170 db_manager: &State<Arc<DatabaseManager>>
171) -> Result<Json<Deployment>, (Status, Json<Value>)> {
172 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
174 Ok(platform) => platform,
175 Err(_) => {
176 return Err((
177 Status::NotFound,
178 Json(json!({
179 "error": "Platform not found",
180 "message": format!("Platform with ID {} does not exist", platform_id)
181 }))
182 ));
183 }
184 };
185
186 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
188 Ok(pool) => pool,
189 Err(_) => {
190 return Err((
191 Status::InternalServerError,
192 Json(json!({
193 "error": "Database error",
194 "message": "Failed to connect to platform database"
195 }))
196 ));
197 }
198 };
199
200 match db::deployment::get_deployment_by_id(&pool, deployment_id).await {
201 Ok(deployment) => Ok(Json(deployment)),
202 Err(_) => Err((
203 Status::NotFound,
204 Json(json!({
205 "error": "Deployment not found",
206 "message": format!("Deployment with ID {} could not be found", deployment_id)
207 }))
208 )),
209 }
210}
211
212#[get("/platform/<platform_id>/apps/<app_id>/deployments?<page>&<per_page>")]
214pub async fn list_app_deployments(
215 platform_id: i64,
216 app_id: i64,
217 page: Option<i64>,
218 per_page: Option<i64>,
219 db_manager: &State<Arc<DatabaseManager>>,
220) -> Result<Json<Value>, (Status, Json<Value>)> {
221 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
223 Ok(platform) => platform,
224 Err(_) => {
225 return Err((
226 Status::NotFound,
227 Json(json!({
228 "error": "Platform not found",
229 "message": format!("Platform with ID {} does not exist", platform_id)
230 }))
231 ));
232 }
233 };
234
235 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
237 Ok(pool) => pool,
238 Err(_) => {
239 return Err((
240 Status::InternalServerError,
241 Json(json!({
242 "error": "Database error",
243 "message": "Failed to connect to platform database"
244 }))
245 ));
246 }
247 };
248
249 match (page, per_page) {
250 (Some(p), Some(pp)) => {
251 let deployments = match db::deployment::list_deployments_by_app(&pool, app_id, p, pp).await {
252 Ok(deployments) => deployments,
253 Err(_) => {
254 return Err((
255 Status::InternalServerError,
256 Json(json!({
257 "error": "Database error",
258 "message": "Failed to retrieve deployments"
259 }))
260 ));
261 }
262 };
263
264 let total_count = match db::deployment::count_deployments_by_app(&pool, app_id).await {
265 Ok(count) => count,
266 Err(_) => {
267 return Err((
268 Status::InternalServerError,
269 Json(json!({
270 "error": "Database error",
271 "message": "Failed to count deployments"
272 }))
273 ));
274 }
275 };
276
277 let total_pages = (total_count as f64 / pp as f64).ceil() as i64;
278
279 let response = json!({
280 "deployments": deployments,
281 "pagination": {
282 "page": p,
283 "per_page": pp,
284 "total_count": total_count,
285 "total_pages": total_pages
286 }
287 });
288
289 Ok(Json(response))
290 }
291 _ => Err((
292 Status::BadRequest,
293 Json(json!({
294 "error": "Missing pagination parameters",
295 "message": "Please provide both 'page' and 'per_page' parameters"
296 }))
297 ))
298 }
299}
300
301#[post("/platform/<platform_id>/deployments", format = "json", data = "<deployment_request>")]
303pub async fn create_deployment(
304 platform_id: i64,
305 deployment_request: Json<CreateDeploymentRequest>,
306 db_manager: &State<Arc<DatabaseManager>>,
307) -> Result<Json<Deployment>, (Status, Json<Value>)> {
308 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
310 Ok(platform) => platform,
311 Err(_) => {
312 return Err((
313 Status::NotFound,
314 Json(json!({
315 "error": "Platform not found",
316 "message": format!("Platform with ID {} does not exist", platform_id)
317 }))
318 ));
319 }
320 };
321
322 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
324 Ok(pool) => pool,
325 Err(_) => {
326 return Err((
327 Status::InternalServerError,
328 Json(json!({
329 "error": "Database error",
330 "message": "Failed to connect to platform database"
331 }))
332 ));
333 }
334 };
335
336 match db::deployment::create_deployment(
337 &pool,
338 deployment_request.app_id,
339 deployment_request.build_id,
340 &deployment_request.version,
341 &deployment_request.deployment_strategy,
342 deployment_request.previous_deployment_id,
343 deployment_request.canary_percentage,
344 deployment_request.environment_variables.clone(),
345 deployment_request.annotations.clone(),
346 deployment_request.labels.clone(),
347 None, ).await {
349 Ok(deployment) => Ok(Json(deployment)),
350 Err(e) => Err((
351 Status::InternalServerError,
352 Json(json!({
353 "error": "Failed to create deployment",
354 "message": e.to_string()
355 }))
356 )),
357 }
358}
359
360#[put("/platform/<platform_id>/deployments/<deployment_id>/status", format = "json", data = "<status_request>")]
362pub async fn update_deployment_status(
363 platform_id: i64,
364 deployment_id: i64,
365 status_request: Json<UpdateDeploymentStatusRequest>,
366 db_manager: &State<Arc<DatabaseManager>>,
367) -> Result<Json<Deployment>, (Status, Json<Value>)> {
368 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
370 Ok(platform) => platform,
371 Err(_) => {
372 return Err((
373 Status::NotFound,
374 Json(json!({
375 "error": "Platform not found",
376 "message": format!("Platform with ID {} does not exist", platform_id)
377 }))
378 ));
379 }
380 };
381
382 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
384 Ok(pool) => pool,
385 Err(_) => {
386 return Err((
387 Status::InternalServerError,
388 Json(json!({
389 "error": "Database error",
390 "message": "Failed to connect to platform database"
391 }))
392 ));
393 }
394 };
395
396 match db::deployment::update_deployment_status(
397 &pool,
398 deployment_id,
399 &status_request.status,
400 status_request.error_message.as_deref(),
401 ).await {
402 Ok(deployment) => Ok(Json(deployment)),
403 Err(e) => Err((
404 Status::InternalServerError,
405 Json(json!({
406 "error": "Failed to update deployment status",
407 "message": e.to_string()
408 }))
409 )),
410 }
411}
412
413#[delete("/platform/<platform_id>/deployments/<deployment_id>")]
415pub async fn delete_deployment(
416 platform_id: i64,
417 deployment_id: i64,
418 db_manager: &State<Arc<DatabaseManager>>,
419) -> Result<Json<Value>, (Status, Json<Value>)> {
420 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
422 Ok(platform) => platform,
423 Err(_) => {
424 return Err((
425 Status::NotFound,
426 Json(json!({
427 "error": "Platform not found",
428 "message": format!("Platform with ID {} does not exist", platform_id)
429 }))
430 ));
431 }
432 };
433
434 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
436 Ok(pool) => pool,
437 Err(_) => {
438 return Err((
439 Status::InternalServerError,
440 Json(json!({
441 "error": "Database error",
442 "message": "Failed to connect to platform database"
443 }))
444 ));
445 }
446 };
447
448 match db::deployment::delete_deployment(&pool, deployment_id).await {
449 Ok(_) => Ok(Json(json!({ "status": "deleted" }))),
450 Err(e) => Err((
451 Status::InternalServerError,
452 Json(json!({
453 "error": "Database error",
454 "message": e.to_string()
455 }))
456 )),
457 }
458}