From 874162b8272890cbc378379cfd06fcefd6ff045a Mon Sep 17 00:00:00 2001 From: Petru Date: Tue, 26 Dec 2023 18:21:47 +0200 Subject: [PATCH 01/25] issue-auth stack/deploy --- src/routes/stack/deploy.rs | 117 +++++++++++++++---------------------- 1 file changed, 47 insertions(+), 70 deletions(-) diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 1d52caa7..3b0bc018 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -1,9 +1,9 @@ use crate::configuration::Settings; +use crate::db; use crate::forms::StackPayload; use crate::helpers::stack::builder::DcBuilder; use crate::helpers::JsonResponse; -use crate::models::stack::Stack; -use crate::models::user::User; +use crate::models; use actix_web::{post, web, web::Data, Responder, Result}; use futures_lite::stream::StreamExt; use lapin::{ @@ -12,89 +12,66 @@ use lapin::{ use sqlx::PgPool; use std::sync::Arc; - #[tracing::instrument(name = "Deploy for every user. Admin endpoint")] #[post("/{id}/deploy")] pub async fn add( - user: web::ReqData>, + user: web::ReqData>, path: web::Path<(i32,)>, pool: Data, sets: Data, ) -> Result { let id = path.0; - tracing::debug!("Received id: {}", id); - - let stack = match sqlx::query_as!( - Stack, - r#" - SELECT * FROM user_stack WHERE id=$1 LIMIT 1 - "#, - id - ) - .fetch_one(pool.get_ref()) - .await - { - Ok(stack) => { - tracing::info!("Stack found: {:?}", stack.id,); - Some(stack) - } - Err(sqlx::Error::RowNotFound) => { - tracing::error!("Row not found 404"); - None - } - Err(e) => { - tracing::error!("Failed to fetch stack, error: {:?}", e); - None - } - }; + let stack = db::stack::fetch(pool.get_ref(), id) + .await + .map_err(|err| JsonResponse::::build().internal_server_error(err)) + .and_then(|stack| match stack { + Some(stack) => Ok(stack), + None => Err(JsonResponse::::build().not_found("not found")), + })?; - return match stack { - Some(stack) => { - let id = stack.id.clone(); - let dc = DcBuilder::new(stack); - dc.build(); + let id = stack.id.clone(); + let dc = DcBuilder::new(stack); + dc.build().ok_or_else(|| { + tracing::error!("Error. Compose builder returned an empty string"); + JsonResponse::::build().internal_server_error("troubles at building") + })?; - let addr = sets.amqp.connection_string(); - let routing_key = "install.start.tfa.all.all".to_string(); - tracing::debug!("Sending message to {:?}", routing_key); + let addr = sets.amqp.connection_string(); + let routing_key = "install.start.tfa.all.all".to_string(); + tracing::debug!("Sending message to {:?}", routing_key); - let conn = Connection::connect(&addr, ConnectionProperties::default()) - .await - .expect("Could not connect RabbitMQ"); + let conn = Connection::connect(&addr, ConnectionProperties::default()) + .await + .expect("Could not connect RabbitMQ"); - tracing::info!("RABBITMQ CONNECTED"); + tracing::info!("RABBITMQ CONNECTED"); - let channel = conn.create_channel().await.unwrap(); - let mut stack_data = - serde_json::from_value::(dc.stack.body.clone()).unwrap(); + let channel = conn.create_channel().await.unwrap(); + let mut stack_data = serde_json::from_value::(dc.stack.body.clone()).unwrap(); - stack_data.id = Some(id); - stack_data.user_token = Some(user.id.clone()); - stack_data.user_email = Some(user.email.clone()); - stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); + stack_data.id = Some(id); + stack_data.user_token = Some(user.id.clone()); + stack_data.user_email = Some(user.email.clone()); + stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); - let payload = serde_json::to_string::(&stack_data).unwrap(); - let _payload = payload.as_bytes(); + let payload = serde_json::to_string::(&stack_data).unwrap(); + let _payload = payload.as_bytes(); - let confirm = channel - .basic_publish( - "install", - routing_key.as_str(), - BasicPublishOptions::default(), - _payload, - BasicProperties::default(), - ) - .await - .unwrap() - .await - .unwrap(); + let confirm = channel + .basic_publish( + "install", + routing_key.as_str(), + BasicPublishOptions::default(), + _payload, + BasicProperties::default(), + ) + .await + .unwrap() + .await + .unwrap(); - assert_eq!(confirm, Confirmation::NotRequested); - tracing::debug!("Message sent to rabbitmq"); - return Ok(JsonResponse::::build().set_id(id).ok("Success")); - } - None => { - Err(JsonResponse::::build().internal_server_error("Deployment failed")) - } - } + assert_eq!(confirm, Confirmation::NotRequested); + return Ok(JsonResponse::::build() + .set_id(id) + .ok("Success")); } From 7ae0f1f13656cd9f5286f827d3cdef371f707754 Mon Sep 17 00:00:00 2001 From: Petru Date: Tue, 26 Dec 2023 18:36:32 +0200 Subject: [PATCH 02/25] issue-auth stack/deploy --- src/routes/stack/deploy.rs | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 3b0bc018..928d6efe 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -42,13 +42,24 @@ pub async fn add( let conn = Connection::connect(&addr, ConnectionProperties::default()) .await - .expect("Could not connect RabbitMQ"); - - tracing::info!("RABBITMQ CONNECTED"); + .map_err(|err| { + JsonResponse::::build() + .internal_server_error("Could not connect RabbitMQ") + })?; - let channel = conn.create_channel().await.unwrap(); - let mut stack_data = serde_json::from_value::(dc.stack.body.clone()).unwrap(); + let channel = conn.create_channel().await.map_err(|err| { + JsonResponse::::build() + .internal_server_error("Can't create rabbitMQ channel") + })?; + let mut stack_data = serde_json::from_value::(dc.stack.body.clone()) + .map_err(|err| JsonResponse::::build().bad_request("can't deserialize"))?; //todo + //add + //json + //error + //path + Ok(JsonResponse::::build().ok("bdc")) + /* stack_data.id = Some(id); stack_data.user_token = Some(user.id.clone()); stack_data.user_email = Some(user.email.clone()); @@ -66,12 +77,16 @@ pub async fn add( BasicProperties::default(), ) .await - .unwrap() + .unwrap() //todo .await - .unwrap(); - - assert_eq!(confirm, Confirmation::NotRequested); - return Ok(JsonResponse::::build() + .map_err(|err| JsonResponse::::build().internal_server_error(err)) + .and_then(|confirm| { + match confirm { + Confirmation::NotRequested => Err(JsonResponse::::build().bad_request("confirmation is NotRequested")), + _ => Ok(JsonResponse::::build() .set_id(id) - .ok("Success")); + .ok("Success")) + } + }) + */ } From 36a88207c8ed97afc9ba2fb1e5d46a61129a4e5e Mon Sep 17 00:00:00 2001 From: Petru Date: Wed, 27 Dec 2023 17:29:47 +0200 Subject: [PATCH 03/25] issue-auth src/routes/stack/deploy.rs --- src/routes/stack/deploy.rs | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 928d6efe..03c52649 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -52,41 +52,40 @@ pub async fn add( .internal_server_error("Can't create rabbitMQ channel") })?; let mut stack_data = serde_json::from_value::(dc.stack.body.clone()) - .map_err(|err| JsonResponse::::build().bad_request("can't deserialize"))?; //todo - //add - //json - //error - //path + .map_err(|err| JsonResponse::::build().bad_request("can't deserialize"))?; - Ok(JsonResponse::::build().ok("bdc")) - /* stack_data.id = Some(id); stack_data.user_token = Some(user.id.clone()); stack_data.user_email = Some(user.email.clone()); stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); - let payload = serde_json::to_string::(&stack_data).unwrap(); - let _payload = payload.as_bytes(); + let payload = serde_json::to_string::(&stack_data).map_err(|err| { + JsonResponse::::build().internal_server_error(format!("{}", err)) + })?; - let confirm = channel + channel .basic_publish( "install", routing_key.as_str(), BasicPublishOptions::default(), - _payload, + payload.as_bytes(), BasicProperties::default(), ) .await - .unwrap() //todo + .map_err(|_| { + JsonResponse::::build().internal_server_error("internal server error") + })? //todo the correct err .await - .map_err(|err| JsonResponse::::build().internal_server_error(err)) - .and_then(|confirm| { - match confirm { - Confirmation::NotRequested => Err(JsonResponse::::build().bad_request("confirmation is NotRequested")), - _ => Ok(JsonResponse::::build() - .set_id(id) - .ok("Success")) + .map_err(|_| { + JsonResponse::::build().internal_server_error("internal server error") + }) + .and_then(|confirm| match confirm { + Confirmation::NotRequested => { + Err(JsonResponse::::build() + .bad_request("confirmation is NotRequested")) } + _ => Ok(JsonResponse::::build() + .set_id(id) + .ok("Success")), }) - */ } From d38f220031e279000f61c8543d09b0a3e6dc1909 Mon Sep 17 00:00:00 2001 From: Petru Date: Wed, 27 Dec 2023 17:41:24 +0200 Subject: [PATCH 04/25] issue-auth src/routes/stack/deploy.rs --- src/routes/stack/deploy.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 03c52649..36fbc281 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -33,7 +33,7 @@ pub async fn add( let dc = DcBuilder::new(stack); dc.build().ok_or_else(|| { tracing::error!("Error. Compose builder returned an empty string"); - JsonResponse::::build().internal_server_error("troubles at building") + JsonResponse::::build().internal_server_error("") })?; let addr = sets.amqp.connection_string(); @@ -43,16 +43,19 @@ pub async fn add( let conn = Connection::connect(&addr, ConnectionProperties::default()) .await .map_err(|err| { - JsonResponse::::build() - .internal_server_error("Could not connect RabbitMQ") + tracing::error!("connecting to RabbitMQ {:?}", err); + JsonResponse::::build().internal_server_error("") })?; let channel = conn.create_channel().await.map_err(|err| { - JsonResponse::::build() - .internal_server_error("Can't create rabbitMQ channel") + tracing::error!("creating RabbitMQ channel {:?}", err); + JsonResponse::::build().internal_server_error("") })?; - let mut stack_data = serde_json::from_value::(dc.stack.body.clone()) - .map_err(|err| JsonResponse::::build().bad_request("can't deserialize"))?; + let mut stack_data = + serde_json::from_value::(dc.stack.body.clone()).map_err(|err| { + tracing::error!("transforming json Value into StackPayload {:?}", err); + JsonResponse::::build().bad_request("") + })?; stack_data.id = Some(id); stack_data.user_token = Some(user.id.clone()); @@ -60,7 +63,8 @@ pub async fn add( stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); let payload = serde_json::to_string::(&stack_data).map_err(|err| { - JsonResponse::::build().internal_server_error(format!("{}", err)) + tracing::error!("serializing StackPayload {:?}", err); + JsonResponse::::build().internal_server_error("") })?; channel @@ -72,12 +76,14 @@ pub async fn add( BasicProperties::default(), ) .await - .map_err(|_| { - JsonResponse::::build().internal_server_error("internal server error") - })? //todo the correct err + .map_err(|err| { + tracing::error!("publishing the message {:?}", err); + JsonResponse::::build().internal_server_error("") + })? .await - .map_err(|_| { - JsonResponse::::build().internal_server_error("internal server error") + .map_err(|err| { + tracing::error!("confirming the publication {:?}", err); + JsonResponse::::build().internal_server_error("") }) .and_then(|confirm| match confirm { Confirmation::NotRequested => { From 1852cb623a5d7222a4f269e31cec7544cdfb65cd Mon Sep 17 00:00:00 2001 From: Petru Date: Wed, 27 Dec 2023 17:47:36 +0200 Subject: [PATCH 05/25] issue-auth channel --- src/routes/stack/deploy.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 36fbc281..9432f552 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -47,10 +47,6 @@ pub async fn add( JsonResponse::::build().internal_server_error("") })?; - let channel = conn.create_channel().await.map_err(|err| { - tracing::error!("creating RabbitMQ channel {:?}", err); - JsonResponse::::build().internal_server_error("") - })?; let mut stack_data = serde_json::from_value::(dc.stack.body.clone()).map_err(|err| { tracing::error!("transforming json Value into StackPayload {:?}", err); @@ -67,7 +63,12 @@ pub async fn add( JsonResponse::::build().internal_server_error("") })?; - channel + conn.create_channel() + .await + .map_err(|err| { + tracing::error!("creating RabbitMQ channel {:?}", err); + JsonResponse::::build().internal_server_error("") + })? .basic_publish( "install", routing_key.as_str(), From 3383358c5afcf024f7e1217adf1113ef7864a9fe Mon Sep 17 00:00:00 2001 From: Petru Date: Wed, 27 Dec 2023 17:51:17 +0200 Subject: [PATCH 06/25] issue-auth RabbitMQ logic --- src/routes/stack/deploy.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 9432f552..c92aa70a 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -36,17 +36,6 @@ pub async fn add( JsonResponse::::build().internal_server_error("") })?; - let addr = sets.amqp.connection_string(); - let routing_key = "install.start.tfa.all.all".to_string(); - tracing::debug!("Sending message to {:?}", routing_key); - - let conn = Connection::connect(&addr, ConnectionProperties::default()) - .await - .map_err(|err| { - tracing::error!("connecting to RabbitMQ {:?}", err); - JsonResponse::::build().internal_server_error("") - })?; - let mut stack_data = serde_json::from_value::(dc.stack.body.clone()).map_err(|err| { tracing::error!("transforming json Value into StackPayload {:?}", err); @@ -63,7 +52,17 @@ pub async fn add( JsonResponse::::build().internal_server_error("") })?; - conn.create_channel() + let addr = sets.amqp.connection_string(); + let routing_key = "install.start.tfa.all.all".to_string(); + tracing::debug!("Sending message to {:?}", routing_key); + + Connection::connect(&addr, ConnectionProperties::default()) + .await + .map_err(|err| { + tracing::error!("connecting to RabbitMQ {:?}", err); + JsonResponse::::build().internal_server_error("") + })? + .create_channel() .await .map_err(|err| { tracing::error!("creating RabbitMQ channel {:?}", err); From 055988c936b9c76d127751461f0f4fdb2a2c0dbf Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 09:33:15 +0200 Subject: [PATCH 07/25] issue-auth pg_pool --- src/routes/client/add.rs | 22 +++++++++++----------- src/routes/client/disable.rs | 32 ++++++++++++++++---------------- src/routes/client/enable.rs | 15 +++++++-------- src/routes/client/update.rs | 20 ++++++++++++-------- src/routes/rating/get.rs | 13 ++++++++----- src/routes/stack/add.rs | 10 +++++----- src/routes/stack/compose.rs | 8 ++++---- src/routes/stack/deploy.rs | 4 ++-- src/routes/stack/get.rs | 8 ++++---- src/routes/stack/update.rs | 34 +++++++++++++--------------------- 10 files changed, 82 insertions(+), 84 deletions(-) diff --git a/src/routes/client/add.rs b/src/routes/client/add.rs index b3d90d94..0b526d10 100644 --- a/src/routes/client/add.rs +++ b/src/routes/client/add.rs @@ -1,21 +1,21 @@ use crate::configuration::Settings; +use crate::db; use crate::helpers::client; use crate::helpers::JsonResponse; use crate::models; -use crate::db; use actix_web::{post, web, Responder, Result}; use sqlx::PgPool; -use tracing::Instrument; use std::sync::Arc; +use tracing::Instrument; #[tracing::instrument(name = "Add client.")] #[post("")] pub async fn add_handler( user: web::ReqData>, settings: web::Data, - pool: web::Data, + pg_pool: web::Data, ) -> Result { - add_handler_inner(&user.id, settings, pool) + add_handler_inner(&user.id, settings, pg_pool) .await .map(|client| JsonResponse::build().set_item(client).ok("Ok")) .map_err(|err| JsonResponse::::build().bad_request(err)) @@ -24,21 +24,21 @@ pub async fn add_handler( pub async fn add_handler_inner( user_id: &String, settings: web::Data, - pool: web::Data, + pg_pool: web::Data, ) -> Result { - let client_count = db::client::count_by_user(pool.get_ref(), user_id).await?; + let client_count = db::client::count_by_user(pg_pool.get_ref(), user_id).await?; if client_count >= settings.max_clients_number { return Err("Too many clients created".to_string()); } - let client = create_client(pool.get_ref(), user_id).await?; - db::client::insert(pool.get_ref(), client).await + let client = create_client(pg_pool.get_ref(), user_id).await?; + db::client::insert(pg_pool.get_ref(), client).await } -async fn create_client(pool: &PgPool, user_id: &String) -> Result { - let mut client = models::Client::default(); +async fn create_client(pg_pool: &PgPool, user_id: &String) -> Result { + let mut client = models::Client::default(); client.user_id = user_id.clone(); - client.secret = client::generate_secret(pool, 255) + client.secret = client::generate_secret(pg_pool, 255) .await .map(|s| Some(s))?; diff --git a/src/routes/client/disable.rs b/src/routes/client/disable.rs index 057a183f..70d2a1cb 100644 --- a/src/routes/client/disable.rs +++ b/src/routes/client/disable.rs @@ -1,33 +1,33 @@ use crate::configuration::Settings; +use crate::db; use crate::helpers::JsonResponse; use crate::models; -use crate::db; use actix_web::{put, web, Responder, Result}; use sqlx::PgPool; -use tracing::Instrument; use std::sync::Arc; +use tracing::Instrument; #[tracing::instrument(name = "Disable client.")] #[put("/{id}/disable")] pub async fn disable_handler( user: web::ReqData>, settings: web::Data, - pool: web::Data, + pg_pool: web::Data, path: web::Path<(i32,)>, ) -> Result { - let client_id = path.0; - let mut client = db::client::fetch(pool.get_ref(), client_id) - .await - .map_err(|msg| JsonResponse::::build().internal_server_error(msg))? - .ok_or_else(|| JsonResponse::::build().not_found("not found"))?; + let client_id = path.0; + let mut client = db::client::fetch(pg_pool.get_ref(), client_id) + .await + .map_err(|msg| JsonResponse::::build().internal_server_error(msg))? + .ok_or_else(|| JsonResponse::::build().not_found("not found"))?; - if client.secret.is_none() { - return Err(JsonResponse::::build().bad_request("client is not active")); - } + if client.secret.is_none() { + return Err(JsonResponse::::build().bad_request("client is not active")); + } - client.secret = None; - db::client::update(pool.get_ref(), client) - .await - .map(|client| JsonResponse::build().set_item(client).ok("success")) - .map_err(|msg| JsonResponse::::build().bad_request(msg)) + client.secret = None; + db::client::update(pg_pool.get_ref(), client) + .await + .map(|client| JsonResponse::build().set_item(client).ok("success")) + .map_err(|msg| JsonResponse::::build().bad_request(msg)) } diff --git a/src/routes/client/enable.rs b/src/routes/client/enable.rs index 5669accc..c87fc445 100644 --- a/src/routes/client/enable.rs +++ b/src/routes/client/enable.rs @@ -1,38 +1,37 @@ use crate::configuration::Settings; +use crate::db; use crate::helpers::client; use crate::helpers::JsonResponse; use crate::models; -use crate::db; use actix_web::{put, web, Responder, Result}; -use tracing::Instrument; use sqlx::PgPool; use std::sync::Arc; +use tracing::Instrument; #[tracing::instrument(name = "Enable client.")] #[put("/{id}/enable")] pub async fn enable_handler( user: web::ReqData>, settings: web::Data, - pool: web::Data, + pg_pool: web::Data, path: web::Path<(i32,)>, ) -> Result { let client_id = path.0; - let mut client = db::client::fetch(pool.get_ref(), client_id) + let mut client = db::client::fetch(pg_pool.get_ref(), client_id) .await .map_err(|msg| JsonResponse::::build().internal_server_error(msg))? - .ok_or_else(|| JsonResponse::::build().not_found("not found"))? - ; + .ok_or_else(|| JsonResponse::::build().not_found("not found"))?; if client.secret.is_some() { return Err(JsonResponse::::build().bad_request("client is already active")); } - client.secret = client::generate_secret(pool.get_ref(), 255) + client.secret = client::generate_secret(pg_pool.get_ref(), 255) .await .map(|secret| Some(secret)) .map_err(|err| JsonResponse::::build().bad_request(err))?; - db::client::update(pool.get_ref(), client) + db::client::update(pg_pool.get_ref(), client) .await .map(|client| JsonResponse::build().set_item(client).ok("success")) .map_err(|err| JsonResponse::::build().bad_request(err)) diff --git a/src/routes/client/update.rs b/src/routes/client/update.rs index b1003162..a52af9b0 100644 --- a/src/routes/client/update.rs +++ b/src/routes/client/update.rs @@ -1,39 +1,43 @@ +use crate::db; use crate::helpers::client; use crate::models; -use crate::db; use crate::{configuration::Settings, helpers::JsonResponse}; use actix_web::{put, web, Responder, Result}; +use futures::TryFutureExt; use sqlx::PgPool; use std::sync::Arc; use tracing::Instrument; -use futures::TryFutureExt; #[tracing::instrument(name = "Update client.")] #[put("/{id}")] pub async fn update_handler( user: web::ReqData>, settings: web::Data, - pool: web::Data, + pg_pool: web::Data, path: web::Path<(i32,)>, ) -> Result { let client_id = path.0; - let mut client = db::client::fetch(pool.get_ref(), client_id) + let mut client = db::client::fetch(pg_pool.get_ref(), client_id) .await .map_err(|msg| JsonResponse::::build().internal_server_error(msg))? - .ok_or_else(|| JsonResponse::::build().not_found("not found"))?; + .ok_or_else(|| JsonResponse::::build().not_found("not found"))?; if client.secret.is_none() { return Err(JsonResponse::::build().bad_request("client is not active")); } - client.secret = client::generate_secret(pool.get_ref(), 255) + client.secret = client::generate_secret(pg_pool.get_ref(), 255) .await .map(|s| Some(s)) .map_err(|msg| JsonResponse::::build().bad_request(msg))?; - db::client::update(pool.get_ref(), client) + db::client::update(pg_pool.get_ref(), client) .await - .map(|client| JsonResponse::::build().set_item(client).ok("success")) + .map(|client| { + JsonResponse::::build() + .set_item(client) + .ok("success") + }) .map_err(|err| { tracing::error!("Failed to execute query: {:?}", err); JsonResponse::::build().internal_server_error("") diff --git a/src/routes/rating/get.rs b/src/routes/rating/get.rs index 4bc0c1ff..9081960c 100644 --- a/src/routes/rating/get.rs +++ b/src/routes/rating/get.rs @@ -1,6 +1,6 @@ +use crate::db; use crate::helpers::JsonResponse; use crate::models; -use crate::db; use actix_web::{get, web, Responder, Result}; use sqlx::PgPool; use tracing::Instrument; @@ -14,10 +14,10 @@ use tracing::Instrument; #[get("/{id}")] pub async fn get_handler( path: web::Path<(i32,)>, - pool: web::Data, + pg_pool: web::Data, ) -> Result { let rate_id = path.0; - let rating = db::rating::fetch(pool.get_ref(), rate_id) + let rating = db::rating::fetch(pg_pool.get_ref(), rate_id) .await .map_err(|_err| JsonResponse::::build().internal_server_error(""))? .ok_or_else(|| JsonResponse::::build().not_found("not found"))?; @@ -27,8 +27,11 @@ pub async fn get_handler( #[tracing::instrument(name = "Get all ratings.")] #[get("")] -pub async fn list_handler(path: web::Path<()>, pool: web::Data) -> Result { - db::rating::fetch_all(pool.get_ref()) +pub async fn list_handler( + path: web::Path<()>, + pg_pool: web::Data, +) -> Result { + db::rating::fetch_all(pg_pool.get_ref()) .await .map(|ratings| JsonResponse::build().set_list(ratings).ok("OK")) .map_err(|err| JsonResponse::::build().internal_server_error("")) diff --git a/src/routes/stack/add.rs b/src/routes/stack/add.rs index ef38ac5f..7ed5a09b 100644 --- a/src/routes/stack/add.rs +++ b/src/routes/stack/add.rs @@ -19,20 +19,20 @@ use std::sync::Arc; pub async fn add( body: Bytes, user: web::ReqData>, - pool: Data, + pg_pool: Data, ) -> Result { // @todo ACL let form = body_into_form(body).await?; let stack_name = form.custom.custom_stack_code.clone(); - check_if_stack_exists(pool.get_ref(), &stack_name).await?; + check_if_stack_exists(pg_pool.get_ref(), &stack_name).await?; let body: Value = serde_json::to_value::(form) .or(serde_json::to_value::(StackForm::default())) .unwrap(); let stack = models::Stack::new(user.id.clone(), stack_name, body); - db::stack::insert(pool.get_ref(), stack) + db::stack::insert(pg_pool.get_ref(), stack) .await .map(|stack| JsonResponse::build().set_item(stack).ok("Ok")) .map_err(|_| { @@ -40,8 +40,8 @@ pub async fn add( }) } -async fn check_if_stack_exists(pool: &PgPool, stack_name: &String) -> Result<(), Error> { - db::stack::fetch_one_by_name(pool, stack_name) +async fn check_if_stack_exists(pg_pool: &PgPool, stack_name: &String) -> Result<(), Error> { + db::stack::fetch_one_by_name(pg_pool, stack_name) .await .map_err(|_| { JsonResponse::::build().internal_server_error("Internal Server Error") diff --git a/src/routes/stack/compose.rs b/src/routes/stack/compose.rs index 28290902..4e58141e 100644 --- a/src/routes/stack/compose.rs +++ b/src/routes/stack/compose.rs @@ -11,10 +11,10 @@ use std::sync::Arc; pub async fn add( user: web::ReqData>, path: web::Path<(i32,)>, - pool: Data, + pg_pool: Data, ) -> Result { let id = path.0; - let stack = db::stack::fetch(pool.get_ref(), id) + let stack = db::stack::fetch(pg_pool.get_ref(), id) .await .map_err(|err| JsonResponse::::build().internal_server_error(err)) .and_then(|stack| match stack { @@ -39,11 +39,11 @@ pub async fn add( pub async fn admin( user: web::ReqData>, path: web::Path<(i32,)>, - pool: Data, + pg_pool: Data, ) -> Result { /// Admin function for generating compose file for specified user let id = path.0; - let stack = db::stack::fetch(pool.get_ref(), id) + let stack = db::stack::fetch(pg_pool.get_ref(), id) .await .map_err(|err| JsonResponse::::build().internal_server_error(err)) .and_then(|stack| match stack { diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index c92aa70a..f18c99d6 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -17,11 +17,11 @@ use std::sync::Arc; pub async fn add( user: web::ReqData>, path: web::Path<(i32,)>, - pool: Data, + pg_pool: Data, sets: Data, ) -> Result { let id = path.0; - let stack = db::stack::fetch(pool.get_ref(), id) + let stack = db::stack::fetch(pg_pool.get_ref(), id) .await .map_err(|err| JsonResponse::::build().internal_server_error(err)) .and_then(|stack| match stack { diff --git a/src/routes/stack/get.rs b/src/routes/stack/get.rs index ac21f342..1e9492a5 100644 --- a/src/routes/stack/get.rs +++ b/src/routes/stack/get.rs @@ -12,12 +12,12 @@ use tracing::Instrument; pub async fn item( user: web::ReqData>, path: web::Path<(i32,)>, - pool: web::Data, + pg_pool: web::Data, ) -> Result { /// Get stack apps of logged user only let (id,) = path.into_inner(); - let stack = db::stack::fetch(pool.get_ref(), id) + let stack = db::stack::fetch(pg_pool.get_ref(), id) .await .map_err(|err| JsonResponse::::build().internal_server_error(err)) .and_then(|stack| match stack { @@ -36,14 +36,14 @@ pub async fn item( pub async fn list( user: web::ReqData>, path: web::Path<(String,)>, - pool: web::Data, + pg_pool: web::Data, ) -> Result { /// This is admin endpoint, used by a m2m app, client app is confidential /// it should return stacks by user id /// in order to pass validation at external deployment service let user_id = path.into_inner().0; - db::stack::fetch_by_user(pool.get_ref(), &user_id) + db::stack::fetch_by_user(pg_pool.get_ref(), &user_id) .await .map_err(|err| JsonResponse::::build().internal_server_error(err)) .map(|stacks| JsonResponse::build().set_list(stacks).ok("OK")) diff --git a/src/routes/stack/update.rs b/src/routes/stack/update.rs index a418b532..229553f7 100644 --- a/src/routes/stack/update.rs +++ b/src/routes/stack/update.rs @@ -1,21 +1,16 @@ -use chrono::Utc; -use actix_web::{ - web, - web::{Data}, - Responder, Result, -}; use crate::forms::stack::StackForm; use crate::helpers::JsonResponse; +use crate::models; use crate::models::user::User; use actix_web::post; +use actix_web::{web, web::Data, Responder, Result}; +use chrono::Utc; use serde_json::Value; -use sqlx::PgPool; use serde_valid::Validate; +use sqlx::PgPool; +use std::sync::Arc; use tracing::Instrument; use uuid::Uuid; -use crate::models; -use std::sync::Arc; - #[tracing::instrument(name = "Update stack.")] #[post("/{id}")] @@ -23,18 +18,14 @@ pub async fn update( path: web::Path<(i32,)>, form: web::Json, user: web::ReqData>, - pool: Data, + pg_pool: Data, ) -> Result { // @todo ACL let (id,) = path.into_inner(); let query_span = tracing::info_span!("Check existence by id."); - match sqlx::query_as!( - models::Stack, - r"SELECT * FROM user_stack WHERE id = $1", - id - ) - .fetch_one(pool.get_ref()) + match sqlx::query_as!(models::Stack, r"SELECT * FROM user_stack WHERE id = $1", id) + .fetch_one(pg_pool.get_ref()) .instrument(query_span) .await { @@ -60,7 +51,8 @@ pub async fn update( ); let _request_span_guard = request_span.enter(); // ->exit - tracing::info!("request_id {} Updating '{}' '{}'", + tracing::info!( + "request_id {} Updating '{}' '{}'", request_id, form.custom.project_name, form.region @@ -97,9 +89,9 @@ pub async fn update( Utc::now(), Utc::now(), ) - .execute(pool.get_ref()) - .instrument(query_span) - .await + .execute(pg_pool.get_ref()) + .instrument(query_span) + .await { Ok(record) => { tracing::info!( From ace2c26cfb382913459864d2f02f5a9133c86935 Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 09:39:20 +0200 Subject: [PATCH 08/25] issue-auth db_pool renamed to pg_pool --- src/startup.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/startup.rs b/src/startup.rs index 8b966eef..b592a4f3 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -12,17 +12,16 @@ use tracing_actix_web::TracingLogger; pub async fn run( listener: TcpListener, - db_pool: Pool, + pg_pool: Pool, settings: Settings, ) -> Result { let settings = web::Data::new(settings); - let db_pool = web::Data::new(db_pool); + let pg_pool = web::Data::new(pg_pool); let server = HttpServer::new(move || { App::new() .wrap(TracingLogger::default()) - .service(web::scope("/health_check") - .service(crate::routes::health_check)) + .service(web::scope("/health_check").service(crate::routes::health_check)) .service( web::scope("/client") .wrap(HttpAuthentication::bearer( @@ -64,7 +63,7 @@ pub async fn run( .service(crate::routes::stack::add::add) .service(crate::routes::stack::update::update), ) - .app_data(db_pool.clone()) + .app_data(pg_pool.clone()) .app_data(settings.clone()) }) .listen(listener)? From 1d4fc9688f5b0c715b752f660075fa68c056ecb3 Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 10:21:13 +0200 Subject: [PATCH 09/25] issue-auth helpers::MqPool --- Cargo.lock | 40 +++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/helpers/mod.rs | 2 ++ src/helpers/mq_pool.rs | 27 +++++++++++++++++++++++++ src/main.rs | 4 ++-- src/routes/stack/deploy.rs | 3 ++- src/startup.rs | 5 +++++ 7 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 src/helpers/mq_pool.rs diff --git a/Cargo.lock b/Cargo.lock index 73e0b28a..e7d155c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -975,11 +975,37 @@ dependencies = [ "tokio", ] +[[package]] +name = "deadpool" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" +dependencies = [ + "async-trait", + "deadpool-runtime", + "num_cpus", + "tokio", +] + +[[package]] +name = "deadpool-lapin" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce11c0dc86703e59a8921bb9afee10b13c242e47624347bd3a3b545c41db556e" +dependencies = [ + "deadpool 0.10.0", + "lapin", + "tokio-executor-trait", +] + [[package]] name = "deadpool-runtime" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +dependencies = [ + "tokio", +] [[package]] name = "deranged" @@ -3103,6 +3129,7 @@ dependencies = [ "chrono", "clap", "config", + "deadpool-lapin", "derive_builder", "futures", "futures-lite 1.13.0", @@ -3329,6 +3356,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-executor-trait" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "802ccf58e108fe16561f35348fabe15ff38218968f033d587e399a84937533cc" +dependencies = [ + "async-trait", + "executor-trait", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.2.0" @@ -3940,7 +3978,7 @@ dependencies = [ "assert-json-diff", "async-trait", "base64 0.21.5", - "deadpool", + "deadpool 0.9.5", "futures", "futures-timer", "http-types", diff --git a/Cargo.toml b/Cargo.toml index 54ee40f6..4555de3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ lapin = { version = "2.3.1", features = ["serde_json"] } futures-lite = "1.13.0" clap = { version = "4.4.8", features = ["derive"] } serde_path_to_error = "0.1.14" +deadpool-lapin = "0.11.0" [dependencies.sqlx] version = "0.6.3" diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index e5439f74..6d7d2a16 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -1,5 +1,7 @@ pub mod client; pub(crate) mod json; +mod mq_pool; pub(crate) mod stack; pub use json::*; +pub use mq_pool::MqPool; diff --git a/src/helpers/mq_pool.rs b/src/helpers/mq_pool.rs new file mode 100644 index 00000000..4e5bcbd1 --- /dev/null +++ b/src/helpers/mq_pool.rs @@ -0,0 +1,27 @@ +use deadpool_lapin::{Config, CreatePoolError, Pool, Runtime}; + +#[derive(Debug)] +pub struct MqPool { + pool: Pool, +} + +impl MqPool { + pub fn try_new(url: String) -> Result { + let mut cfg = Config::default(); + cfg.url = Some(url); + let pool = cfg.create_pool(Some(Runtime::Tokio1)).map_err(|err| { + tracing::error!("{:?}", err); + + match err { + CreatePoolError::Config(_) => { + std::io::Error::new(std::io::ErrorKind::Other, "config error") + } + CreatePoolError::Build(_) => { + std::io::Error::new(std::io::ErrorKind::Other, "build error") + } + } + })?; + + Ok(MqPool { pool }) + } +} diff --git a/src/main.rs b/src/main.rs index ebf4987c..8132f582 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ async fn main() -> std::io::Result<()> { let settings = get_configuration().expect("Failed to read configuration."); - let db_pool = PgPool::connect(&settings.database.connection_string()) + let pg_pool = PgPool::connect(&settings.database.connection_string()) .await .expect("Failed to connect to database."); @@ -20,5 +20,5 @@ async fn main() -> std::io::Result<()> { let listener = TcpListener::bind(address).expect(&format!("failed to bind to {}", settings.app_port)); - run(listener, db_pool, settings).await?.await + run(listener, pg_pool, settings).await?.await } diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index f18c99d6..2593c46e 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -2,7 +2,7 @@ use crate::configuration::Settings; use crate::db; use crate::forms::StackPayload; use crate::helpers::stack::builder::DcBuilder; -use crate::helpers::JsonResponse; +use crate::helpers::{JsonResponse, MqPool}; use crate::models; use actix_web::{post, web, web::Data, Responder, Result}; use futures_lite::stream::StreamExt; @@ -18,6 +18,7 @@ pub async fn add( user: web::ReqData>, path: web::Path<(i32,)>, pg_pool: Data, + mq_pool: Data, sets: Data, ) -> Result { let id = path.0; diff --git a/src/startup.rs b/src/startup.rs index b592a4f3..88312023 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -1,4 +1,5 @@ use crate::configuration::Settings; +use crate::helpers; use actix_cors::Cors; use actix_web::dev::Server; use actix_web::{ @@ -18,6 +19,9 @@ pub async fn run( let settings = web::Data::new(settings); let pg_pool = web::Data::new(pg_pool); + let mq_pool = helpers::MqPool::try_new(settings.amqp.connection_string())?; + let mq_pool = web::Data::new(mq_pool); + let server = HttpServer::new(move || { App::new() .wrap(TracingLogger::default()) @@ -64,6 +68,7 @@ pub async fn run( .service(crate::routes::stack::update::update), ) .app_data(pg_pool.clone()) + .app_data(mq_pool.clone()) .app_data(settings.clone()) }) .listen(listener)? From c6bf4a2c222ab43d2550c85e6d34e7d6f192b403 Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 10:31:31 +0200 Subject: [PATCH 10/25] issue-auth mq_manager --- src/helpers/mod.rs | 4 ++-- src/helpers/{mq_pool.rs => mq_manager.rs} | 8 +++++--- src/routes/stack/deploy.rs | 4 ++-- src/startup.rs | 6 +++--- 4 files changed, 12 insertions(+), 10 deletions(-) rename src/helpers/{mq_pool.rs => mq_manager.rs} (87%) diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index 6d7d2a16..6d3b1699 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -1,7 +1,7 @@ pub mod client; pub(crate) mod json; -mod mq_pool; +mod mq_manager; pub(crate) mod stack; pub use json::*; -pub use mq_pool::MqPool; +pub use mq_manager::MqManager; diff --git a/src/helpers/mq_pool.rs b/src/helpers/mq_manager.rs similarity index 87% rename from src/helpers/mq_pool.rs rename to src/helpers/mq_manager.rs index 4e5bcbd1..00b95261 100644 --- a/src/helpers/mq_pool.rs +++ b/src/helpers/mq_manager.rs @@ -1,11 +1,11 @@ use deadpool_lapin::{Config, CreatePoolError, Pool, Runtime}; #[derive(Debug)] -pub struct MqPool { +pub struct MqManager { pool: Pool, } -impl MqPool { +impl MqManager { pub fn try_new(url: String) -> Result { let mut cfg = Config::default(); cfg.url = Some(url); @@ -22,6 +22,8 @@ impl MqPool { } })?; - Ok(MqPool { pool }) + Ok(Self { pool }) } + + pub async fn create_channel() {} } diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 2593c46e..dc00eafd 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -2,7 +2,7 @@ use crate::configuration::Settings; use crate::db; use crate::forms::StackPayload; use crate::helpers::stack::builder::DcBuilder; -use crate::helpers::{JsonResponse, MqPool}; +use crate::helpers::{JsonResponse, MqManager}; use crate::models; use actix_web::{post, web, web::Data, Responder, Result}; use futures_lite::stream::StreamExt; @@ -18,7 +18,7 @@ pub async fn add( user: web::ReqData>, path: web::Path<(i32,)>, pg_pool: Data, - mq_pool: Data, + mq_manager: Data, sets: Data, ) -> Result { let id = path.0; diff --git a/src/startup.rs b/src/startup.rs index 88312023..b510af64 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -19,8 +19,8 @@ pub async fn run( let settings = web::Data::new(settings); let pg_pool = web::Data::new(pg_pool); - let mq_pool = helpers::MqPool::try_new(settings.amqp.connection_string())?; - let mq_pool = web::Data::new(mq_pool); + let mq_manager = helpers::MqManager::try_new(settings.amqp.connection_string())?; + let mq_manager = web::Data::new(mq_manager); let server = HttpServer::new(move || { App::new() @@ -68,7 +68,7 @@ pub async fn run( .service(crate::routes::stack::update::update), ) .app_data(pg_pool.clone()) - .app_data(mq_pool.clone()) + .app_data(mq_manager.clone()) .app_data(settings.clone()) }) .listen(listener)? From d870fcac78a1ed21f0293b993e2bb5dde1542259 Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 22:13:28 +0200 Subject: [PATCH 11/25] issue-auth mq_manager::publish_and_confirm --- src/helpers/mq_manager.rs | 64 +++++++++++++++++++++++++++++++++++++- src/routes/stack/deploy.rs | 51 ++++++------------------------ 2 files changed, 73 insertions(+), 42 deletions(-) diff --git a/src/helpers/mq_manager.rs b/src/helpers/mq_manager.rs index 00b95261..ed7a9b17 100644 --- a/src/helpers/mq_manager.rs +++ b/src/helpers/mq_manager.rs @@ -1,4 +1,9 @@ use deadpool_lapin::{Config, CreatePoolError, Pool, Runtime}; +use lapin::{ + options::*, + publisher_confirm::{Confirmation, PublisherConfirm}, + BasicProperties, Connection, ConnectionProperties, +}; #[derive(Debug)] pub struct MqManager { @@ -25,5 +30,62 @@ impl MqManager { Ok(Self { pool }) } - pub async fn create_channel() {} + pub async fn publish( + &self, + exchange: String, + routing_key: String, + payload: &[u8], + ) -> Result { + let addr = String::new(); + Connection::connect(&addr, ConnectionProperties::default()) + .await + .map_err(|err| { + tracing::error!("connecting to RabbitMQ {:?}", err); + format!("connecting to RabbitMQ {:?}", err) + })? + .create_channel() + .await + .map_err(|err| { + tracing::error!("creating RabbitMQ channel {:?}", err); + format!("creating RabbitMQ channel {:?}", err) + })? + .basic_publish( + "install", + routing_key.as_str(), + BasicPublishOptions::default(), + payload, + BasicProperties::default(), + ) + .await + .map_err(|err| { + tracing::error!("publishing message {:?}", err); + format!("publishing message {:?}", err) + }) + } + + pub async fn publish_and_confirm( + &self, + exchange: String, + routing_key: String, + payload: &[u8], + ) -> Result<(), String> { + self.publish(exchange, routing_key, payload) + .await + .map_err(|err| { + tracing::error!("publishing the message {:?}", err); + format!("publishing the message {:?}", err) + })? + .await + .map_err(|err| { + tracing::error!("confirming the publication {:?}", err); + format!("confirming the publication {:?}", err) + }) + .and_then(|confirm| match confirm { + Confirmation::NotRequested => { + tracing::error!("confirmation is NotRequested"); + Err(format!("confirmation is NotRequested")) + } + _ => Ok(()), + }) + } } diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index dc00eafd..86531193 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -6,9 +6,7 @@ use crate::helpers::{JsonResponse, MqManager}; use crate::models; use actix_web::{post, web, web::Data, Responder, Result}; use futures_lite::stream::StreamExt; -use lapin::{ - options::*, publisher_confirm::Confirmation, BasicProperties, Connection, ConnectionProperties, -}; +use lapin::publisher_confirm::Confirmation; use sqlx::PgPool; use std::sync::Arc; @@ -51,48 +49,19 @@ pub async fn add( let payload = serde_json::to_string::(&stack_data).map_err(|err| { tracing::error!("serializing StackPayload {:?}", err); JsonResponse::::build().internal_server_error("") - })?; - - let addr = sets.amqp.connection_string(); - let routing_key = "install.start.tfa.all.all".to_string(); - tracing::debug!("Sending message to {:?}", routing_key); + })?; //todo is it possible to use lapin serde - Connection::connect(&addr, ConnectionProperties::default()) - .await - .map_err(|err| { - tracing::error!("connecting to RabbitMQ {:?}", err); - JsonResponse::::build().internal_server_error("") - })? - .create_channel() - .await - .map_err(|err| { - tracing::error!("creating RabbitMQ channel {:?}", err); - JsonResponse::::build().internal_server_error("") - })? - .basic_publish( - "install", - routing_key.as_str(), - BasicPublishOptions::default(), + mq_manager + .publish_and_confirm( + "install".to_string(), + "install.start.tfa.all.all".to_string(), payload.as_bytes(), - BasicProperties::default(), ) .await - .map_err(|err| { - tracing::error!("publishing the message {:?}", err); - JsonResponse::::build().internal_server_error("") - })? - .await - .map_err(|err| { - tracing::error!("confirming the publication {:?}", err); - JsonResponse::::build().internal_server_error("") - }) - .and_then(|confirm| match confirm { - Confirmation::NotRequested => { - Err(JsonResponse::::build() - .bad_request("confirmation is NotRequested")) - } - _ => Ok(JsonResponse::::build() + .map_err(|err| JsonResponse::::build().internal_server_error(err)) + .map(|_| { + JsonResponse::::build() .set_id(id) - .ok("Success")), + .ok("Success") }) } From bf8cadc53164f58bfd48912b313bd1ce6a79856c Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 22:31:13 +0200 Subject: [PATCH 12/25] issue-auth move to deadpool --- src/helpers/mq_manager.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/helpers/mq_manager.rs b/src/helpers/mq_manager.rs index ed7a9b17..898f5af1 100644 --- a/src/helpers/mq_manager.rs +++ b/src/helpers/mq_manager.rs @@ -36,13 +36,12 @@ impl MqManager { routing_key: String, payload: &[u8], ) -> Result { - let addr = String::new(); - Connection::connect(&addr, ConnectionProperties::default()) - .await - .map_err(|err| { - tracing::error!("connecting to RabbitMQ {:?}", err); - format!("connecting to RabbitMQ {:?}", err) - })? + let connection = self.pool.get().await.map_err(|err| { + tracing::error!("getting connection from pool {:?}", err); + format!("getting connection from pool {:?}", err) + })?; + + connection .create_channel() .await .map_err(|err| { @@ -50,7 +49,7 @@ impl MqManager { format!("creating RabbitMQ channel {:?}", err) })? .basic_publish( - "install", + exchange.as_str(), routing_key.as_str(), BasicPublishOptions::default(), payload, From 67c2f592ef442150bde618ca8c2ae474ee68f5aa Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 22:40:08 +0200 Subject: [PATCH 13/25] issue_auth mq_manager.create_channel --- src/helpers/mq_manager.rs | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/helpers/mq_manager.rs b/src/helpers/mq_manager.rs index 898f5af1..707d4d17 100644 --- a/src/helpers/mq_manager.rs +++ b/src/helpers/mq_manager.rs @@ -2,7 +2,7 @@ use deadpool_lapin::{Config, CreatePoolError, Pool, Runtime}; use lapin::{ options::*, publisher_confirm::{Confirmation, PublisherConfirm}, - BasicProperties, Connection, ConnectionProperties, + BasicProperties, Channel, Connection, ConnectionProperties, }; #[derive(Debug)] @@ -30,24 +30,30 @@ impl MqManager { Ok(Self { pool }) } + async fn create_channel(&self) -> Result { + self.pool + .get() + .await + .map_err(|err| { + tracing::error!("getting connection from pool {:?}", err); + format!("getting connection from pool {:?}", err) + })? + .create_channel() + .await + .map_err(|err| { + tracing::error!("creating RabbitMQ channel {:?}", err); + format!("creating RabbitMQ channel {:?}", err) + }) + } + pub async fn publish( &self, exchange: String, routing_key: String, payload: &[u8], ) -> Result { - let connection = self.pool.get().await.map_err(|err| { - tracing::error!("getting connection from pool {:?}", err); - format!("getting connection from pool {:?}", err) - })?; - - connection - .create_channel() - .await - .map_err(|err| { - tracing::error!("creating RabbitMQ channel {:?}", err); - format!("creating RabbitMQ channel {:?}", err) - })? + self.create_channel() + .await? .basic_publish( exchange.as_str(), routing_key.as_str(), @@ -69,11 +75,7 @@ impl MqManager { payload: &[u8], ) -> Result<(), String> { self.publish(exchange, routing_key, payload) - .await - .map_err(|err| { - tracing::error!("publishing the message {:?}", err); - format!("publishing the message {:?}", err) - })? + .await? .await .map_err(|err| { tracing::error!("confirming the publication {:?}", err); From 9ad15f73b173c224b094dce934a9e5852f294de2 Mon Sep 17 00:00:00 2001 From: Petru Date: Sat, 30 Dec 2023 22:47:50 +0200 Subject: [PATCH 14/25] issue-auth mq_manager get_connection --- src/helpers/mq_manager.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/helpers/mq_manager.rs b/src/helpers/mq_manager.rs index 707d4d17..4fde2617 100644 --- a/src/helpers/mq_manager.rs +++ b/src/helpers/mq_manager.rs @@ -1,8 +1,8 @@ -use deadpool_lapin::{Config, CreatePoolError, Pool, Runtime}; +use deadpool_lapin::{Config, CreatePoolError, Object, Pool, Runtime}; use lapin::{ options::*, publisher_confirm::{Confirmation, PublisherConfirm}, - BasicProperties, Channel, Connection, ConnectionProperties, + BasicProperties, Channel, }; #[derive(Debug)] @@ -30,14 +30,16 @@ impl MqManager { Ok(Self { pool }) } + async fn get_connection(&self) -> Result { + self.pool.get().await.map_err(|err| { + tracing::error!("getting connection from pool {:?}", err); + format!("getting connection from pool {:?}", err) + }) + } + async fn create_channel(&self) -> Result { - self.pool - .get() - .await - .map_err(|err| { - tracing::error!("getting connection from pool {:?}", err); - format!("getting connection from pool {:?}", err) - })? + self.get_connection() + .await? .create_channel() .await .map_err(|err| { From 8d7e9a0136cb25e877411424e0e4bc32350156bf Mon Sep 17 00:00:00 2001 From: Petru Date: Sun, 31 Dec 2023 18:34:57 +0200 Subject: [PATCH 15/25] issue-auth tracing::instrument for DcBuilder::build --- src/helpers/stack/builder.rs | 130 ++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 1db77c54..42df43fa 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -1,12 +1,12 @@ +use crate::forms::{stack, App, StackForm, Volume, Web}; +use crate::helpers::stack::dctypes::{ + AdvancedVolumes, Compose, ComposeNetwork, ComposeNetworkSettingDetails, ComposeNetworks, + ComposeVolume, Entrypoint, Environment, MapOrEmpty, NetworkSettings, Networks, Port, Ports, + PublishedPort, Service, Services, SingleValue, TopLevelVolumes, Volumes, +}; +use crate::models::stack::Stack; use indexmap::IndexMap; -use crate::helpers::stack::dctypes::{Compose, Port, Ports, PublishedPort, Service, Services, - Volumes, Environment, Entrypoint, AdvancedVolumes, SingleValue, - Networks, TopLevelVolumes, ComposeVolume, ComposeNetwork, - ComposeNetworks, MapOrEmpty, ComposeNetworkSettingDetails, - NetworkSettings}; use serde_yaml; -use crate::forms::{StackForm, stack, App, Volume, Web}; -use crate::models::stack::Stack; #[derive(Clone, Debug)] struct Config {} @@ -16,7 +16,7 @@ impl Default for Config { } } -impl Default for Port{ +impl Default for Port { fn default() -> Self { Port { target: 80, @@ -38,10 +38,13 @@ pub struct DcBuilder { impl TryInto for Volume { type Error = String; fn try_into(self) -> Result { - let source = self.host_path.clone(); let target = self.container_path.clone(); - tracing::debug!("Volume conversion result: source: {:?} target: {:?}", source, target); + tracing::debug!( + "Volume conversion result: source: {:?} target: {:?}", + source, + target + ); Ok(AdvancedVolumes { source: source, target: target.unwrap_or("".to_string()), @@ -57,12 +60,18 @@ impl TryInto for Volume { impl TryInto for stack::Port { type Error = String; fn try_into(self) -> Result { - let cp = self.container_port.clone() + let cp = self + .container_port + .clone() .unwrap_or("".to_string()) - .parse::().map_err(|err| "Could not parse port".to_string() )?; - let hp = self.host_port.clone() + .parse::() + .map_err(|err| "Could not parse port".to_string())?; + let hp = self + .host_port + .clone() .unwrap_or("".to_string()) - .parse::().map_err(|err| "Could not parse port".to_string() )?; + .parse::() + .map_err(|err| "Could not parse port".to_string())?; tracing::debug!("Port conversion result: cp: {:?} hp: {:?}", cp, hp); Ok(Port { @@ -92,8 +101,7 @@ fn convert_shared_ports(ports: Option>) -> Result, St match ports { Some(ports) => { tracing::debug!("Ports >>>> {:?}", ports); - for port in ports { - } + for port in ports {} } None => { tracing::debug!("No ports defined by user"); @@ -126,25 +134,22 @@ impl TryIntoService for App { ..Default::default() }; - let networks: Networks = self.network - .clone() - .try_into() - .unwrap_or_default(); + let networks: Networks = self.network.clone().try_into().unwrap_or_default(); - let ports: Vec = self.ports + let ports: Vec = self + .ports .clone() .unwrap_or_default() .into_iter() .map(|x| x.try_into().unwrap()) .collect(); - let volumes: Vec = self.volumes + let volumes: Vec = self + .volumes .clone() .unwrap_or_default() .into_iter() - .map(|x| { - x.try_into().unwrap() - }) + .map(|x| x.try_into().unwrap()) .collect(); let mut envs = IndexMap::new(); @@ -152,7 +157,7 @@ impl TryIntoService for App { let items = item .into_iter() .map(|(k, v)| (k, Some(SingleValue::String(v.clone())))) - .collect::>(); + .collect::>(); envs.extend(items); } @@ -169,7 +174,6 @@ impl TryIntoService for App { impl Into>> for stack::ComposeNetworks { fn into(self) -> IndexMap> { - // tracing::debug!("networks found {:?}", self.networks); let mut networks = vec!["default_network".to_string()]; if self.networks.is_some() { @@ -177,59 +181,58 @@ impl Into>> for stack::ComposeNetwo } let networks = networks .into_iter() - .map(|net| - (net, - MapOrEmpty::Map( - NetworkSettings { - attachable: false, - driver: None, - driver_opts: Default::default(), - enable_ipv6: false, - internal: false, - // external: None, - external: Some(ComposeNetwork::Bool(true)), - ipam: None, - labels: Default::default(), - name: Some("default".to_string()), - } - )) - ) + .map(|net| { + ( + net, + MapOrEmpty::Map(NetworkSettings { + attachable: false, + driver: None, + driver_opts: Default::default(), + enable_ipv6: false, + internal: false, + // external: None, + external: Some(ComposeNetwork::Bool(true)), + ipam: None, + labels: Default::default(), + name: Some("default".to_string()), + }), + ) + }) .collect::>(); networks } } - pub fn extract_named_volumes(app: App) -> IndexMap> { - let mut named_volumes = IndexMap::default(); - let volumes = app.volumes - .unwrap() - .into_iter() - .filter(|volume| is_named_docker_volume( - volume.host_path.clone().unwrap().as_str()) - ) - .map(|volume| { - let k = volume.host_path.clone().unwrap(); - (k.clone(), MapOrEmpty::Map(ComposeVolume { + let volumes = app + .volumes + .unwrap() + .into_iter() + .filter(|volume| is_named_docker_volume(volume.host_path.clone().unwrap().as_str())) + .map(|volume| { + let k = volume.host_path.clone().unwrap(); + ( + k.clone(), + MapOrEmpty::Map(ComposeVolume { driver: None, driver_opts: Default::default(), external: None, labels: Default::default(), - name: Some(k.clone()) - })) - }) - .collect::>>(); + name: Some(k.clone()), + }), + ) + }) + .collect::>>(); - named_volumes.extend(volumes); + named_volumes.extend(volumes); // tracing::debug!("Named volumes: {:?}", named_volumes); named_volumes } impl DcBuilder { - pub fn new(stack: Stack) -> Self { DcBuilder { config: Config::default(), @@ -237,6 +240,7 @@ impl DcBuilder { } } + #[tracing::instrument(name = "building stack")] pub fn build(&self) -> Option { tracing::debug!("Start build docker compose from {:?}", &self.stack.body); let mut compose_content = Compose { @@ -277,7 +281,6 @@ impl DcBuilder { if !named_volumes.is_empty() { compose_content.volumes = TopLevelVolumes(named_volumes); } - } Err(e) => { tracing::debug!("Unpack stack form error {:?}", e); @@ -286,8 +289,7 @@ impl DcBuilder { tracing::debug!("services {:?}", &services); compose_content.services = Services(services); - - let fname= format!("./files/{}.yml", self.stack.stack_id); + let fname = format!("./files/{}.yml", self.stack.stack_id); tracing::debug!("Saving docker compose to file {:?}", fname); let target_file = std::path::Path::new(fname.as_str()); // serialize to string From ea374d7d054e81da977565812c1ee5d6b18631ef Mon Sep 17 00:00:00 2001 From: Petru Date: Sun, 31 Dec 2023 19:04:34 +0200 Subject: [PATCH 16/25] issue-auth DcBuilder build() --- src/helpers/stack/builder.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 42df43fa..5a42b75b 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -206,8 +206,12 @@ impl Into>> for stack::ComposeNetwo pub fn extract_named_volumes(app: App) -> IndexMap> { let mut named_volumes = IndexMap::default(); - let volumes = app - .volumes + let volumes = app.volumes; + if volumes.is_none() { + return named_volumes; + } + + let volumes = volumes .unwrap() .into_iter() .filter(|volume| is_named_docker_volume(volume.host_path.clone().unwrap().as_str())) @@ -293,12 +297,11 @@ impl DcBuilder { tracing::debug!("Saving docker compose to file {:?}", fname); let target_file = std::path::Path::new(fname.as_str()); // serialize to string - let serialized = match serde_yaml::to_string(&compose_content) { - Ok(s) => s, - Err(e) => panic!("Failed to serialize docker-compose file: {}", e), - }; - // serialize to file - std::fs::write(target_file, serialized.clone()).unwrap(); + let serialized = serde_yaml::to_string(&compose_content) + .map_err(|err| panic!("Failed to serialize docker-compose file: {}", err)) + .unwrap(); + + std::fs::write(target_file, serialized.clone()).map_err(|err| panic!("{}", err)); Some(serialized) } From fb7b13203b682efb19fe43185c23f8d2c22a1a46 Mon Sep 17 00:00:00 2001 From: petru Date: Sat, 6 Jan 2024 15:09:36 +0200 Subject: [PATCH 17/25] issue-auth mq_manager. publish. Serialize --- src/helpers/mq_manager.rs | 17 +++++++++++------ src/routes/stack/deploy.rs | 7 +------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/helpers/mq_manager.rs b/src/helpers/mq_manager.rs index 4fde2617..5b058ea4 100644 --- a/src/helpers/mq_manager.rs +++ b/src/helpers/mq_manager.rs @@ -4,6 +4,7 @@ use lapin::{ publisher_confirm::{Confirmation, PublisherConfirm}, BasicProperties, Channel, }; +use serde::ser::Serialize; #[derive(Debug)] pub struct MqManager { @@ -48,19 +49,23 @@ impl MqManager { }) } - pub async fn publish( + pub async fn publish( &self, exchange: String, routing_key: String, - payload: &[u8], + msg: &T, ) -> Result { + let payload = serde_json::to_string::(msg).map_err(|err| { + format!("{:?}", err) + })?; + self.create_channel() .await? .basic_publish( exchange.as_str(), routing_key.as_str(), BasicPublishOptions::default(), - payload, + payload.as_bytes(), BasicProperties::default(), ) .await @@ -70,13 +75,13 @@ impl MqManager { }) } - pub async fn publish_and_confirm( + pub async fn publish_and_confirm( &self, exchange: String, routing_key: String, - payload: &[u8], + msg: &T ) -> Result<(), String> { - self.publish(exchange, routing_key, payload) + self.publish(exchange, routing_key, msg) .await? .await .map_err(|err| { diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 86531193..f626cc07 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -46,16 +46,11 @@ pub async fn add( stack_data.user_email = Some(user.email.clone()); stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); - let payload = serde_json::to_string::(&stack_data).map_err(|err| { - tracing::error!("serializing StackPayload {:?}", err); - JsonResponse::::build().internal_server_error("") - })?; //todo is it possible to use lapin serde - mq_manager .publish_and_confirm( "install".to_string(), "install.start.tfa.all.all".to_string(), - payload.as_bytes(), + &stack_data, ) .await .map_err(|err| JsonResponse::::build().internal_server_error(err)) From 6ddd62ccef1363159ae9d73fbab93d5ddb7ec7e7 Mon Sep 17 00:00:00 2001 From: petru Date: Sat, 6 Jan 2024 21:44:03 +0200 Subject: [PATCH 18/25] issue-auth DcBuilder stack. try from --- src/forms/mod.rs | 4 +-- src/forms/stack.rs | 33 ---------------------- src/forms/stack_payload.rs | 54 ++++++++++++++++++++++++++++++++++++ src/helpers/stack/builder.rs | 6 ++-- src/routes/stack/deploy.rs | 12 ++------ 5 files changed, 62 insertions(+), 47 deletions(-) create mode 100644 src/forms/stack_payload.rs diff --git a/src/forms/mod.rs b/src/forms/mod.rs index ae65e1c4..cee99fef 100644 --- a/src/forms/mod.rs +++ b/src/forms/mod.rs @@ -1,8 +1,8 @@ mod rating; - pub mod stack; pub mod user; +mod stack_payload; pub use rating::*; - pub use stack::*; +pub use stack_payload::*; diff --git a/src/forms/stack.rs b/src/forms/stack.rs index cc322330..febd2af9 100644 --- a/src/forms/stack.rs +++ b/src/forms/stack.rs @@ -125,39 +125,6 @@ pub struct StackForm { pub custom: Custom, } -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] -#[serde(rename_all = "snake_case")] -pub struct StackPayload { - pub(crate) id: Option, - pub(crate) user_token: Option, - pub(crate) user_email: Option, - #[serde(rename = "commonDomain")] - pub common_domain: String, - pub domain_list: Option, - pub region: String, - pub zone: Option, - pub server: String, - pub os: String, - pub ssl: String, - pub vars: Option>, - #[serde(rename = "integrated_features")] - pub integrated_features: Option>, - #[serde(rename = "extended_features")] - pub extended_features: Option>, - pub subscriptions: Option>, - pub form_app: Option>, - pub disk_type: Option, - #[serde(rename = "save_token")] - pub save_token: bool, - #[serde(rename = "cloud_token")] - pub cloud_token: String, - pub provider: String, - pub stack_code: String, - #[serde(rename = "selected_plan")] - pub selected_plan: String, - pub custom: Custom, -} - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DomainList {} diff --git a/src/forms/stack_payload.rs b/src/forms/stack_payload.rs new file mode 100644 index 00000000..521642d5 --- /dev/null +++ b/src/forms/stack_payload.rs @@ -0,0 +1,54 @@ +use std::convert::TryFrom; +use crate::models; +use crate::forms; +use serde_json::Value; +use serde::{Deserialize, Serialize}; +use serde_valid::Validate; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] +#[serde(rename_all = "snake_case")] +pub struct StackPayload { + pub(crate) id: Option, + pub(crate) user_token: Option, + pub(crate) user_email: Option, + #[serde(rename = "commonDomain")] + pub common_domain: String, + pub domain_list: Option, + pub region: String, + pub zone: Option, + pub server: String, + pub os: String, + pub ssl: String, + pub vars: Option>, + #[serde(rename = "integrated_features")] + pub integrated_features: Option>, + #[serde(rename = "extended_features")] + pub extended_features: Option>, + pub subscriptions: Option>, + pub form_app: Option>, + pub disk_type: Option, + #[serde(rename = "save_token")] + pub save_token: bool, + #[serde(rename = "cloud_token")] + pub cloud_token: String, + pub provider: String, + pub stack_code: String, + #[serde(rename = "selected_plan")] + pub selected_plan: String, + pub custom: forms::stack::Custom, +} + +impl TryFrom<&models::Stack> for StackPayload { + type Error = String; + + fn try_from(stack: &models::Stack) -> Result { + let mut stack_data = serde_json::from_value::(stack.body.clone()).map_err(|err| { + format!("{:?}", err) + })?; + + stack_data.id = Some(stack.id.clone()); + stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); + + Ok(stack_data) + } +} diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 5a42b75b..eeca4a2a 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -4,7 +4,7 @@ use crate::helpers::stack::dctypes::{ ComposeVolume, Entrypoint, Environment, MapOrEmpty, NetworkSettings, Networks, Port, Ports, PublishedPort, Service, Services, SingleValue, TopLevelVolumes, Volumes, }; -use crate::models::stack::Stack; +use crate::models; use indexmap::IndexMap; use serde_yaml; #[derive(Clone, Debug)] @@ -32,7 +32,7 @@ impl Default for Port { #[derive(Clone, Debug)] pub struct DcBuilder { config: Config, - pub(crate) stack: Stack, + pub(crate) stack: models::Stack, } impl TryInto for Volume { @@ -237,7 +237,7 @@ pub fn extract_named_volumes(app: App) -> IndexMap Self { + pub fn new(stack: models::Stack) -> Self { DcBuilder { config: Config::default(), stack, diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index f626cc07..80f49858 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -1,6 +1,6 @@ use crate::configuration::Settings; use crate::db; -use crate::forms::StackPayload; +use crate::forms; use crate::helpers::stack::builder::DcBuilder; use crate::helpers::{JsonResponse, MqManager}; use crate::models; @@ -35,16 +35,10 @@ pub async fn add( JsonResponse::::build().internal_server_error("") })?; - let mut stack_data = - serde_json::from_value::(dc.stack.body.clone()).map_err(|err| { - tracing::error!("transforming json Value into StackPayload {:?}", err); - JsonResponse::::build().bad_request("") - })?; - - stack_data.id = Some(id); + let mut stack_data = forms::StackPayload::try_from(&dc.stack) + .map_err(|err| JsonResponse::::build().bad_request(err))?; stack_data.user_token = Some(user.id.clone()); stack_data.user_email = Some(user.email.clone()); - stack_data.stack_code = stack_data.custom.custom_stack_code.clone(); mq_manager .publish_and_confirm( From 0c8936690caf53e6e3e31ff7ca5039460be21c92 Mon Sep 17 00:00:00 2001 From: petru Date: Sun, 7 Jan 2024 08:51:14 +0200 Subject: [PATCH 19/25] issue-auth Option->Result for DcBuilder::build --- src/helpers/stack/builder.rs | 74 ++++++++++++++++-------------------- src/routes/stack/compose.rs | 18 +++++---- src/routes/stack/deploy.rs | 5 +-- 3 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index eeca4a2a..1b7c0a9e 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -124,7 +124,7 @@ fn is_named_docker_volume(volume: &str) -> bool { } trait TryIntoService { - fn try_into_service(&self) -> Service; + fn try_into_service(&self) -> Service; //todo transform into try_into } impl TryIntoService for App { @@ -245,64 +245,56 @@ impl DcBuilder { } #[tracing::instrument(name = "building stack")] - pub fn build(&self) -> Option { - tracing::debug!("Start build docker compose from {:?}", &self.stack.body); + pub fn build(&self) -> Result { let mut compose_content = Compose { version: Some("3.8".to_string()), ..Default::default() }; - let _stack = serde_json::from_value::(self.stack.body.clone()); + let apps = serde_json::from_value::(self.stack.body.clone()) + .map_err(|err| format!("{:?}", err))?; let mut services = IndexMap::new(); let mut named_volumes = IndexMap::default(); - match _stack { - Ok(apps) => { - for app_type in &apps.custom.web { - let service = app_type.app.try_into_service(); - services.insert(app_type.app.code.clone().to_owned(), Some(service)); - named_volumes.extend(extract_named_volumes(app_type.app.clone())); - } - - if let Some(srvs) = apps.custom.service { - for app_type in srvs { - let service = app_type.app.try_into_service(); - services.insert(app_type.app.code.clone().to_owned(), Some(service)); - named_volumes.extend(extract_named_volumes(app_type.app.clone())); - } - } - - if let Some(features) = apps.custom.feature { - for app_type in features { - let service = app_type.app.try_into_service(); - services.insert(app_type.app.code.clone().to_owned(), Some(service)); - named_volumes.extend(extract_named_volumes(app_type.app.clone())); - } - } - - let networks = apps.custom.networks.clone(); - compose_content.networks = ComposeNetworks(networks.into()); - - if !named_volumes.is_empty() { - compose_content.volumes = TopLevelVolumes(named_volumes); - } + for app_type in &apps.custom.web { + let service = app_type.app.try_into_service(); //todo + services.insert(app_type.app.code.clone().to_owned(), Some(service)); + named_volumes.extend(extract_named_volumes(app_type.app.clone())); + } + + if let Some(srvs) = apps.custom.service { + for app_type in srvs { + let service = app_type.app.try_into_service(); //todo + services.insert(app_type.app.code.clone().to_owned(), Some(service)); + named_volumes.extend(extract_named_volumes(app_type.app.clone())); } - Err(e) => { - tracing::debug!("Unpack stack form error {:?}", e); + } + + if let Some(features) = apps.custom.feature { + for app_type in features { + let service = app_type.app.try_into_service(); //todo + services.insert(app_type.app.code.clone().to_owned(), Some(service)); + named_volumes.extend(extract_named_volumes(app_type.app.clone())); } } + + let networks = apps.custom.networks.clone(); + compose_content.networks = ComposeNetworks(networks.into()); + + if !named_volumes.is_empty() { + compose_content.volumes = TopLevelVolumes(named_volumes); + } + tracing::debug!("services {:?}", &services); compose_content.services = Services(services); let fname = format!("./files/{}.yml", self.stack.stack_id); tracing::debug!("Saving docker compose to file {:?}", fname); let target_file = std::path::Path::new(fname.as_str()); - // serialize to string let serialized = serde_yaml::to_string(&compose_content) - .map_err(|err| panic!("Failed to serialize docker-compose file: {}", err)) - .unwrap(); + .map_err(|err| format!("Failed to serialize docker-compose file: {}", err))?; - std::fs::write(target_file, serialized.clone()).map_err(|err| panic!("{}", err)); + std::fs::write(target_file, serialized.clone()).map_err(|err| format!("{}", err))?; - Some(serialized) + Ok(serialized) } } diff --git a/src/routes/stack/compose.rs b/src/routes/stack/compose.rs index 4e58141e..b8b51233 100644 --- a/src/routes/stack/compose.rs +++ b/src/routes/stack/compose.rs @@ -26,10 +26,11 @@ pub async fn add( })?; let id = stack.id.clone(); - let fc = DcBuilder::new(stack).build().ok_or_else(|| { - tracing::error!("Error. Compose builder returned an empty string"); - JsonResponse::::build().internal_server_error("troubles at building") - })?; + let fc = DcBuilder::new(stack) + .build() + .map_err(|err| { + JsonResponse::::build().internal_server_error(err) + })?; Ok(JsonResponse::build().set_id(id).set_item(fc).ok("Success")) } @@ -52,10 +53,11 @@ pub async fn admin( })?; let id = stack.id.clone(); - let fc = DcBuilder::new(stack).build().ok_or_else(|| { - tracing::error!("Error. Compose builder returned an empty string"); - JsonResponse::::build().internal_server_error("troubles at building") - })?; + let fc = DcBuilder::new(stack) + .build() + .map_err(|err| { + JsonResponse::::build().internal_server_error(err) + })?; Ok(JsonResponse::build().set_id(id).set_item(fc).ok("Success")) } diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 80f49858..005ac531 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -30,9 +30,8 @@ pub async fn add( let id = stack.id.clone(); let dc = DcBuilder::new(stack); - dc.build().ok_or_else(|| { - tracing::error!("Error. Compose builder returned an empty string"); - JsonResponse::::build().internal_server_error("") + dc.build().map_err(|err| { + JsonResponse::::build().internal_server_error(err) })?; let mut stack_data = forms::StackPayload::try_from(&dc.stack) From 3bad20d8927ee81c9e2a8b1b05ca9667e79344e6 Mon Sep 17 00:00:00 2001 From: petru Date: Sun, 7 Jan 2024 09:48:53 +0200 Subject: [PATCH 20/25] issue-auth StackForm::try_from --- src/forms/mod.rs | 2 ++ src/forms/stack.rs | 46 --------------------------- src/forms/stack_form.rs | 61 ++++++++++++++++++++++++++++++++++++ src/helpers/stack/builder.rs | 4 +-- src/routes/stack/add.rs | 14 ++++----- src/routes/stack/update.rs | 8 ++--- 6 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 src/forms/stack_form.rs diff --git a/src/forms/mod.rs b/src/forms/mod.rs index cee99fef..a1379dec 100644 --- a/src/forms/mod.rs +++ b/src/forms/mod.rs @@ -2,7 +2,9 @@ mod rating; pub mod stack; pub mod user; mod stack_payload; +mod stack_form; pub use rating::*; pub use stack::*; pub use stack_payload::*; +pub use stack_form::*; diff --git a/src/forms/stack.rs b/src/forms/stack.rs index febd2af9..a9fc3ccc 100644 --- a/src/forms/stack.rs +++ b/src/forms/stack.rs @@ -79,52 +79,6 @@ impl AsRef for App { } } -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] -pub struct StackForm { - // #[validate(min_length=2)] - // #[validate(max_length=255)] - #[serde(rename = "commonDomain")] - pub common_domain: Option, - pub domain_list: Option, - #[validate(min_length = 2)] - #[validate(max_length = 255)] - pub stack_code: Option, - #[validate(min_length = 2)] - #[validate(max_length = 50)] - pub region: String, - #[validate(min_length = 2)] - #[validate(max_length = 50)] - pub zone: Option, - #[validate(min_length = 2)] - #[validate(max_length = 50)] - pub server: String, - #[validate(min_length = 2)] - #[validate(max_length = 50)] - pub os: String, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - pub ssl: String, - pub vars: Option>, - pub integrated_features: Option>, - pub extended_features: Option>, - pub subscriptions: Option>, - pub form_app: Option>, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - pub disk_type: Option, - pub save_token: bool, - #[validate(min_length = 10)] - #[validate(max_length = 255)] - pub cloud_token: String, - #[validate(min_length = 2)] - #[validate(max_length = 50)] - pub provider: String, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - pub selected_plan: String, - pub custom: Custom, -} - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DomainList {} diff --git a/src/forms/stack_form.rs b/src/forms/stack_form.rs new file mode 100644 index 00000000..989205af --- /dev/null +++ b/src/forms/stack_form.rs @@ -0,0 +1,61 @@ +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use serde_valid::Validate; +use std::collections::HashMap; +use std::fmt; +use crate::models; +use crate::forms; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] +pub struct StackForm { + // #[validate(min_length=2)] + // #[validate(max_length=255)] + #[serde(rename = "commonDomain")] + pub common_domain: Option, + pub domain_list: Option, + #[validate(min_length = 2)] + #[validate(max_length = 255)] + pub stack_code: Option, + #[validate(min_length = 2)] + #[validate(max_length = 50)] + pub region: String, + #[validate(min_length = 2)] + #[validate(max_length = 50)] + pub zone: Option, + #[validate(min_length = 2)] + #[validate(max_length = 50)] + pub server: String, + #[validate(min_length = 2)] + #[validate(max_length = 50)] + pub os: String, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + pub ssl: String, + pub vars: Option>, + pub integrated_features: Option>, + pub extended_features: Option>, + pub subscriptions: Option>, + pub form_app: Option>, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + pub disk_type: Option, + pub save_token: bool, + #[validate(min_length = 10)] + #[validate(max_length = 255)] + pub cloud_token: String, + #[validate(min_length = 2)] + #[validate(max_length = 50)] + pub provider: String, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + pub selected_plan: String, + pub custom: forms::Custom, +} + +impl TryFrom<&models::Stack> for StackForm { + type Error = String; + + fn try_from(stack: &models::Stack) -> Result { + serde_json::from_value::(stack.body.clone()).map_err(|err| format!("{:?}", err)) + } +} diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 1b7c0a9e..ea91da78 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -250,8 +250,8 @@ impl DcBuilder { version: Some("3.8".to_string()), ..Default::default() }; - let apps = serde_json::from_value::(self.stack.body.clone()) - .map_err(|err| format!("{:?}", err))?; + + let apps = StackForm::try_from(&self.stack)?; let mut services = IndexMap::new(); let mut named_volumes = IndexMap::default(); diff --git a/src/routes/stack/add.rs b/src/routes/stack/add.rs index 7ed5a09b..bcf281c7 100644 --- a/src/routes/stack/add.rs +++ b/src/routes/stack/add.rs @@ -1,5 +1,5 @@ use crate::db; -use crate::forms::stack::StackForm; +use crate::forms; use crate::helpers::JsonResponse; use crate::models; use actix_web::Error; @@ -27,8 +27,8 @@ pub async fn add( check_if_stack_exists(pg_pool.get_ref(), &stack_name).await?; - let body: Value = serde_json::to_value::(form) - .or(serde_json::to_value::(StackForm::default())) + let body: Value = serde_json::to_value::(form) + .or(serde_json::to_value::(forms::StackForm::default())) .unwrap(); let stack = models::Stack::new(user.id.clone(), stack_name, body); @@ -53,17 +53,17 @@ async fn check_if_stack_exists(pg_pool: &PgPool, stack_name: &String) -> Result< }) } -async fn body_into_form(body: Bytes) -> Result { +async fn body_into_form(body: Bytes) -> Result { let body_bytes = actix_web::body::to_bytes(body).await.unwrap(); let body_str = str::from_utf8(&body_bytes) - .map_err(|err| JsonResponse::::build().internal_server_error(err.to_string()))?; + .map_err(|err| JsonResponse::::build().internal_server_error(err.to_string()))?; let deserializer = &mut serde_json::Deserializer::from_str(body_str); serde_path_to_error::deserialize(deserializer) .map_err(|err| { let msg = format!("{}:{:?}", err.path().to_string(), err); - JsonResponse::::build().bad_request(msg) + JsonResponse::::build().bad_request(msg) }) - .and_then(|form: StackForm| { + .and_then(|form: forms::StackForm| { if !form.validate().is_ok() { let errors = form.validate().unwrap_err(); let err_msg = format!("Invalid data received {:?}", &errors.to_string()); diff --git a/src/routes/stack/update.rs b/src/routes/stack/update.rs index 229553f7..a22be0c2 100644 --- a/src/routes/stack/update.rs +++ b/src/routes/stack/update.rs @@ -1,4 +1,4 @@ -use crate::forms::stack::StackForm; +use crate::forms; use crate::helpers::JsonResponse; use crate::models; use crate::models::user::User; @@ -16,7 +16,7 @@ use uuid::Uuid; #[post("/{id}")] pub async fn update( path: web::Path<(i32,)>, - form: web::Json, + form: web::Json, user: web::ReqData>, pg_pool: Data, ) -> Result { @@ -67,11 +67,11 @@ pub async fn update( return Err(JsonResponse::::build().bad_request(errors.to_string())); } - let body: Value = match serde_json::to_value::(form.into_inner()) { + let body: Value = match serde_json::to_value::(form.into_inner()) { Ok(body) => body, Err(err) => { tracing::error!("Request_id {} error unwrap body {:?}", request_id, err); - serde_json::to_value::(StackForm::default()).unwrap() + serde_json::to_value::(forms::StackForm::default()).unwrap() } }; From 27e66b97acd49e65bbcf488d86bd2656edfb87ca Mon Sep 17 00:00:00 2001 From: petru Date: Sun, 7 Jan 2024 22:58:15 +0200 Subject: [PATCH 21/25] issue-auth Networks::try_from --- src/helpers/stack/builder.rs | 44 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index ea91da78..4acf9631 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -84,14 +84,18 @@ impl TryInto for stack::Port { } } -impl TryInto for stack::ServiceNetworks { +impl TryFrom<&stack::ServiceNetworks> for Networks { type Error = (); - fn try_into(self) -> Result { - let mut networks = vec!["default_network".to_string()]; - if self.network.is_some() { - networks.append(&mut self.network.unwrap()); - } - Ok(Networks::Simple(networks)) + + fn try_from(serviceNetworks: &stack::ServiceNetworks) -> Result { + let mut result = vec!["default_network".to_string()]; + serviceNetworks.network.as_ref().map(|networks| { + for n in networks { + result.push(n.to_string()); + } + }); + + Ok(Networks::Simple(result)) } } @@ -123,20 +127,18 @@ fn is_named_docker_volume(volume: &str) -> bool { is_alphanumeric && does_not_contain_slash } -trait TryIntoService { - fn try_into_service(&self) -> Service; //todo transform into try_into -} +impl TryFrom<&App> for Service { + type Error = String; -impl TryIntoService for App { - fn try_into_service(&self) -> Service { + fn try_from(app: &App) -> Result { let mut service = Service { - image: Some(self.docker_image.to_string()), + image: Some(app.docker_image.to_string()), ..Default::default() }; - let networks: Networks = self.network.clone().try_into().unwrap_or_default(); + let networks = Networks::try_from(&app.network).unwrap_or_default(); - let ports: Vec = self + let ports: Vec = app //todo .ports .clone() .unwrap_or_default() @@ -144,7 +146,7 @@ impl TryIntoService for App { .map(|x| x.try_into().unwrap()) .collect(); - let volumes: Vec = self + let volumes: Vec = app //todo .volumes .clone() .unwrap_or_default() @@ -153,7 +155,7 @@ impl TryIntoService for App { .collect(); let mut envs = IndexMap::new(); - for item in self.environment.environment.clone().unwrap_or_default() { + for item in app.environment.environment.clone().unwrap_or_default() { //todo let items = item .into_iter() .map(|(k, v)| (k, Some(SingleValue::String(v.clone())))) @@ -168,7 +170,7 @@ impl TryIntoService for App { service.volumes = Volumes::Advanced(volumes); service.environment = Environment::KvPair(envs); - service + Ok(service) } } @@ -256,14 +258,14 @@ impl DcBuilder { let mut named_volumes = IndexMap::default(); for app_type in &apps.custom.web { - let service = app_type.app.try_into_service(); //todo + let service = Service::try_from(&app_type.app)?; services.insert(app_type.app.code.clone().to_owned(), Some(service)); named_volumes.extend(extract_named_volumes(app_type.app.clone())); } if let Some(srvs) = apps.custom.service { for app_type in srvs { - let service = app_type.app.try_into_service(); //todo + let service = Service::try_from(&app_type.app)?; services.insert(app_type.app.code.clone().to_owned(), Some(service)); named_volumes.extend(extract_named_volumes(app_type.app.clone())); } @@ -271,7 +273,7 @@ impl DcBuilder { if let Some(features) = apps.custom.feature { for app_type in features { - let service = app_type.app.try_into_service(); //todo + let service = Service::try_from(&app_type.app)?; services.insert(app_type.app.code.clone().to_owned(), Some(service)); named_volumes.extend(extract_named_volumes(app_type.app.clone())); } From 3e01e8741207c96b4c2963de66365cf3368b8493 Mon Sep 17 00:00:00 2001 From: petru Date: Sun, 7 Jan 2024 23:50:43 +0200 Subject: [PATCH 22/25] issue-auth TryInto --- src/helpers/stack/builder.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 4acf9631..55314ce2 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -1,4 +1,5 @@ use crate::forms::{stack, App, StackForm, Volume, Web}; +use crate::forms; use crate::helpers::stack::dctypes::{ AdvancedVolumes, Compose, ComposeNetwork, ComposeNetworkSettingDetails, ComposeNetworks, ComposeVolume, Entrypoint, Environment, MapOrEmpty, NetworkSettings, Networks, Port, Ports, @@ -57,23 +58,21 @@ impl TryInto for Volume { } } -impl TryInto for stack::Port { +impl TryInto for &stack::Port { type Error = String; fn try_into(self) -> Result { let cp = self .container_port - .clone() - .unwrap_or("".to_string()) - .parse::() + .as_ref() + .map_or(Ok(0u16), |s| s.parse::()) .map_err(|err| "Could not parse port".to_string())?; + let hp = self .host_port - .clone() - .unwrap_or("".to_string()) - .parse::() + .as_ref() + .map_or(Ok(0u16), |s| s.parse::()) .map_err(|err| "Could not parse port".to_string())?; - tracing::debug!("Port conversion result: cp: {:?} hp: {:?}", cp, hp); Ok(Port { target: cp, host_ip: None, @@ -138,13 +137,16 @@ impl TryFrom<&App> for Service { let networks = Networks::try_from(&app.network).unwrap_or_default(); - let ports: Vec = app //todo - .ports - .clone() - .unwrap_or_default() - .into_iter() - .map(|x| x.try_into().unwrap()) - .collect(); + let ports: Vec = match &app.ports { + Some(ports) => { + let mut collector = vec![]; + for port in ports { + collector.push(port.try_into()?); + } + collector + } + None => vec![] + }; let volumes: Vec = app //todo .volumes From bddf56fc8e28e1f12964bfe8f82b78bb0bc61cc5 Mon Sep 17 00:00:00 2001 From: petru Date: Mon, 8 Jan 2024 21:47:11 +0200 Subject: [PATCH 23/25] issue_auth stack_app --- src/forms/mod.rs | 4 ++ src/forms/stack.rs | 105 ++--------------------------- src/forms/stack_app.rs | 126 +++++++++++++++++++++++++++++++++++ src/forms/stack_custom.rs | 81 ++++++++++++++++++++++ src/forms/stack_payload.rs | 2 +- src/helpers/stack/builder.rs | 69 +------------------ 6 files changed, 218 insertions(+), 169 deletions(-) create mode 100644 src/forms/stack_app.rs create mode 100644 src/forms/stack_custom.rs diff --git a/src/forms/mod.rs b/src/forms/mod.rs index a1379dec..b7ef2dcf 100644 --- a/src/forms/mod.rs +++ b/src/forms/mod.rs @@ -3,8 +3,12 @@ pub mod stack; pub mod user; mod stack_payload; mod stack_form; +mod stack_custom; +mod stack_app; pub use rating::*; pub use stack::*; pub use stack_payload::*; pub use stack_form::*; +pub use stack_custom::*; +pub use stack_app::*; diff --git a/src/forms/stack.rs b/src/forms/stack.rs index a9fc3ccc..d62fa319 100644 --- a/src/forms/stack.rs +++ b/src/forms/stack.rs @@ -3,6 +3,7 @@ use serde_json::Value; use serde_valid::Validate; use std::collections::HashMap; use std::fmt; +use crate::forms; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] pub struct Role { @@ -73,12 +74,6 @@ impl fmt::Display for DockerImage { } } -impl AsRef for App { - fn as_ref(&self) -> &DockerImage { - &self.docker_image - } -} - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DomainList {} @@ -91,103 +86,11 @@ pub struct Var {} pub struct Price { pub value: f64, } -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] -pub struct Custom { - pub web: Vec, - pub feature: Option>, - pub service: Option>, - #[validate(minimum = 0)] - #[validate(maximum = 10)] - pub servers_count: u32, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - pub custom_stack_code: String, - #[validate(min_length = 3)] - #[validate(max_length = 255)] - pub project_git_url: Option, - pub custom_stack_category: Option>, - pub custom_stack_short_description: Option, - pub custom_stack_description: Option, - #[validate(min_length = 3)] - #[validate(max_length = 255)] - pub project_name: String, - pub project_overview: Option, - pub project_description: Option, - #[serde(flatten)] - pub networks: ComposeNetworks, // all networks -} - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] pub struct Network { name: String, } -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] -pub struct App { - #[serde(rename = "_etag")] - #[validate(min_length = 3)] - #[validate(max_length = 255)] - pub etag: Option, - #[serde(rename = "_id")] - pub id: u32, - #[serde(rename = "_created")] - pub created: Option, - #[serde(rename = "_updated")] - pub updated: Option, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - pub name: String, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - pub code: String, - #[validate(min_length = 3)] - #[validate(max_length = 50)] - #[serde(rename = "type")] - pub type_field: String, - #[serde(flatten)] - pub role: Role, - pub default: Option, - pub versions: Option>, - #[serde(flatten)] - pub docker_image: DockerImage, - #[serde(flatten)] - pub requirements: Requirements, - #[validate(minimum = 1)] - pub popularity: Option, - pub commercial: Option, - pub subscription: Option, - pub autodeploy: Option, - pub suggested: Option, - pub dependency: Option, - pub avoid_render: Option, - pub price: Option, - pub icon: Option, - pub domain: Option, - pub category_id: Option, - pub parent_app_id: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub descr: Option, - pub full_description: Option, - pub description: Option, - pub plan_type: Option, - pub ansible_var: Option, - pub repo_dir: Option, - pub url_app: Option, - pub url_git: Option, - pub restart: Option, - pub volumes: Option>, - #[serde(flatten)] - pub environment: Environment, - #[serde(flatten)] - pub network: ServiceNetworks, - // #[serde(flatten)] - // pub ports: Ports, - #[serde(rename(deserialize = "sharedPorts"))] - #[serde(rename(serialize = "shared_ports"))] - #[serde(alias = "shared_ports")] - pub ports: Option>, -} - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Environment { pub(crate) environment: Option>>, @@ -217,7 +120,7 @@ pub struct ComposeNetworks { #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Web { #[serde(flatten)] - pub app: App, + pub app: forms::App, pub custom: Option, pub main: bool, } @@ -229,7 +132,7 @@ pub struct Feature { // #[serde(alias = "shared_ports")] // pub shared_ports: Option>, #[serde(flatten)] - pub app: App, + pub app: forms::App, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] @@ -239,7 +142,7 @@ pub struct Service { // #[serde(alias = "shared_ports")] // pub shared_ports: Option>, #[serde(flatten)] - pub(crate) app: App, + pub(crate) app: forms::App, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/src/forms/stack_app.rs b/src/forms/stack_app.rs new file mode 100644 index 00000000..8ebdec38 --- /dev/null +++ b/src/forms/stack_app.rs @@ -0,0 +1,126 @@ +use crate::forms; +use crate::helpers::stack::dctypes; +use indexmap::IndexMap; +use serde_json::Value; +use serde::{Deserialize, Serialize}; +use serde_valid::Validate; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] +pub struct App { + #[serde(rename = "_etag")] + #[validate(min_length = 3)] + #[validate(max_length = 255)] + pub etag: Option, + #[serde(rename = "_id")] + pub id: u32, + #[serde(rename = "_created")] + pub created: Option, + #[serde(rename = "_updated")] + pub updated: Option, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + pub name: String, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + pub code: String, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + #[serde(rename = "type")] + pub type_field: String, + #[serde(flatten)] + pub role: forms::Role, + pub default: Option, + pub versions: Option>, + #[serde(flatten)] + pub docker_image: forms::DockerImage, + #[serde(flatten)] + pub requirements: forms::Requirements, + #[validate(minimum = 1)] + pub popularity: Option, + pub commercial: Option, + pub subscription: Option, + pub autodeploy: Option, + pub suggested: Option, + pub dependency: Option, + pub avoid_render: Option, + pub price: Option, + pub icon: Option, + pub domain: Option, + pub category_id: Option, + pub parent_app_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub descr: Option, + pub full_description: Option, + pub description: Option, + pub plan_type: Option, + pub ansible_var: Option, + pub repo_dir: Option, + pub url_app: Option, + pub url_git: Option, + pub restart: Option, + pub volumes: Option>, + #[serde(flatten)] + pub environment: forms::Environment, + #[serde(flatten)] + pub network: forms::ServiceNetworks, + // #[serde(flatten)] + // pub ports: Ports, + #[serde(rename(deserialize = "sharedPorts"))] + #[serde(rename(serialize = "shared_ports"))] + #[serde(alias = "shared_ports")] + pub ports: Option>, +} + +impl App { + pub fn named_volumes(&self) -> IndexMap> { //todo Result + let mut named_volumes = IndexMap::default(); + + let volumes = &self.volumes; + if volumes.is_none() { + return named_volumes; + } + + let volumes = volumes + .clone() //todo remove it + .unwrap() + .into_iter() + .filter(|volume| is_named_docker_volume(volume.host_path.clone().unwrap().as_str())) + .map(|volume| { + let k = volume.host_path.clone().unwrap(); + ( + k.clone(), + dctypes::MapOrEmpty::Map(dctypes::ComposeVolume { + driver: None, + driver_opts: Default::default(), + external: None, + labels: Default::default(), + name: Some(k.clone()), + }), + ) + }) + .collect::>>(); + + named_volumes.extend(volumes); + // tracing::debug!("Named volumes: {:?}", named_volumes); + + named_volumes + } +} + +impl AsRef for App { + fn as_ref(&self) -> &forms::DockerImage { + &self.docker_image + } +} + + +fn is_named_docker_volume(volume: &str) -> bool { //todo + // Docker named volumes typically don't contain special characters or slashes + // They are alphanumeric and may include underscores or hyphens + let is_alphanumeric = volume + .chars() + .all(|c| c.is_alphanumeric() || c == '_' || c == '-'); + let does_not_contain_slash = !volume.contains('/'); + is_alphanumeric && does_not_contain_slash +} + diff --git a/src/forms/stack_custom.rs b/src/forms/stack_custom.rs new file mode 100644 index 00000000..b6277a2f --- /dev/null +++ b/src/forms/stack_custom.rs @@ -0,0 +1,81 @@ +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use serde_valid::Validate; +use crate::forms; +use indexmap::IndexMap; +use crate::helpers::stack::dctypes; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] +pub struct Custom { + pub web: Vec, + pub feature: Option>, + pub service: Option>, + #[validate(minimum = 0)] + #[validate(maximum = 10)] + pub servers_count: u32, + #[validate(min_length = 3)] + #[validate(max_length = 50)] + pub custom_stack_code: String, + #[validate(min_length = 3)] + #[validate(max_length = 255)] + pub project_git_url: Option, + pub custom_stack_category: Option>, + pub custom_stack_short_description: Option, + pub custom_stack_description: Option, + #[validate(min_length = 3)] + #[validate(max_length = 255)] + pub project_name: String, + pub project_overview: Option, + pub project_description: Option, + #[serde(flatten)] + pub networks: forms::ComposeNetworks, // all networks +} + +impl Custom { + pub fn services(&self) -> Result>, String> { + let mut services = IndexMap::new(); + + for app_type in &self.web { + let service = dctypes::Service::try_from(&app_type.app)?; + services.insert(app_type.app.code.clone().to_owned(), Some(service)); + } + + if let Some(srvs) = &self.service { + for app_type in srvs { + let service = dctypes::Service::try_from(&app_type.app)?; + services.insert(app_type.app.code.clone().to_owned(), Some(service)); + } + } + + if let Some(features) = &self.feature { + for app_type in features { + let service = dctypes::Service::try_from(&app_type.app)?; + services.insert(app_type.app.code.clone().to_owned(), Some(service)); + } + } + + Ok(services) + } + + pub fn named_volumes(&self) -> Result>, String> { + let mut named_volumes = IndexMap::new(); + + for app_type in &self.web { + named_volumes.extend(app_type.app.named_volumes()); + } + + if let Some(srvs) = &self.service { + for app_type in srvs { + named_volumes.extend(app_type.app.named_volumes()); + } + } + + if let Some(features) = &self.feature { + for app_type in features { + named_volumes.extend(app_type.app.named_volumes()); + } + } + + Ok(named_volumes) + } +} diff --git a/src/forms/stack_payload.rs b/src/forms/stack_payload.rs index 521642d5..e7a56cd0 100644 --- a/src/forms/stack_payload.rs +++ b/src/forms/stack_payload.rs @@ -35,7 +35,7 @@ pub struct StackPayload { pub stack_code: String, #[serde(rename = "selected_plan")] pub selected_plan: String, - pub custom: forms::stack::Custom, + pub custom: forms::Custom, } impl TryFrom<&models::Stack> for StackPayload { diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 55314ce2..4457cd2c 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -116,16 +116,6 @@ fn convert_shared_ports(ports: Option>) -> Result, St Ok(_ports) } -fn is_named_docker_volume(volume: &str) -> bool { - // Docker named volumes typically don't contain special characters or slashes - // They are alphanumeric and may include underscores or hyphens - let is_alphanumeric = volume - .chars() - .all(|c| c.is_alphanumeric() || c == '_' || c == '-'); - let does_not_contain_slash = !volume.contains('/'); - is_alphanumeric && does_not_contain_slash -} - impl TryFrom<&App> for Service { type Error = String; @@ -207,39 +197,6 @@ impl Into>> for stack::ComposeNetwo } } -pub fn extract_named_volumes(app: App) -> IndexMap> { - let mut named_volumes = IndexMap::default(); - - let volumes = app.volumes; - if volumes.is_none() { - return named_volumes; - } - - let volumes = volumes - .unwrap() - .into_iter() - .filter(|volume| is_named_docker_volume(volume.host_path.clone().unwrap().as_str())) - .map(|volume| { - let k = volume.host_path.clone().unwrap(); - ( - k.clone(), - MapOrEmpty::Map(ComposeVolume { - driver: None, - driver_opts: Default::default(), - external: None, - labels: Default::default(), - name: Some(k.clone()), - }), - ) - }) - .collect::>>(); - - named_volumes.extend(volumes); - // tracing::debug!("Named volumes: {:?}", named_volumes); - - named_volumes -} - impl DcBuilder { pub fn new(stack: models::Stack) -> Self { DcBuilder { @@ -256,30 +213,8 @@ impl DcBuilder { }; let apps = StackForm::try_from(&self.stack)?; - let mut services = IndexMap::new(); - let mut named_volumes = IndexMap::default(); - - for app_type in &apps.custom.web { - let service = Service::try_from(&app_type.app)?; - services.insert(app_type.app.code.clone().to_owned(), Some(service)); - named_volumes.extend(extract_named_volumes(app_type.app.clone())); - } - - if let Some(srvs) = apps.custom.service { - for app_type in srvs { - let service = Service::try_from(&app_type.app)?; - services.insert(app_type.app.code.clone().to_owned(), Some(service)); - named_volumes.extend(extract_named_volumes(app_type.app.clone())); - } - } - - if let Some(features) = apps.custom.feature { - for app_type in features { - let service = Service::try_from(&app_type.app)?; - services.insert(app_type.app.code.clone().to_owned(), Some(service)); - named_volumes.extend(extract_named_volumes(app_type.app.clone())); - } - } + let services = apps.custom.services()?; + let named_volumes = apps.custom.named_volumes()?; let networks = apps.custom.networks.clone(); compose_content.networks = ComposeNetworks(networks.into()); From b8334e4b6818dce890553ada7790746b10a9705d Mon Sep 17 00:00:00 2001 From: petru Date: Wed, 10 Jan 2024 17:53:32 +0200 Subject: [PATCH 24/25] issue-auth Volume::is_named_docker --- src/forms/stack.rs | 13 +++++++++++ src/forms/stack_app.rs | 52 +++++++++++++----------------------------- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/forms/stack.rs b/src/forms/stack.rs index d62fa319..5a1296c1 100644 --- a/src/forms/stack.rs +++ b/src/forms/stack.rs @@ -101,6 +101,19 @@ pub struct Volume { pub(crate) container_path: Option, } +impl Volume { + pub fn is_named_docker(&self) -> bool { + // Docker named volumes typically don't contain special characters or slashes + // They are alphanumeric and may include underscores or hyphens + self + .host_path + .as_ref() + .unwrap() + .chars() + .all(|c| c.is_alphanumeric() || c == '_' || c == '-') + } +} + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Volumes { volumes: Vec, diff --git a/src/forms/stack_app.rs b/src/forms/stack_app.rs index 8ebdec38..5608d768 100644 --- a/src/forms/stack_app.rs +++ b/src/forms/stack_app.rs @@ -72,36 +72,28 @@ pub struct App { } impl App { - pub fn named_volumes(&self) -> IndexMap> { //todo Result + pub fn named_volumes(&self) -> IndexMap> { let mut named_volumes = IndexMap::default(); - let volumes = &self.volumes; - if volumes.is_none() { + if self.volumes.is_none() { return named_volumes; } - let volumes = volumes - .clone() //todo remove it - .unwrap() - .into_iter() - .filter(|volume| is_named_docker_volume(volume.host_path.clone().unwrap().as_str())) - .map(|volume| { - let k = volume.host_path.clone().unwrap(); - ( - k.clone(), - dctypes::MapOrEmpty::Map(dctypes::ComposeVolume { - driver: None, - driver_opts: Default::default(), - external: None, - labels: Default::default(), - name: Some(k.clone()), - }), - ) - }) - .collect::>>(); + for volume in self.volumes.as_ref().unwrap() { + if !volume.is_named_docker() { + continue; + } - named_volumes.extend(volumes); - // tracing::debug!("Named volumes: {:?}", named_volumes); + let k = volume.host_path.as_ref().unwrap().clone(); + let v = dctypes::MapOrEmpty::Map(dctypes::ComposeVolume { + driver: None, + driver_opts: Default::default(), + external: None, + labels: Default::default(), + name: Some(k.clone()), + }); + named_volumes.insert(k, v); + } named_volumes } @@ -112,15 +104,3 @@ impl AsRef for App { &self.docker_image } } - - -fn is_named_docker_volume(volume: &str) -> bool { //todo - // Docker named volumes typically don't contain special characters or slashes - // They are alphanumeric and may include underscores or hyphens - let is_alphanumeric = volume - .chars() - .all(|c| c.is_alphanumeric() || c == '_' || c == '-'); - let does_not_contain_slash = !volume.contains('/'); - is_alphanumeric && does_not_contain_slash -} - From ea055ccfcd320c615972b57c46ae9a96003b0dc4 Mon Sep 17 00:00:00 2001 From: petru Date: Thu, 11 Jan 2024 18:02:00 +0200 Subject: [PATCH 25/25] issue-auth forms::stack --- src/forms/mod.rs | 9 ------- src/forms/{stack_app.rs => stack/app.rs} | 24 ++++++++--------- .../{stack_custom.rs => stack/custom.rs} | 8 +++--- src/forms/{stack_form.rs => stack/form.rs} | 12 ++++----- src/forms/{stack.rs => stack/mod.rs} | 16 ++++++++--- .../{stack_payload.rs => stack/payload.rs} | 8 +++--- src/helpers/stack/builder.rs | 27 +++++++++---------- src/helpers/stack/dctypes.rs | 8 +----- src/middleware/client.rs | 2 +- src/middleware/trydirect.rs | 4 +-- src/routes/client/update.rs | 1 - src/routes/rating/add.rs | 3 +-- src/routes/rating/get.rs | 2 +- src/routes/stack/add.rs | 12 ++++----- src/routes/stack/deploy.rs | 3 +-- src/routes/stack/update.rs | 8 +++--- src/services/rating.rs | 2 -- src/telemetry.rs | 2 +- 18 files changed, 70 insertions(+), 81 deletions(-) rename src/forms/{stack_app.rs => stack/app.rs} (83%) rename src/forms/{stack_custom.rs => stack/custom.rs} (92%) rename src/forms/{stack_form.rs => stack/form.rs} (84%) rename src/forms/{stack.rs => stack/mod.rs} (96%) rename src/forms/{stack_payload.rs => stack/payload.rs} (87%) diff --git a/src/forms/mod.rs b/src/forms/mod.rs index b7ef2dcf..9647ea6e 100644 --- a/src/forms/mod.rs +++ b/src/forms/mod.rs @@ -1,14 +1,5 @@ mod rating; pub mod stack; pub mod user; -mod stack_payload; -mod stack_form; -mod stack_custom; -mod stack_app; pub use rating::*; -pub use stack::*; -pub use stack_payload::*; -pub use stack_form::*; -pub use stack_custom::*; -pub use stack_app::*; diff --git a/src/forms/stack_app.rs b/src/forms/stack/app.rs similarity index 83% rename from src/forms/stack_app.rs rename to src/forms/stack/app.rs index 5608d768..71509262 100644 --- a/src/forms/stack_app.rs +++ b/src/forms/stack/app.rs @@ -28,13 +28,13 @@ pub struct App { #[serde(rename = "type")] pub type_field: String, #[serde(flatten)] - pub role: forms::Role, + pub role: forms::stack::Role, pub default: Option, - pub versions: Option>, + pub versions: Option>, #[serde(flatten)] - pub docker_image: forms::DockerImage, + pub docker_image: forms::stack::DockerImage, #[serde(flatten)] - pub requirements: forms::Requirements, + pub requirements: forms::stack::Requirements, #[validate(minimum = 1)] pub popularity: Option, pub commercial: Option, @@ -43,8 +43,8 @@ pub struct App { pub suggested: Option, pub dependency: Option, pub avoid_render: Option, - pub price: Option, - pub icon: Option, + pub price: Option, + pub icon: Option, pub domain: Option, pub category_id: Option, pub parent_app_id: Option, @@ -58,17 +58,17 @@ pub struct App { pub url_app: Option, pub url_git: Option, pub restart: Option, - pub volumes: Option>, + pub volumes: Option>, #[serde(flatten)] - pub environment: forms::Environment, + pub environment: forms::stack::Environment, #[serde(flatten)] - pub network: forms::ServiceNetworks, + pub network: forms::stack::ServiceNetworks, // #[serde(flatten)] // pub ports: Ports, #[serde(rename(deserialize = "sharedPorts"))] #[serde(rename(serialize = "shared_ports"))] #[serde(alias = "shared_ports")] - pub ports: Option>, + pub ports: Option>, } impl App { @@ -99,8 +99,8 @@ impl App { } } -impl AsRef for App { - fn as_ref(&self) -> &forms::DockerImage { +impl AsRef for App { + fn as_ref(&self) -> &forms::stack::DockerImage { &self.docker_image } } diff --git a/src/forms/stack_custom.rs b/src/forms/stack/custom.rs similarity index 92% rename from src/forms/stack_custom.rs rename to src/forms/stack/custom.rs index b6277a2f..34f5437b 100644 --- a/src/forms/stack_custom.rs +++ b/src/forms/stack/custom.rs @@ -7,9 +7,9 @@ use crate::helpers::stack::dctypes; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] pub struct Custom { - pub web: Vec, - pub feature: Option>, - pub service: Option>, + pub web: Vec, + pub feature: Option>, + pub service: Option>, #[validate(minimum = 0)] #[validate(maximum = 10)] pub servers_count: u32, @@ -28,7 +28,7 @@ pub struct Custom { pub project_overview: Option, pub project_description: Option, #[serde(flatten)] - pub networks: forms::ComposeNetworks, // all networks + pub networks: forms::stack::ComposeNetworks, // all networks } impl Custom { diff --git a/src/forms/stack_form.rs b/src/forms/stack/form.rs similarity index 84% rename from src/forms/stack_form.rs rename to src/forms/stack/form.rs index 989205af..4e11776f 100644 --- a/src/forms/stack_form.rs +++ b/src/forms/stack/form.rs @@ -7,12 +7,12 @@ use crate::models; use crate::forms; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] -pub struct StackForm { +pub struct Stack { // #[validate(min_length=2)] // #[validate(max_length=255)] #[serde(rename = "commonDomain")] pub common_domain: Option, - pub domain_list: Option, + pub domain_list: Option, #[validate(min_length = 2)] #[validate(max_length = 255)] pub stack_code: Option, @@ -31,7 +31,7 @@ pub struct StackForm { #[validate(min_length = 3)] #[validate(max_length = 50)] pub ssl: String, - pub vars: Option>, + pub vars: Option>, pub integrated_features: Option>, pub extended_features: Option>, pub subscriptions: Option>, @@ -49,13 +49,13 @@ pub struct StackForm { #[validate(min_length = 3)] #[validate(max_length = 50)] pub selected_plan: String, - pub custom: forms::Custom, + pub custom: forms::stack::Custom, } -impl TryFrom<&models::Stack> for StackForm { +impl TryFrom<&models::Stack> for Stack { type Error = String; fn try_from(stack: &models::Stack) -> Result { - serde_json::from_value::(stack.body.clone()).map_err(|err| format!("{:?}", err)) + serde_json::from_value::(stack.body.clone()).map_err(|err| format!("{:?}", err)) } } diff --git a/src/forms/stack.rs b/src/forms/stack/mod.rs similarity index 96% rename from src/forms/stack.rs rename to src/forms/stack/mod.rs index 5a1296c1..aadeddcc 100644 --- a/src/forms/stack.rs +++ b/src/forms/stack/mod.rs @@ -5,6 +5,16 @@ use std::collections::HashMap; use std::fmt; use crate::forms; +mod app; +mod custom; +mod form; +mod payload; + +pub use app::*; +pub use custom::*; +pub use form::*; +pub use payload::*; + #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] pub struct Role { pub role: Option>, @@ -133,7 +143,7 @@ pub struct ComposeNetworks { #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Web { #[serde(flatten)] - pub app: forms::App, + pub app: forms::stack::App, pub custom: Option, pub main: bool, } @@ -145,7 +155,7 @@ pub struct Feature { // #[serde(alias = "shared_ports")] // pub shared_ports: Option>, #[serde(flatten)] - pub app: forms::App, + pub app: forms::stack::App, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] @@ -155,7 +165,7 @@ pub struct Service { // #[serde(alias = "shared_ports")] // pub shared_ports: Option>, #[serde(flatten)] - pub(crate) app: forms::App, + pub(crate) app: forms::stack::App, } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/src/forms/stack_payload.rs b/src/forms/stack/payload.rs similarity index 87% rename from src/forms/stack_payload.rs rename to src/forms/stack/payload.rs index e7a56cd0..70be8410 100644 --- a/src/forms/stack_payload.rs +++ b/src/forms/stack/payload.rs @@ -7,7 +7,7 @@ use serde_valid::Validate; #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)] #[serde(rename_all = "snake_case")] -pub struct StackPayload { +pub struct Payload { pub(crate) id: Option, pub(crate) user_token: Option, pub(crate) user_email: Option, @@ -35,14 +35,14 @@ pub struct StackPayload { pub stack_code: String, #[serde(rename = "selected_plan")] pub selected_plan: String, - pub custom: forms::Custom, + pub custom: forms::stack::Custom, } -impl TryFrom<&models::Stack> for StackPayload { +impl TryFrom<&models::Stack> for Payload { type Error = String; fn try_from(stack: &models::Stack) -> Result { - let mut stack_data = serde_json::from_value::(stack.body.clone()).map_err(|err| { + let mut stack_data = serde_json::from_value::(stack.body.clone()).map_err(|err| { format!("{:?}", err) })?; diff --git a/src/helpers/stack/builder.rs b/src/helpers/stack/builder.rs index 4457cd2c..9068c9d0 100644 --- a/src/helpers/stack/builder.rs +++ b/src/helpers/stack/builder.rs @@ -1,4 +1,3 @@ -use crate::forms::{stack, App, StackForm, Volume, Web}; use crate::forms; use crate::helpers::stack::dctypes::{ AdvancedVolumes, Compose, ComposeNetwork, ComposeNetworkSettingDetails, ComposeNetworks, @@ -36,7 +35,7 @@ pub struct DcBuilder { pub(crate) stack: models::Stack, } -impl TryInto for Volume { +impl TryInto for forms::stack::Volume { type Error = String; fn try_into(self) -> Result { let source = self.host_path.clone(); @@ -58,20 +57,20 @@ impl TryInto for Volume { } } -impl TryInto for &stack::Port { +impl TryInto for &forms::stack::Port { type Error = String; fn try_into(self) -> Result { let cp = self .container_port .as_ref() .map_or(Ok(0u16), |s| s.parse::()) - .map_err(|err| "Could not parse port".to_string())?; + .map_err(|_| "Could not parse port".to_string())?; let hp = self .host_port .as_ref() .map_or(Ok(0u16), |s| s.parse::()) - .map_err(|err| "Could not parse port".to_string())?; + .map_err(|_| "Could not parse port".to_string())?; Ok(Port { target: cp, @@ -83,12 +82,12 @@ impl TryInto for &stack::Port { } } -impl TryFrom<&stack::ServiceNetworks> for Networks { +impl TryFrom<&forms::stack::ServiceNetworks> for Networks { type Error = (); - fn try_from(serviceNetworks: &stack::ServiceNetworks) -> Result { + fn try_from(service_networks: &forms::stack::ServiceNetworks) -> Result { let mut result = vec!["default_network".to_string()]; - serviceNetworks.network.as_ref().map(|networks| { + service_networks.network.as_ref().map(|networks| { for n in networks { result.push(n.to_string()); } @@ -98,13 +97,13 @@ impl TryFrom<&stack::ServiceNetworks> for Networks { } } -fn convert_shared_ports(ports: Option>) -> Result, String> { +//todo +fn convert_shared_ports(ports: Option>) -> Result, String> { tracing::debug!("convert shared ports {:?}", &ports); let mut _ports: Vec = vec![]; match ports { Some(ports) => { tracing::debug!("Ports >>>> {:?}", ports); - for port in ports {} } None => { tracing::debug!("No ports defined by user"); @@ -116,10 +115,10 @@ fn convert_shared_ports(ports: Option>) -> Result, St Ok(_ports) } -impl TryFrom<&App> for Service { +impl TryFrom<&forms::stack::App> for Service { type Error = String; - fn try_from(app: &App) -> Result { + fn try_from(app: &forms::stack::App) -> Result { let mut service = Service { image: Some(app.docker_image.to_string()), ..Default::default() @@ -166,7 +165,7 @@ impl TryFrom<&App> for Service { } } -impl Into>> for stack::ComposeNetworks { +impl Into>> for forms::stack::ComposeNetworks { fn into(self) -> IndexMap> { // tracing::debug!("networks found {:?}", self.networks); let mut networks = vec!["default_network".to_string()]; @@ -212,7 +211,7 @@ impl DcBuilder { ..Default::default() }; - let apps = StackForm::try_from(&self.stack)?; + let apps = forms::stack::Stack::try_from(&self.stack)?; let services = apps.custom.services()?; let named_volumes = apps.custom.named_volumes()?; diff --git a/src/helpers/stack/dctypes.rs b/src/helpers/stack/dctypes.rs index 931deab1..22383934 100644 --- a/src/helpers/stack/dctypes.rs +++ b/src/helpers/stack/dctypes.rs @@ -46,12 +46,6 @@ pub struct Compose { pub extensions: HashMap, } -impl Compose { - pub fn new() -> Self { - Default::default() - } -} - #[derive(Builder, Clone, Debug, Deserialize, Serialize, PartialEq, Default)] #[builder(setter(into), default)] pub struct Service { @@ -839,4 +833,4 @@ impl Serialize for MapOrEmpty } } } -} \ No newline at end of file +} diff --git a/src/middleware/client.rs b/src/middleware/client.rs index 60bce270..a6915d55 100644 --- a/src/middleware/client.rs +++ b/src/middleware/client.rs @@ -77,7 +77,7 @@ where let header_hash: String = get_header(&req, "stacker-hash")?; let db_pool = req.app_data::>>().unwrap().get_ref(); - let mut client: Client = db_fetch_client(db_pool, client_id).await?; + let client: Client = db_fetch_client(db_pool, client_id).await?; if client.secret.is_none() { return Err("client is not active".to_string()); } diff --git a/src/middleware/trydirect.rs b/src/middleware/trydirect.rs index e40f89b1..62b47046 100644 --- a/src/middleware/trydirect.rs +++ b/src/middleware/trydirect.rs @@ -32,7 +32,7 @@ async fn fetch_user(auth_url: &str, token: &str) -> Result .header(ACCEPT, "application/json") .send() .await - .map_err(|err| "no resp from auth server".to_string())?; + .map_err(|_err| "no resp from auth server".to_string())?; if !resp.status().is_success() { return Err("401 Unauthorized".to_string()); @@ -41,6 +41,6 @@ async fn fetch_user(auth_url: &str, token: &str) -> Result resp .json::() .await - .map_err(|err| "can't parse the response body".to_string())? + .map_err(|_err| "can't parse the response body".to_string())? .try_into() } diff --git a/src/routes/client/update.rs b/src/routes/client/update.rs index a52af9b0..5f19de51 100644 --- a/src/routes/client/update.rs +++ b/src/routes/client/update.rs @@ -3,7 +3,6 @@ use crate::helpers::client; use crate::models; use crate::{configuration::Settings, helpers::JsonResponse}; use actix_web::{put, web, Responder, Result}; -use futures::TryFutureExt; use sqlx::PgPool; use std::sync::Arc; use tracing::Instrument; diff --git a/src/routes/rating/add.rs b/src/routes/rating/add.rs index 48f03309..ea9657b2 100644 --- a/src/routes/rating/add.rs +++ b/src/routes/rating/add.rs @@ -6,7 +6,6 @@ use actix_web::{post, web, Responder, Result}; use sqlx::PgPool; use tracing::Instrument; use std::sync::Arc; -use futures::TryFutureExt; // workflow // add, update, list, get(user_id), ACL, @@ -39,5 +38,5 @@ pub async fn add_handler( db::rating::insert(pg_pool.get_ref(), rating) .await .map(|rating| JsonResponse::build().set_item(rating).ok("success")) - .map_err(|err| JsonResponse::::build().internal_server_error("Failed to insert")) + .map_err(|_err| JsonResponse::::build().internal_server_error("Failed to insert")) } diff --git a/src/routes/rating/get.rs b/src/routes/rating/get.rs index 9081960c..c7591891 100644 --- a/src/routes/rating/get.rs +++ b/src/routes/rating/get.rs @@ -34,5 +34,5 @@ pub async fn list_handler( db::rating::fetch_all(pg_pool.get_ref()) .await .map(|ratings| JsonResponse::build().set_list(ratings).ok("OK")) - .map_err(|err| JsonResponse::::build().internal_server_error("")) + .map_err(|_err| JsonResponse::::build().internal_server_error("")) } diff --git a/src/routes/stack/add.rs b/src/routes/stack/add.rs index bcf281c7..5a850c09 100644 --- a/src/routes/stack/add.rs +++ b/src/routes/stack/add.rs @@ -27,8 +27,8 @@ pub async fn add( check_if_stack_exists(pg_pool.get_ref(), &stack_name).await?; - let body: Value = serde_json::to_value::(form) - .or(serde_json::to_value::(forms::StackForm::default())) + let body: Value = serde_json::to_value::(form) + .or(serde_json::to_value::(forms::stack::Stack::default())) .unwrap(); let stack = models::Stack::new(user.id.clone(), stack_name, body); @@ -53,17 +53,17 @@ async fn check_if_stack_exists(pg_pool: &PgPool, stack_name: &String) -> Result< }) } -async fn body_into_form(body: Bytes) -> Result { +async fn body_into_form(body: Bytes) -> Result { let body_bytes = actix_web::body::to_bytes(body).await.unwrap(); let body_str = str::from_utf8(&body_bytes) - .map_err(|err| JsonResponse::::build().internal_server_error(err.to_string()))?; + .map_err(|err| JsonResponse::::build().internal_server_error(err.to_string()))?; let deserializer = &mut serde_json::Deserializer::from_str(body_str); serde_path_to_error::deserialize(deserializer) .map_err(|err| { let msg = format!("{}:{:?}", err.path().to_string(), err); - JsonResponse::::build().bad_request(msg) + JsonResponse::::build().bad_request(msg) }) - .and_then(|form: forms::StackForm| { + .and_then(|form: forms::stack::Stack| { if !form.validate().is_ok() { let errors = form.validate().unwrap_err(); let err_msg = format!("Invalid data received {:?}", &errors.to_string()); diff --git a/src/routes/stack/deploy.rs b/src/routes/stack/deploy.rs index 005ac531..71d459ff 100644 --- a/src/routes/stack/deploy.rs +++ b/src/routes/stack/deploy.rs @@ -5,7 +5,6 @@ use crate::helpers::stack::builder::DcBuilder; use crate::helpers::{JsonResponse, MqManager}; use crate::models; use actix_web::{post, web, web::Data, Responder, Result}; -use futures_lite::stream::StreamExt; use lapin::publisher_confirm::Confirmation; use sqlx::PgPool; use std::sync::Arc; @@ -34,7 +33,7 @@ pub async fn add( JsonResponse::::build().internal_server_error(err) })?; - let mut stack_data = forms::StackPayload::try_from(&dc.stack) + let mut stack_data = forms::stack::Payload::try_from(&dc.stack) .map_err(|err| JsonResponse::::build().bad_request(err))?; stack_data.user_token = Some(user.id.clone()); stack_data.user_email = Some(user.email.clone()); diff --git a/src/routes/stack/update.rs b/src/routes/stack/update.rs index a22be0c2..316a1ba2 100644 --- a/src/routes/stack/update.rs +++ b/src/routes/stack/update.rs @@ -16,7 +16,7 @@ use uuid::Uuid; #[post("/{id}")] pub async fn update( path: web::Path<(i32,)>, - form: web::Json, + form: web::Json, user: web::ReqData>, pg_pool: Data, ) -> Result { @@ -67,11 +67,11 @@ pub async fn update( return Err(JsonResponse::::build().bad_request(errors.to_string())); } - let body: Value = match serde_json::to_value::(form.into_inner()) { + let body: Value = match serde_json::to_value::(form.into_inner()) { Ok(body) => body, Err(err) => { tracing::error!("Request_id {} error unwrap body {:?}", request_id, err); - serde_json::to_value::(forms::StackForm::default()).unwrap() + serde_json::to_value::(forms::stack::Stack::default()).unwrap() } }; @@ -93,7 +93,7 @@ pub async fn update( .instrument(query_span) .await { - Ok(record) => { + Ok(_record) => { tracing::info!( "req_id: {} stack details have been saved to database", request_id diff --git a/src/services/rating.rs b/src/services/rating.rs index 22f42024..82222211 100644 --- a/src/services/rating.rs +++ b/src/services/rating.rs @@ -1,6 +1,4 @@ use crate::models::rating::Rating; -use sqlx::PgPool; -use reqwest::Url; use tracing::Instrument; use tracing_subscriber::fmt::format; diff --git a/src/telemetry.rs b/src/telemetry.rs index 724381a7..fb57df1e 100644 --- a/src/telemetry.rs +++ b/src/telemetry.rs @@ -1,4 +1,4 @@ -use tracing::subscriber::{self, set_global_default}; +use tracing::subscriber::set_global_default; use tracing::Subscriber; use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; use tracing_log::LogTracer;