diff --git a/Cargo.toml b/Cargo.toml index 6ae6568..d914bf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,33 +1,36 @@ [package] name = "device-common" -version = "0.1.0" +version = "0.1.1" edition = "2021" -publish = ["nexus","https://maven.anypoint.tv/repository/crate/index"] -repository = "https://Ryan:HEG2XSI4fF88+zR2DkVuiEzNXRMvC9Bd077s7qMpyg@" authors = ["Ryan Bae "] [dependencies] -serde = { version = "1.0.202", features = ["derive"] } -serde_json = "1.0.117" -bincode = "1.3.3" -aws-config = { version = "1.5.0" } -aws-sdk-kinesis = { version = "1.27.0", features = ["behavior-version-latest"] } -aws-sdk-ssm = "1.39" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +bincode = "1.3" +aws-config = { version = "1.5" } +aws-sdk-kinesis = { version = "1.36", features = ["behavior-version-latest"] } +aws-sdk-ssm = "1.40" aws-types="1.3" -aws-credential-types = { version = "1.2.0", features = ["hardcoded-credentials"] } +aws-credential-types = { version = "1.2", features = ["hardcoded-credentials"] } deadpool-postgres = "0.14" tokio-postgres = { version = "0.7", features = ["with-chrono-0_4"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-unwrap = "1.0" -tracing-appender = "0.2.3" +tracing-appender = "0.2" thiserror = "1.0" -tokio = "1.38.0" +tokio = { version = "1.39", features = ["full"] } lapin = "2.3" sysinfo = "0.30" prometheus = "0.13" dashmap = "6.0" toml = "0.8" +serial_test = "3.1" +async-trait = "0.1" + +[dev-dependencies] +mockall = "0.13" [profile.dev] opt-level = 0 diff --git a/src/database.rs b/src/database.rs index dc298b0..2914327 100644 --- a/src/database.rs +++ b/src/database.rs @@ -21,73 +21,6 @@ async fn initialize_data() -> Arc { Arc::new(pool) } -/* -pub async fn initialize_data() -> Arc { - let config = get_config().await; - - let mut current_dir = current_exe().unwrap(); - current_dir.pop(); - current_dir.push("db.pem"); - let cert_file = File::open(current_dir.display().to_string()).unwrap(); - let mut buf = BufReader::new(cert_file); - let mut root_store = rustls::RootCertStore::empty(); - for cert in rustls_pemfile::certs(&mut buf) { - root_store.add(cert.unwrap()).unwrap(); - } - - let tls_config = rustls::ClientConfig::builder() - .with_root_certificates(root_store) - .with_no_client_auth(); - - let tls = MakeRustlsConnect::new(tls_config); - - let mut pg = deadpool_postgres::Config::new(); - pg.host = Some(config.database.host.clone()); - pg.user = Some(config.database.user.clone()); - pg.password = Some(config.database.password.clone()); - pg.dbname = Some(config.database.name.clone()); - pg.port = Some(config.database.port as u16); - - let pool = pg.create_pool(Some(Runtime::Tokio1), tls).unwrap(); - - Arc::new(pool) -} -*/ - -/* -pub async fn initialize_data() -> Arc { - let config = get_config().await; - - let mut current_dir = current_exe().unwrap(); - current_dir.pop(); - current_dir.push("db.pem"); - let cert_file = File::open(current_dir.display().to_string()).unwrap(); - let mut buf = BufReader::new(cert_file); - let mut root_store = rustls::RootCertStore::empty(); - for cert in rustls_pemfile::certs(&mut buf) { - root_store.add(cert.unwrap()).unwrap(); - } - - let tls_config = TlsConnector::builder() - .danger_accept_invalid_certs(true) - .build() - .expect_or_log(""); - - let tls = MakeTlsConnector::new(tls_config); - - let mut pg = deadpool_postgres::Config::new(); - pg.host = Some(config.database.host.clone()); - pg.user = Some(config.database.user.clone()); - pg.password = Some(config.database.password.clone()); - pg.dbname = Some(config.database.name.clone()); - pg.port = Some(config.database.port as u16); - - let pool = pg.create_pool(Some(Runtime::Tokio1), tls).unwrap(); - - Arc::new(pool) -} -*/ - pub async fn get_connection_pool() -> Arc { CONNECTION_POOL.get_or_init(initialize_data) .await diff --git a/src/env.rs b/src/env.rs index e32d8af..2c63c63 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,18 +1,152 @@ use std::env; -use std::error::Error; use std::str::FromStr; +use crate::log::expect_or_log; +use crate::model::error::DeviceError; pub fn set(key: &str, val: &str) { env::set_var(key, val); } -pub fn get(key: &str) -> Result> { +pub fn get(key: &str) -> Result { let ret = env::var(key)?; Ok(ret) } -pub fn get_i64(key: &str) -> Result> { +pub fn get_i64(key: &str) -> Result { let str_env = env::var(key)?; let ret = i64::from_str(&str_env)?; Ok(ret) +} + +pub fn get_prefix() -> String { + let profile = expect_or_log(env::var("RUST_PROFILE"), "RUST_PROFILE is not set"); + + let prefix = match profile.as_str() { + "dev" => "/dev", + "local" => "/dev", + "prod" => "/prod", + _ => { + expect_or_log(Err("Unexpected value"), &format!("Unexpected RUST_PROFILE value: {}", profile)) + } + }; + + prefix.to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + use serial_test::serial; + + fn setup() { + env::remove_var("RUST_PROFILE"); + } + + fn teardown() { + env::remove_var("RUST_PROFILE"); + } + + #[test] + #[serial] + fn test_set_and_get() { + setup(); + let key = "TEST_ENV_VAR"; + let value = "test_value"; + + set(key, value); + + let result = get(key); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), value); + teardown(); + } + + #[test] + #[serial] + fn test_get_none_exist_ent_var() { + setup(); + let key = "NONE_EXIST_ENT_ENV_VAR"; + + env::remove_var(key); + + let result = get(key); + assert!(result.is_err()); + teardown(); + } + + #[test] + #[serial] + fn test_set_and_get_i64() { + setup(); + let key = "TEST_ENV_I64"; + let value = "12345"; + + set(key, value); + + let result = get_i64(key); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), 12345); + teardown(); + } + + #[test] + #[serial] + fn test_get_i64_invalid_value() { + setup(); + let key = "TEST_ENV_I64_INVALID"; + let value = "invalid_number"; + + set(key, value); + + let result = get_i64(key); + assert!(result.is_err()); + teardown(); + } + + #[test] + #[serial] + fn test_get_prefix_dev() { + setup(); + env::set_var("RUST_PROFILE", "dev"); + assert_eq!(get_prefix(), "/dev"); + teardown(); + } + + #[test] + #[serial] + fn test_get_prefix_prod() { + setup(); + env::set_var("RUST_PROFILE", "prod"); + assert_eq!(get_prefix(), "/prod"); + teardown(); + } + + #[test] + #[serial] + fn test_get_prefix_local() { + setup(); + env::set_var("RUST_PROFILE", "local"); + assert_eq!(get_prefix(), "/dev"); + teardown(); + } + + #[test] + #[should_panic(expected = "Unexpected RUST_PROFILE value")] + #[serial] + fn test_get_prefix_unexpected_value() { + setup(); + let unexpected_profile = "abcdefg53546"; + env::set_var("RUST_PROFILE", &unexpected_profile); + get_prefix(); + teardown(); + } + + #[test] + #[should_panic(expected = "RUST_PROFILE is not set")] + #[serial] + fn test_get_prefix_not_set() { + setup(); + get_prefix(); + teardown(); + } } \ No newline at end of file diff --git a/src/log.rs b/src/log.rs index dad4ae2..c337167 100644 --- a/src/log.rs +++ b/src/log.rs @@ -1,6 +1,6 @@ use std::env::current_exe; use std::fs; -use tracing::{Level, subscriber}; +use tracing::{error, Level, subscriber}; use tracing_appender::non_blocking::{WorkerGuard}; use tracing_appender::rolling::{RollingFileAppender, Rotation}; use tracing_unwrap::{OptionExt, ResultExt}; @@ -90,6 +90,17 @@ pub async fn init(log_file_name: &str) -> WorkerGuard { _guard } +pub fn expect_or_log(result: Result, message: &str) -> T { + match result { + Ok(val) => val, + Err(err) => { + let err_message = err.to_string(); + error!("{}: {}", message, err_message); + panic!("{}: {}", message, err_message); + } + } +} + fn get_log_dir() -> String { let mut current_dir = current_exe().unwrap(); current_dir.pop(); diff --git a/src/metrics.rs b/src/metrics.rs index d000783..ce8dd8a 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,6 +1,6 @@ use sysinfo::System; use prometheus::{register_gauge, Gauge}; -use std::sync::OnceLock; +use std::sync::{Arc, OnceLock}; pub fn get_cpu_usage() -> &'static Gauge { static GAUGE: OnceLock = OnceLock::new(); diff --git a/src/parameter_store.rs b/src/parameter_store.rs index 9c21abb..4c198f0 100644 --- a/src/parameter_store.rs +++ b/src/parameter_store.rs @@ -47,30 +47,8 @@ async fn get_client() -> Arc { .clone() } -pub fn get_prefix() -> String { - let mut profile: String = "".to_string(); - let name = "RUST_PROFILE"; - - match std::env::var(name) { - Ok(v) => profile = v, - Err(e) => panic!("${} is not set ({})", name, e), - } - - let mut prefix: String = "".to_string(); - match profile.as_str() { - "local" => { - prefix = "/dev".to_string(); - }, - _ => { - prefix = profile - } - }; - - prefix -} - pub async fn get_parameter(key: String) -> String { - let key_profile = get_prefix() + &key; + let key_profile = crate::env::get_prefix() + &key; let parameter_output = get_client() .await .get_parameter()