From 98a4199a5f15e9580c65282544d07f91ec36875b Mon Sep 17 00:00:00 2001 From: Charley <charley.geoffroy@protonmail.com> Date: Sat, 20 Apr 2024 22:22:51 +0200 Subject: [PATCH 1/5] feat: add grpc client api and add proto folder Signed-off-by: Charley <charley.geoffroy@protonmail.com> --- .gitignore | 4 ++++ proto/vmm.proto | 30 ++++++++++++++++++++++++++++++ src/api/Cargo.toml | 5 +++++ src/api/build.rs | 4 ++++ src/api/src/client.rs | 32 ++++++++++++++++++++++++++++++++ src/api/src/lib.rs | 1 + src/api/src/main.rs | 17 +++++------------ src/api/src/services.rs | 32 +++++++++++--------------------- 8 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 proto/vmm.proto create mode 100644 src/api/build.rs create mode 100644 src/api/src/client.rs diff --git a/.gitignore b/.gitignore index f73ca97..49e45fc 100644 --- a/.gitignore +++ b/.gitignore @@ -224,3 +224,7 @@ $RECYCLE.BIN/ *.lnk # End of https://www.toptal.com/developers/gitignore/api/windows,macos,linux,vim,intellij+all,rust,rust-analyzer,visualstudiocode + +# RooFs and Kernel +kernel/* +rootfs/* \ No newline at end of file diff --git a/proto/vmm.proto b/proto/vmm.proto new file mode 100644 index 0000000..a6f48fe --- /dev/null +++ b/proto/vmm.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package vmmorchestrator; + +enum Language { + PYTHON = 0; + JAVASCRIPT = 1; + RUST = 2; +} + +enum LogLevel { + DEBUG = 0; + INFO = 1; + WARN = 2; + ERROR = 3; +} + +service VmmService { + rpc Run (RunVmmRequest) returns (RunVmmResponse); +} + +message RunVmmRequest { + Language language = 1; + LogLevel log_level = 4; + string code = 2; + string env = 3; +} + +message RunVmmResponse { +} diff --git a/src/api/Cargo.toml b/src/api/Cargo.toml index 088cf4d..017133e 100644 --- a/src/api/Cargo.toml +++ b/src/api/Cargo.toml @@ -8,3 +8,8 @@ edition = "2021" [dependencies] actix-web = "4.5.1" serde = "1.0.197" +tonic = "0.9" +prost = "0.11" + +[build-dependencies] +tonic-build = "0.9" \ No newline at end of file diff --git a/src/api/build.rs b/src/api/build.rs new file mode 100644 index 0000000..c53d705 --- /dev/null +++ b/src/api/build.rs @@ -0,0 +1,4 @@ +fn main() -> Result<(), Box<dyn std::error::Error>> { + tonic_build::compile_protos("../../proto/vmm.proto")?; + Ok(()) +} diff --git a/src/api/src/client.rs b/src/api/src/client.rs new file mode 100644 index 0000000..73030a6 --- /dev/null +++ b/src/api/src/client.rs @@ -0,0 +1,32 @@ +use tonic::transport::Channel; +use vmmorchestrator::vmm_service_client::VmmServiceClient; + +pub mod vmmorchestrator { + tonic::include_proto!("vmmorchestrator"); +} + +pub struct VmmClient { + client: VmmServiceClient<Channel>, +} + +impl VmmClient { + pub async fn new() -> Result<Self, tonic::transport::Error> { + let client = VmmServiceClient::connect("http://[::1]:50051") + .await + .expect("Failed to connect to VMM service"); + + Ok(VmmClient { client }) + } + + pub async fn run_vmm(&mut self) { + let request = tonic::Request::new(vmmorchestrator::RunVmmRequest { + language: vmmorchestrator::Language::Rust as i32, + env: "fn main() { println!(\"Hello, World!\"); }".to_string(), + code: "fn main() { println!(\"Hello, World!\"); }".to_string(), + log_level: vmmorchestrator::LogLevel::Info as i32, + }); + + let response = self.client.run(request).await.unwrap(); + println!("RESPONSE={:?}", response); + } +} diff --git a/src/api/src/lib.rs b/src/api/src/lib.rs index 4e379ae..24f4aba 100644 --- a/src/api/src/lib.rs +++ b/src/api/src/lib.rs @@ -1 +1,2 @@ +pub mod client; pub mod services; diff --git a/src/api/src/main.rs b/src/api/src/main.rs index 162db20..2de501b 100644 --- a/src/api/src/main.rs +++ b/src/api/src/main.rs @@ -1,20 +1,13 @@ use actix_web::{App, HttpServer}; -use api::services::{configuration, logs, metrics, run, shutdown}; +use api::services::{run, shutdown}; #[actix_web::main] async fn main() -> std::io::Result<()> { let port = 3000; println!("Starting server on port: {}", port); - HttpServer::new(|| { - App::new() - .service(configuration) - .service(run) - .service(logs) - .service(metrics) - .service(shutdown) - }) - .bind(("127.0.0.1", port))? - .run() - .await + HttpServer::new(|| App::new().service(run).service(shutdown)) + .bind(("127.0.0.1", port))? + .run() + .await } diff --git a/src/api/src/services.rs b/src/api/src/services.rs index 97d724c..897cd7a 100644 --- a/src/api/src/services.rs +++ b/src/api/src/services.rs @@ -1,28 +1,18 @@ -use actix_web::{get, post, web, HttpResponse, Responder}; - -#[post("/configuration")] -pub async fn configuration(req_body: String) -> impl Responder { - // TODO: Use the body to create the vm configuration - HttpResponse::Ok().body(req_body) -} +use crate::client::VmmClient; +use actix_web::{post, HttpResponse, Responder}; #[post("/run")] pub async fn run(req_body: String) -> impl Responder { - // TODO: Use the body id to start the fm - HttpResponse::Ok().body(req_body) -} - -#[get("/logs/{id}")] -pub async fn logs(id: web::Path<String>) -> HttpResponse { - // TODO: maybe not close the stream and keep sending the logs - HttpResponse::Ok().body(format!("Logs here: {}", &id)) -} - -#[get("/metrics/{id}")] -pub async fn metrics(id: web::Path<String>) -> HttpResponse { - // TODO: Get the metrics for a VM with the given ID + let grpc_client = VmmClient::new().await; - HttpResponse::Ok().body(format!("Metrics here: {}", &id)) + match grpc_client { + Ok(mut client) => { + client.run_vmm().await; + HttpResponse::Ok().body(req_body) + } + Err(e) => HttpResponse::InternalServerError() + .body("Failed to connect to VMM service with error: ".to_string() + &e.to_string()), + } } #[post("/shutdown")] From b9c7f1f88ff027d3056bb202980f71cfbda22c7a Mon Sep 17 00:00:00 2001 From: Charley <charley.geoffroy@protonmail.com> Date: Sat, 20 Apr 2024 22:56:20 +0200 Subject: [PATCH 2/5] chore: rename services.rs and minor refactor Signed-off-by: Charley <charley.geoffroy@protonmail.com> --- proto/vmm.proto | 5 +---- src/cli/src/main.rs | 20 +++++--------------- src/cli/src/{request.rs => services.rs} | 23 ++++++++++++----------- 3 files changed, 18 insertions(+), 30 deletions(-) rename src/cli/src/{request.rs => services.rs} (59%) diff --git a/proto/vmm.proto b/proto/vmm.proto index a6f48fe..f5ba1cf 100644 --- a/proto/vmm.proto +++ b/proto/vmm.proto @@ -7,24 +7,21 @@ enum Language { JAVASCRIPT = 1; RUST = 2; } - enum LogLevel { DEBUG = 0; INFO = 1; WARN = 2; ERROR = 3; } - service VmmService { rpc Run (RunVmmRequest) returns (RunVmmResponse); + } - message RunVmmRequest { Language language = 1; LogLevel log_level = 4; string code = 2; string env = 3; } - message RunVmmResponse { } diff --git a/src/cli/src/main.rs b/src/cli/src/main.rs index 1faebb8..6c28af9 100644 --- a/src/cli/src/main.rs +++ b/src/cli/src/main.rs @@ -1,14 +1,14 @@ use clap::Parser; use args::{CliArgs, Commands}; -use request::run_request; -use request::HttpRunRequest; +use services::run_request; +use services::HttpRunRequest; use std::io::{self}; use types::Config; -use utils::{load_config, read_file}; +use utils::load_config; mod args; -mod request; +mod services; mod types; mod utils; @@ -20,17 +20,7 @@ async fn main() -> io::Result<()> { Commands::Run { config_path } => { let yaml_config: Config = load_config(&config_path).expect("Error while loading the configuration file"); - - let code = - read_file(&yaml_config.code_path).expect("Error while reading the code file"); - println!("Code from file: \n{}", code); - - let env = - read_file(&yaml_config.env_path).expect("Error while reading the environment file"); - println!("Env from file : \n{}", env); - println!("Configuration from YAML file: \n {:#?}", yaml_config); - - let body = HttpRunRequest::new(yaml_config.language, env, code, yaml_config.log_level); + let body = HttpRunRequest::new(yaml_config); let response = run_request(body).await; match response { diff --git a/src/cli/src/request.rs b/src/cli/src/services.rs similarity index 59% rename from src/cli/src/request.rs rename to src/cli/src/services.rs index cb7872e..3c01dbd 100644 --- a/src/cli/src/request.rs +++ b/src/cli/src/services.rs @@ -1,27 +1,28 @@ -use crate::types::{Language, LogLevel}; +use crate::types::{Config, Language, LogLevel}; +use crate::utils::read_file; use reqwest::Client; use serde::Serialize; use std::error::Error; + #[derive(Serialize, Debug)] pub struct HttpRunRequest { pub language: Language, - pub env_content: String, - pub code_content: String, + pub env: String, + pub code: String, pub log_level: LogLevel, } impl HttpRunRequest { - pub fn new( - language: Language, - env_content: String, - code_content: String, - log_level: LogLevel, - ) -> Self { + pub fn new(config: Config) -> Self { + let code: String = read_file(&config.code_path).expect("Error while reading the code file"); + let env = read_file(&config.env_path).expect("Error while reading the environment file"); + let language = config.language; + let log_level = config.log_level; HttpRunRequest { language, - env_content, - code_content, + env, + code, log_level, } } From 1b36132f9842bff898171facd49a899911bcb324 Mon Sep 17 00:00:00 2001 From: Charley <charley.geoffroy@protonmail.com> Date: Sat, 20 Apr 2024 22:59:17 +0200 Subject: [PATCH 3/5] chore: rename some enums call Signed-off-by: Charley <charley.geoffroy@protonmail.com> --- src/api/src/client.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/src/client.rs b/src/api/src/client.rs index 73030a6..5c232b2 100644 --- a/src/api/src/client.rs +++ b/src/api/src/client.rs @@ -1,5 +1,6 @@ use tonic::transport::Channel; use vmmorchestrator::vmm_service_client::VmmServiceClient; +use vmmorchestrator::{Language, LogLevel}; pub mod vmmorchestrator { tonic::include_proto!("vmmorchestrator"); @@ -20,10 +21,10 @@ impl VmmClient { pub async fn run_vmm(&mut self) { let request = tonic::Request::new(vmmorchestrator::RunVmmRequest { - language: vmmorchestrator::Language::Rust as i32, + language: Language::Rust as i32, env: "fn main() { println!(\"Hello, World!\"); }".to_string(), code: "fn main() { println!(\"Hello, World!\"); }".to_string(), - log_level: vmmorchestrator::LogLevel::Info as i32, + log_level: LogLevel::Info as i32, }); let response = self.client.run(request).await.unwrap(); From 7364de2186cfe2f7cdc43d62df60bc6dff85b5f7 Mon Sep 17 00:00:00 2001 From: Charley <charley.geoffroy@protonmail.com> Date: Sun, 21 Apr 2024 01:17:05 +0200 Subject: [PATCH 4/5] refactor(cli): update code quality Signed-off-by: Charley <charley.geoffroy@protonmail.com> --- Cargo.toml | 2 +- proto/vmm.proto | 11 ++++++++--- src/cli/src/main.rs | 12 ++++++------ src/cli/src/services.rs | 36 +++++++++++++++++------------------- src/cli/src/types.rs | 8 +++++--- src/cli/src/utils.rs | 8 ++++---- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 715dc56..94d73a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = [ "src/api","src/vmm", "src/cli"] +members = ["src/api", "src/vmm", "src/cli"] resolver = "2" diff --git a/proto/vmm.proto b/proto/vmm.proto index f5ba1cf..1debb55 100644 --- a/proto/vmm.proto +++ b/proto/vmm.proto @@ -4,24 +4,29 @@ package vmmorchestrator; enum Language { PYTHON = 0; - JAVASCRIPT = 1; + NODE = 1; RUST = 2; } + enum LogLevel { DEBUG = 0; INFO = 1; WARN = 2; ERROR = 3; } + service VmmService { rpc Run (RunVmmRequest) returns (RunVmmResponse); - } + message RunVmmRequest { + Language language = 1; - LogLevel log_level = 4; string code = 2; string env = 3; + LogLevel log_level = 4; + } + message RunVmmResponse { } diff --git a/src/cli/src/main.rs b/src/cli/src/main.rs index 6c28af9..a9b14ac 100644 --- a/src/cli/src/main.rs +++ b/src/cli/src/main.rs @@ -1,10 +1,10 @@ use clap::Parser; +use crate::types::YamlConfigFile; use args::{CliArgs, Commands}; -use services::run_request; -use services::HttpRunRequest; + +use services::HttpVmmRequest; use std::io::{self}; -use types::Config; use utils::load_config; mod args; @@ -18,10 +18,10 @@ async fn main() -> io::Result<()> { match args.command { Commands::Run { config_path } => { - let yaml_config: Config = + let yaml_config: YamlConfigFile = load_config(&config_path).expect("Error while loading the configuration file"); - let body = HttpRunRequest::new(yaml_config); - let response = run_request(body).await; + let body = HttpVmmRequest::new(yaml_config); + let response = HttpVmmRequest::post(body).await; match response { Ok(_) => println!("Request successful"), diff --git a/src/cli/src/services.rs b/src/cli/src/services.rs index 3c01dbd..ced3e73 100644 --- a/src/cli/src/services.rs +++ b/src/cli/src/services.rs @@ -1,42 +1,40 @@ -use crate::types::{Config, Language, LogLevel}; +use crate::types::{Language, LogLevel, YamlConfigFile}; use crate::utils::read_file; use reqwest::Client; use serde::Serialize; use std::error::Error; - - #[derive(Serialize, Debug)] -pub struct HttpRunRequest { +pub struct HttpVmmRequest { pub language: Language, pub env: String, pub code: String, pub log_level: LogLevel, } -impl HttpRunRequest { - pub fn new(config: Config) -> Self { +impl HttpVmmRequest { + pub fn new(config: YamlConfigFile) -> Self { let code: String = read_file(&config.code_path).expect("Error while reading the code file"); let env = read_file(&config.env_path).expect("Error while reading the environment file"); let language = config.language; let log_level = config.log_level; - HttpRunRequest { + HttpVmmRequest { language, env, code, log_level, } } -} -pub async fn run_request(request: HttpRunRequest) -> Result<(), Box<dyn Error>> { - let client = Client::new(); - let res = client - .post("http://127.0.0.1:3000/run") - .body(serde_json::to_string(&request)?) - .send() - .await?; - println!("Response Status: {}", res.status()); - let body = res.text().await?; - println!("Response body: {}", body); - Ok(()) + pub async fn post(request: HttpVmmRequest) -> Result<(), Box<dyn Error>> { + let client = Client::new(); + let res = client + .post("http://127.0.0.1:3000/run") + .body(serde_json::to_string(&request)?) + .send() + .await?; + println!("Response Status: {}", res.status()); + let body = res.text().await?; + println!("Response body: {}", body); + Ok(()) + } } diff --git a/src/cli/src/types.rs b/src/cli/src/types.rs index 7e6fac6..e143a3f 100644 --- a/src/cli/src/types.rs +++ b/src/cli/src/types.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use clap::ValueEnum; use serde::{Deserialize, Serialize}; @@ -19,9 +21,9 @@ pub enum LogLevel { } #[derive(Deserialize, Debug)] -pub struct Config { +pub struct YamlConfigFile { pub language: Language, - pub env_path: String, - pub code_path: String, + pub env_path: PathBuf, + pub code_path: PathBuf, pub log_level: LogLevel, } diff --git a/src/cli/src/utils.rs b/src/cli/src/utils.rs index e9a1992..865583d 100644 --- a/src/cli/src/utils.rs +++ b/src/cli/src/utils.rs @@ -1,18 +1,18 @@ -use crate::types::Config; +use crate::types::YamlConfigFile; use std::fs::File; use std::io::{self, Read}; use std::path::PathBuf; -pub fn load_config(config_path: &PathBuf) -> io::Result<Config> { +pub fn load_config(config_path: &PathBuf) -> io::Result<YamlConfigFile> { let mut file = File::open(config_path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; - let config: Config = serde_yaml::from_str(&contents) + let config: YamlConfigFile = serde_yaml::from_str(&contents) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; Ok(config) } -pub fn read_file(file_path: &str) -> io::Result<String> { +pub fn read_file(file_path: &PathBuf) -> io::Result<String> { let mut file = File::open(file_path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; From 8b9f8ac9d1438346fe4b8af49e5fe94b0db8ca8d Mon Sep 17 00:00:00 2001 From: Charley <charley.geoffroy@protonmail.com> Date: Sun, 21 Apr 2024 16:09:03 +0200 Subject: [PATCH 5/5] feat: add shared models as DTO and enum between API and CLI Signed-off-by: Charley <charley.geoffroy@protonmail.com> --- src/api/Cargo.toml | 1 + src/api/src/client.rs | 11 +---- src/api/src/services.rs | 19 +++++++-- src/cli/Cargo.toml | 1 + src/cli/config/config.template.yaml | 4 +- src/cli/src/main.rs | 15 ++++--- src/cli/src/services.rs | 41 +++++++++---------- src/cli/src/utils.rs | 32 ++++++++------- src/shared-models/Cargo.toml | 16 ++++++++ .../src/types.rs => shared-models/src/lib.rs} | 24 +++++++---- 10 files changed, 98 insertions(+), 66 deletions(-) create mode 100644 src/shared-models/Cargo.toml rename src/{cli/src/types.rs => shared-models/src/lib.rs} (61%) diff --git a/src/api/Cargo.toml b/src/api/Cargo.toml index 017133e..5a6f3d0 100644 --- a/src/api/Cargo.toml +++ b/src/api/Cargo.toml @@ -10,6 +10,7 @@ actix-web = "4.5.1" serde = "1.0.197" tonic = "0.9" prost = "0.11" +shared_models = { path="../shared-models" } [build-dependencies] tonic-build = "0.9" \ No newline at end of file diff --git a/src/api/src/client.rs b/src/api/src/client.rs index 5c232b2..1abc188 100644 --- a/src/api/src/client.rs +++ b/src/api/src/client.rs @@ -1,6 +1,5 @@ use tonic::transport::Channel; use vmmorchestrator::vmm_service_client::VmmServiceClient; -use vmmorchestrator::{Language, LogLevel}; pub mod vmmorchestrator { tonic::include_proto!("vmmorchestrator"); @@ -19,14 +18,8 @@ impl VmmClient { Ok(VmmClient { client }) } - pub async fn run_vmm(&mut self) { - let request = tonic::Request::new(vmmorchestrator::RunVmmRequest { - language: Language::Rust as i32, - env: "fn main() { println!(\"Hello, World!\"); }".to_string(), - code: "fn main() { println!(\"Hello, World!\"); }".to_string(), - log_level: LogLevel::Info as i32, - }); - + pub async fn run_vmm(&mut self, request: vmmorchestrator::RunVmmRequest) { + let request = tonic::Request::new(request); let response = self.client.run(request).await.unwrap(); println!("RESPONSE={:?}", response); } diff --git a/src/api/src/services.rs b/src/api/src/services.rs index 897cd7a..1648667 100644 --- a/src/api/src/services.rs +++ b/src/api/src/services.rs @@ -1,14 +1,25 @@ +use crate::client::vmmorchestrator::RunVmmRequest; use crate::client::VmmClient; -use actix_web::{post, HttpResponse, Responder}; +use actix_web::{post, web, HttpResponse, Responder}; +use shared_models::CloudletDtoRequest; #[post("/run")] -pub async fn run(req_body: String) -> impl Responder { +pub async fn run(req_body: web::Json<CloudletDtoRequest>) -> impl Responder { + let req = req_body.into_inner(); let grpc_client = VmmClient::new().await; + let vmm_request = RunVmmRequest { + code: req.code, + env: req.env, + language: req.language as i32, + log_level: req.log_level as i32, + }; + match grpc_client { Ok(mut client) => { - client.run_vmm().await; - HttpResponse::Ok().body(req_body) + println!("Successfully connected to VMM service"); + client.run_vmm(vmm_request).await; + HttpResponse::Ok().body("Successfully ran VMM") } Err(e) => HttpResponse::InternalServerError() .body("Failed to connect to VMM service with error: ".to_string() + &e.to_string()), diff --git a/src/cli/Cargo.toml b/src/cli/Cargo.toml index 89d519d..ef09404 100644 --- a/src/cli/Cargo.toml +++ b/src/cli/Cargo.toml @@ -14,3 +14,4 @@ serde_yaml = "0.9.34" schemars = "0.8.16" serde_json = "1.0.115" reqwest = "0.12.3" +shared_models = { path="../shared-models" } \ No newline at end of file diff --git a/src/cli/config/config.template.yaml b/src/cli/config/config.template.yaml index 73dfaad..59baa6b 100644 --- a/src/cli/config/config.template.yaml +++ b/src/cli/config/config.template.yaml @@ -1,4 +1,4 @@ language: rust -env_path: /path/cloudlet/src/cli/config/example.env -code_path: /path/cloudlet/src/cli/src/main.rs +env_path: /home/charley/polytech/cloudlet/src/cli/config/example.env +code_path: /home/charley/polytech/cloudlet/src/cli/src/main.rs log_level: debug diff --git a/src/cli/src/main.rs b/src/cli/src/main.rs index a9b14ac..2fa2760 100644 --- a/src/cli/src/main.rs +++ b/src/cli/src/main.rs @@ -1,15 +1,14 @@ use clap::Parser; -use crate::types::YamlConfigFile; use args::{CliArgs, Commands}; +use shared_models::YamlClientConfigFile; -use services::HttpVmmRequest; +use services::CloudletClient; use std::io::{self}; -use utils::load_config; +use utils::ConfigFileHandler; mod args; mod services; -mod types; mod utils; #[tokio::main] @@ -18,10 +17,10 @@ async fn main() -> io::Result<()> { match args.command { Commands::Run { config_path } => { - let yaml_config: YamlConfigFile = - load_config(&config_path).expect("Error while loading the configuration file"); - let body = HttpVmmRequest::new(yaml_config); - let response = HttpVmmRequest::post(body).await; + let yaml_config: YamlClientConfigFile = ConfigFileHandler::load_config(&config_path) + .expect("Error while loading the configuration file"); + let body = CloudletClient::new_cloudlet_config(yaml_config); + let response = CloudletClient::run(body).await; match response { Ok(_) => println!("Request successful"), diff --git a/src/cli/src/services.rs b/src/cli/src/services.rs index ced3e73..84835d2 100644 --- a/src/cli/src/services.rs +++ b/src/cli/src/services.rs @@ -1,23 +1,18 @@ -use crate::types::{Language, LogLevel, YamlConfigFile}; -use crate::utils::read_file; +use crate::utils::ConfigFileHandler; use reqwest::Client; -use serde::Serialize; +use shared_models::{CloudletDtoRequest, YamlClientConfigFile}; use std::error::Error; -#[derive(Serialize, Debug)] -pub struct HttpVmmRequest { - pub language: Language, - pub env: String, - pub code: String, - pub log_level: LogLevel, -} +pub struct CloudletClient {} -impl HttpVmmRequest { - pub fn new(config: YamlConfigFile) -> Self { - let code: String = read_file(&config.code_path).expect("Error while reading the code file"); - let env = read_file(&config.env_path).expect("Error while reading the environment file"); +impl CloudletClient { + pub fn new_cloudlet_config(config: YamlClientConfigFile) -> CloudletDtoRequest { + let code: String = ConfigFileHandler::read_file(&config.code_path) + .expect("Error while reading the code file"); + let env = ConfigFileHandler::read_file(&config.env_path) + .expect("Error while reading the environment file"); let language = config.language; let log_level = config.log_level; - HttpVmmRequest { + CloudletDtoRequest { language, env, code, @@ -25,16 +20,20 @@ impl HttpVmmRequest { } } - pub async fn post(request: HttpVmmRequest) -> Result<(), Box<dyn Error>> { + pub async fn run(request: CloudletDtoRequest) -> Result<(), Box<dyn Error>> { let client = Client::new(); + let json = serde_json::to_string(&request)?; + println!("REQUEST : {:?}", request); let res = client .post("http://127.0.0.1:3000/run") - .body(serde_json::to_string(&request)?) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .body(json) .send() .await?; - println!("Response Status: {}", res.status()); - let body = res.text().await?; - println!("Response body: {}", body); - Ok(()) + + match res.status().as_u16() { + 200 => Ok(()), + _ => Err("Error while making the request".into()), + } } } diff --git a/src/cli/src/utils.rs b/src/cli/src/utils.rs index 865583d..0d80519 100644 --- a/src/cli/src/utils.rs +++ b/src/cli/src/utils.rs @@ -1,20 +1,24 @@ -use crate::types::YamlConfigFile; +use shared_models::YamlClientConfigFile; use std::fs::File; use std::io::{self, Read}; use std::path::PathBuf; -pub fn load_config(config_path: &PathBuf) -> io::Result<YamlConfigFile> { - let mut file = File::open(config_path)?; - let mut contents = String::new(); - file.read_to_string(&mut contents)?; - let config: YamlConfigFile = serde_yaml::from_str(&contents) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; - Ok(config) -} +pub struct ConfigFileHandler {} + +impl ConfigFileHandler { + pub fn load_config(config_path: &PathBuf) -> io::Result<YamlClientConfigFile> { + let mut file = File::open(config_path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + let config: YamlClientConfigFile = serde_yaml::from_str(&contents) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Ok(config) + } -pub fn read_file(file_path: &PathBuf) -> io::Result<String> { - let mut file = File::open(file_path)?; - let mut contents = String::new(); - file.read_to_string(&mut contents)?; - Ok(contents) + pub fn read_file(file_path: &PathBuf) -> io::Result<String> { + let mut file = File::open(file_path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + Ok(contents) + } } diff --git a/src/shared-models/Cargo.toml b/src/shared-models/Cargo.toml new file mode 100644 index 0000000..2422219 --- /dev/null +++ b/src/shared-models/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "shared_models" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.5.3", features = ["derive"] } +serde = { version = "1.0.197", features = ["derive"] } +serde_yaml = "0.9.34" +serde_json = "1.0.115" + +[lib] +name = "shared_models" +path = "src/lib.rs" \ No newline at end of file diff --git a/src/cli/src/types.rs b/src/shared-models/src/lib.rs similarity index 61% rename from src/cli/src/types.rs rename to src/shared-models/src/lib.rs index e143a3f..cfa7582 100644 --- a/src/cli/src/types.rs +++ b/src/shared-models/src/lib.rs @@ -6,24 +6,32 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, ValueEnum, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum Language { - Rust, - Python, - Node, + RUST, + PYTHON, + NODE, } #[derive(Clone, Debug, ValueEnum, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum LogLevel { - Debug, - Info, - Warn, - Error, + DEBUG, + INFO, + WARN, + ERROR, } #[derive(Deserialize, Debug)] -pub struct YamlConfigFile { +pub struct YamlClientConfigFile { pub language: Language, pub env_path: PathBuf, pub code_path: PathBuf, pub log_level: LogLevel, } + +#[derive(Serialize, Deserialize, Debug)] +pub struct CloudletDtoRequest { + pub language: Language, + pub env: String, + pub code: String, + pub log_level: LogLevel, +}