180 lines
5.2 KiB
Rust
180 lines
5.2 KiB
Rust
// mod to communicate with api-grub config file
|
|
// 1) check changes in unix-socket
|
|
// 2) save changes in local config file
|
|
use anyhow::{Error, Ok, Result};
|
|
use log::{info, warn, error};
|
|
use std::{fs, path::Path};
|
|
use serde_json::from_str;
|
|
use tokio::{io::AsyncReadExt, net::UnixListener};
|
|
use tokio::time::{sleep, Duration};
|
|
use std::result::Result::Ok as stdOk;
|
|
use tokio::sync::mpsc::Sender;
|
|
use integr_structs::api::v3::Config;
|
|
|
|
const CONFIG_PATH: &str = "config_api.json";
|
|
const SOCKET_PATH: &str = "api-grub.sock";
|
|
|
|
// TODO: rewrite to use current_exe
|
|
/// # Fn `pull_local_config`
|
|
///
|
|
/// ## function to one-time pulling local config by straight reading
|
|
///
|
|
/// ### Dev-Info :
|
|
///
|
|
/// *input* : -
|
|
///
|
|
/// *output* : `anyhow::Result<integr_structs::api::v3::Config>`
|
|
///
|
|
/// *initiator* : fn `main`
|
|
///
|
|
/// *managing* : -
|
|
///
|
|
pub async fn pull_local_config() -> Result<Config> {
|
|
let path = Path::new(CONFIG_PATH);
|
|
if path.exists() && path.is_file() {
|
|
let config: Config = from_str(
|
|
&fs::read_to_string(CONFIG_PATH)?
|
|
)?;
|
|
Ok(config)
|
|
} else {
|
|
Err(Error::msg("No local conf was found"))
|
|
}
|
|
}
|
|
|
|
// for config pulling
|
|
/// # Fn `pull_local_config`
|
|
///
|
|
/// ## function to init Unix-Socket listening for grabbing new configs
|
|
///
|
|
/// ### Dev-Info :
|
|
///
|
|
/// *input* : `&tokio::sync::mpsc::Sender<integr_structs::api::v3::Config>`
|
|
///
|
|
/// *output* : `anyhow::Result<()>`
|
|
///
|
|
/// *initiator* : fn `main`
|
|
///
|
|
/// *managing* : -
|
|
///
|
|
/// *depends on* : `const SOCKET_PATH`
|
|
///
|
|
pub async fn init_config_grub_mechanism(tx: &Sender<Config>) -> Result<()> {
|
|
info!("Initializing Unix-Socket listening for pulling new configs...");
|
|
let server = init_unix_listener().await?;
|
|
|
|
info!("Listening Unix-Socket...");
|
|
let mut buffer = String::new();
|
|
|
|
loop {
|
|
if let stdOk((mut stream, _)) = server.accept().await {
|
|
if let Err(er) = stream.read_to_string(&mut buffer).await {
|
|
warn!("Cannot read config from stream due to {}", er);
|
|
} else {
|
|
let config: Result<Config, serde_json::Error> = from_str(&buffer);
|
|
if let stdOk(conf) = config {
|
|
info!("New config was pulled from Unix-Stream. Saving it locally and sharing with API-grub module...");
|
|
if let Err(er) = save_new_config(&buffer).await {
|
|
error!("Cannot save new config locally due to: {}", er);
|
|
}
|
|
let _ = tx.send(conf).await;
|
|
} else if let Err(er) = config {
|
|
warn!("Invalid config was pulled. Error: {}", er);
|
|
}
|
|
}
|
|
}
|
|
sleep(Duration::from_millis(500)).await;
|
|
}
|
|
}
|
|
|
|
// saving new config locally
|
|
/// # Fn `save_new_config`
|
|
///
|
|
/// ## function for saving new config locally
|
|
///
|
|
/// ### Dev-Info :
|
|
///
|
|
/// *input* : `&String | &str`
|
|
///
|
|
/// *output* : `anyhow::Result<()>`
|
|
///
|
|
/// *initiator* : fn `main`
|
|
///
|
|
/// *managing* : -
|
|
///
|
|
/// *depends on* : `const CONFIG_PATH`
|
|
///
|
|
async fn save_new_config(config: &String) -> Result<()> {
|
|
fs::write(CONFIG_PATH, config)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// # Fn `pull_local_config`
|
|
///
|
|
/// ## function for saving new config locally
|
|
///
|
|
/// ### Dev-Info :
|
|
///
|
|
/// *input* : `&tokio::sync::mpsc::Sender<Config>`
|
|
///
|
|
/// *output* : `anyhow::Result<tokio::net::UnixListener>`
|
|
///
|
|
/// *initiator* : fn `init_config_grub_mechanism`
|
|
///
|
|
/// *managing* : -
|
|
///
|
|
/// *depends on* : `const SOCKET_PATH`
|
|
///
|
|
async fn init_unix_listener() -> Result<UnixListener> {
|
|
let _ = fs::remove_file(SOCKET_PATH);
|
|
Ok(UnixListener::bind(SOCKET_PATH)?)
|
|
}
|
|
|
|
|
|
#[cfg(test)]
|
|
mod config_unittests {
|
|
use super::*;
|
|
use tokio::test;
|
|
|
|
#[test]
|
|
async fn check_init_unix_listener() {
|
|
let res = init_unix_listener().await;
|
|
if res.is_ok() {
|
|
assert!(fs::remove_file(SOCKET_PATH).is_ok())
|
|
} else {
|
|
assert!(false)
|
|
}
|
|
}
|
|
#[test]
|
|
async fn check_save_new_config() {
|
|
use std::fs;
|
|
use integr_structs::api::v3::Config;
|
|
use serde_json::to_string;
|
|
|
|
let test_config_path = "test_config_api.json";
|
|
|
|
// config gen
|
|
let config = to_string::<Config>(&Config::default());
|
|
assert!(config.is_ok());
|
|
let config = config.unwrap();
|
|
|
|
// config file gen and write
|
|
assert!(fs::File::create(test_config_path).is_ok());
|
|
assert!(fs::write(test_config_path, config).is_ok());
|
|
|
|
// config file reading and checking content
|
|
let file = fs::read_to_string(test_config_path);
|
|
assert!(file.is_ok());
|
|
let file = file.unwrap();
|
|
assert_ne!(file.len(), 0);
|
|
|
|
// deleting test config file
|
|
assert!(fs::remove_file(test_config_path).is_ok())
|
|
}
|
|
|
|
#[test]
|
|
async fn check_pull_local_config() {
|
|
use std::path::Path;
|
|
let local_config = Path::new(CONFIG_PATH);
|
|
assert_eq!(local_config.is_file() && local_config.exists(), pull_local_config().await.is_ok())
|
|
}
|
|
} |