From 69a741c7d9da8d3fb45c4b741fc35effaa4b0676 Mon Sep 17 00:00:00 2001 From: Alexis-Bernard Date: Fri, 24 Feb 2023 16:21:40 +0100 Subject: [PATCH] feat: add config Signed-off-by: WoodenMaiden --- .gitignore | 3 ++ agent/Cargo.toml | 5 +- agent/lib/Cargo.toml | 14 ------ agent/lib/src/config.rs | 66 +++++++++++++++++++++++++++ agent/lib/src/external_api/service.rs | 26 +++++------ agent/lib/src/lib.rs | 1 + agent/src/main.rs | 43 ++++++++++++++--- 7 files changed, 123 insertions(+), 35 deletions(-) delete mode 100644 agent/lib/Cargo.toml create mode 100644 agent/lib/src/config.rs diff --git a/.gitignore b/.gitignore index 95fe04a..7f400bf 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ agent/Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +# config file +config.yaml \ No newline at end of file diff --git a/agent/Cargo.toml b/agent/Cargo.toml index 360cf7b..2cab3ec 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -12,8 +12,11 @@ anyhow = "1.0.69" serialport = "4.2.0" serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.93" +serde_yaml = "0.9" +clap = { version="4.1.6", features=["derive"] } unshare = "0.7.0" +thiserror = "1.0.32" [lib] name = "agent_lib" -path = "lib/src/lib.rs" \ No newline at end of file +path = "lib/src/lib.rs" diff --git a/agent/lib/Cargo.toml b/agent/lib/Cargo.toml deleted file mode 100644 index 7c1914a..0000000 --- a/agent/lib/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "agent_lib" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -serialport = "4.2.0" -serde = { version = "1.0.152", features = ["derive"] } -serde_json = "1.0.93" -log = "0.4.0" -anyhow = "1.0.69" -env_logger = "0.10.0" \ No newline at end of file diff --git a/agent/lib/src/config.rs b/agent/lib/src/config.rs new file mode 100644 index 0000000..0f85c27 --- /dev/null +++ b/agent/lib/src/config.rs @@ -0,0 +1,66 @@ +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use std::{ + fs::File, + io::{self, BufReader}, +}; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum AgentConfigError { + #[error("cannot load config file")] + Load(#[from] io::Error), + #[error("cannot parse config file")] + Parse(#[from] serde_yaml::Error), + #[error("unsupported config kind")] + KindNotSupported, + #[error("unsupported config api version")] + VersionNotSupported, +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +#[allow(non_snake_case)] +pub struct AgentConfig { + /// The api version of the agent config file + pub apiVersion: String, + /// The kind of the agent config file + pub kind: String, + /// The serial configuration + pub serial: SerialConfig, +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct SerialConfig { + /// The path to the serial port + pub path: String, + /// The baud rate to use for the serial port + pub baud_rate: u32, +} + +impl AgentConfig { + /// Load a AgentConfig from a file. + /// + /// Arguments: + /// + /// * `path`: The path to the config file. + /// + /// Returns: + /// + /// A Result + pub fn load(path: &str) -> Result { + let file = File::open(path).map_err(AgentConfigError::Load)?; + let reader = BufReader::new(file); + let config: AgentConfig = + serde_yaml::from_reader(reader).map_err(AgentConfigError::Parse)?; + + if config.kind != "AgentConfig" { + return Err(AgentConfigError::KindNotSupported.into()); + } + + if config.apiVersion != "lambdo.io/v1alpha1" { + return Err(AgentConfigError::VersionNotSupported.into()); + } + + Ok(config) + } +} diff --git a/agent/lib/src/external_api/service.rs b/agent/lib/src/external_api/service.rs index 83478fb..36c11e9 100644 --- a/agent/lib/src/external_api/service.rs +++ b/agent/lib/src/external_api/service.rs @@ -4,25 +4,23 @@ use log::{error, info}; use super::model::CodeEntry; pub struct ExternalApi { - serial_read_path: String, - serial_write_path: String, + serial_path: String, serial_baud_rate: u32, } impl ExternalApi { - pub fn new(serial_read_path: String, serial_write_path: String, serial_baud_rate: u32) -> Self { + pub fn new(serial_path: String, serial_baud_rate: u32) -> Self { Self { - serial_read_path, - serial_write_path, + serial_path, serial_baud_rate, } } pub fn read_from_serial(&mut self) -> Result { - info!("Reading from serial port: {}", self.serial_read_path); + info!("Reading from serial port: {}", self.serial_path); // Open the serial port - let mut serial = serialport::new(&self.serial_read_path, self.serial_baud_rate) + let mut serial = serialport::new(&self.serial_path, self.serial_baud_rate) .open() .map_err(|e| anyhow!("Failed to open serial port: {}", e))?; @@ -95,7 +93,7 @@ impl ExternalApi { pub fn write_to_serial(&mut self, data: &str) -> Result<()> { // Open the serial port - let mut serial = serialport::new(&self.serial_write_path, self.serial_baud_rate) + let mut serial = serialport::new(&self.serial_path, self.serial_baud_rate) .open() .map_err(|e| anyhow!("Failed to open serial port: {}", e))?; @@ -124,7 +122,7 @@ mod tests { #[test] fn test_parse_json_payload() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), "".to_string(), 0); + let mut internal_api = ExternalApi::new("".to_string(), 0); // Data vector with the following JSON payload: // { @@ -159,7 +157,7 @@ mod tests { #[test] fn test_parse_json_payload_failed() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), "".to_string(), 0); + let mut internal_api = ExternalApi::new("".to_string(), 0); // Data vector with missing comma let data = [ @@ -182,7 +180,7 @@ mod tests { #[test] fn test_data_cut_before_delimiter() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), "".to_string(), 0); + let mut internal_api = ExternalApi::new("".to_string(), 0); let data = [97, 98, 99, 28, 1, 2, 3, 4, 5, 6, 7]; let mut data_received: Vec = Vec::new(); @@ -198,7 +196,7 @@ mod tests { #[test] fn test_data_transferred_without_delimiter() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), "".to_string(), 0); + let mut internal_api = ExternalApi::new("".to_string(), 0); let data = [97, 98, 99, 1, 2, 3, 4, 5, 6, 7]; let mut data_received: Vec = Vec::new(); @@ -214,7 +212,7 @@ mod tests { #[test] fn test_data_transferred_multiple_time() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), "".to_string(), 0); + let mut internal_api = ExternalApi::new("".to_string(), 0); let data = [97, 98, 99]; let data2 = [1, 2, 3, 4, 5, 6, 7]; @@ -234,7 +232,7 @@ mod tests { #[test] fn test_data_transferred_with_delimiter() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), "".to_string(), 0); + let mut internal_api = ExternalApi::new("".to_string(), 0); let data = [97, 98, 99]; let data2 = [1, 2, 3, 4, 5, 6, 7]; diff --git a/agent/lib/src/lib.rs b/agent/lib/src/lib.rs index 91866ed..428bc93 100644 --- a/agent/lib/src/lib.rs +++ b/agent/lib/src/lib.rs @@ -1,2 +1,3 @@ +pub mod config; pub mod external_api; pub mod internal_api; diff --git a/agent/src/main.rs b/agent/src/main.rs index e1196fc..0963188 100644 --- a/agent/src/main.rs +++ b/agent/src/main.rs @@ -1,14 +1,37 @@ -use agent_lib::{external_api::service::ExternalApi, internal_api::service::InternalApi}; -use anyhow::{ Result, anyhow }; +use agent_lib::{ + config::AgentConfig, external_api::service::ExternalApi, internal_api::service::InternalApi, +}; +use anyhow::{anyhow, Result}; +use clap::Parser; +use log::{debug, error, info, trace}; -use log::{info, error}; +#[derive(Parser)] +#[clap( + version = "0.1", + author = "Polytech Montpellier - DevOps", + about = "A Serverless runtime in Rust" +)] +pub struct AgentOpts { + /// Config file path + #[clap(short, long, default_value = "/etc/lambdo/agent/config.yaml")] + config: String, +} fn main() -> Result<()> { env_logger::init(); info!("Starting agent"); - let mut external_api = - ExternalApi::new("/dev/pts/4".to_string(), "/dev/pts/6".to_string(), 9600); + let options = AgentOpts::parse(); + + debug!("loading config file at {}", options.config); + let config = AgentConfig::load(options.config.as_str())?; + + trace!( + "config file loaded successfully with content: {:#?}", + config + ); + + let mut external_api = ExternalApi::new(config.serial.path, config.serial.baud_rate); let code_entry = external_api.read_from_serial()?; let mut internal_api = InternalApi::new(code_entry); @@ -17,7 +40,15 @@ fn main() -> Result<()> { match res { Err(e) => error!("Error: {:?}", e), - Ok(code) => info!("Code: {:?}", code), + Ok(code) => { + info!("Code: {:?}", code); + + // Convert Code object to JSON + let code_json = serde_json::to_string(&code).unwrap(); + + // Write the JSON to the serial port + external_api.write_to_serial(&code_json)?; + } } info!("Stopping agent");