use std::env;
use std::path::{Path, PathBuf};
pub const NETAVARK_PROXY_RUN_DIR: &str = "/run/podman";
pub const NETAVARK_PROXY_RUN_DIR_ENV: &str = "NETAVARK_PROXY_RUN_DIR_ENV";
pub const DEFAULT_UDS_PATH: &str = "/run/podman/nv-proxy.sock";
pub const DEFAULT_CONFIG_DIR: &str = "";
pub const DEFAULT_NETWORK_CONFIG: &str = "/dev/stdin";
pub const DEFAULT_TIMEOUT: u32 = 8;
pub const PROXY_SOCK_NAME: &str = "nv-proxy.sock";
pub const CACHE_FILE_NAME: &str = "nv-proxy.lease";
pub const DEFAULT_INACTIVITY_TIMEOUT: u64 = 300;
pub fn get_run_dir(run_cli: Option<&str>) -> String {
match env::var(NETAVARK_PROXY_RUN_DIR_ENV) {
Ok(v) => return v,
Err(_) => {
if let Some(val) = run_cli {
return val.to_string();
}
}
}
NETAVARK_PROXY_RUN_DIR.to_string()
}
pub fn get_proxy_sock_fqname(run_dir_opt: Option<&str>) -> PathBuf {
let run_dir = get_run_dir(run_dir_opt);
Path::new(&run_dir).join(PROXY_SOCK_NAME)
}
pub fn get_cache_fqname(run_dir: Option<&str>) -> PathBuf {
let run_dir = get_run_dir(run_dir);
Path::new(&run_dir).join(CACHE_FILE_NAME)
}
#[cfg(test)]
mod conf_tests {
use crate::dhcp_proxy::proxy_conf::{
get_cache_fqname, get_proxy_sock_fqname, get_run_dir, CACHE_FILE_NAME,
NETAVARK_PROXY_RUN_DIR, NETAVARK_PROXY_RUN_DIR_ENV, PROXY_SOCK_NAME,
};
use std::path::Path;
use std::collections::HashMap;
use std::env;
use std::ffi::OsStr;
use std::hash::Hash;
use std::panic::{self, RefUnwindSafe, UnwindSafe};
use std::sync::Mutex;
use once_cell::sync::Lazy;
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
static SERIAL_TEST: Lazy<Mutex<()>> = Lazy::new(Default::default);
pub fn with_var<K, V, F, R>(key: K, value: Option<V>, closure: F) -> R
where
K: AsRef<OsStr> + Clone + Eq + Hash,
V: AsRef<OsStr> + Clone,
F: Fn() -> R + UnwindSafe + RefUnwindSafe,
{
with_vars(vec![(key, value)], closure)
}
pub fn with_var_unset<K, F, R>(key: K, closure: F) -> R
where
K: AsRef<OsStr> + Clone + Eq + Hash,
F: Fn() -> R + UnwindSafe + RefUnwindSafe,
{
with_var(key, None::<&str>, closure)
}
pub fn with_vars<K, V, F, R>(kvs: Vec<(K, Option<V>)>, closure: F) -> R
where
K: AsRef<OsStr> + Clone + Eq + Hash,
V: AsRef<OsStr> + Clone,
F: Fn() -> R + UnwindSafe + RefUnwindSafe,
{
let guard = SERIAL_TEST.lock().unwrap();
let mut old_kvs: HashMap<K, Option<String>> = HashMap::new();
for (key, value) in kvs {
if !old_kvs.contains_key(&key) {
let old_value = env::var(&key).ok();
old_kvs.insert(key.clone(), old_value);
}
update_env(&key, value);
}
match panic::catch_unwind(closure) {
Ok(result) => {
for (key, value) in old_kvs {
update_env(key, value);
}
result
}
Err(err) => {
for (key, value) in old_kvs {
update_env(key, value);
}
drop(guard);
panic::resume_unwind(err);
}
}
}
fn update_env<K, V>(key: K, value: Option<V>)
where
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
match value {
Some(v) => env::set_var(key, v),
None => env::remove_var(key),
}
}
fn random_string(len: usize) -> String {
let rand_string: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(len)
.map(char::from)
.collect();
format!("/{rand_string}")
}
#[test]
fn test_run_dir_env() {
let r = random_string(25);
with_var(NETAVARK_PROXY_RUN_DIR_ENV, Some(&r), || {
assert_eq!(get_run_dir(None), r)
});
}
#[test]
fn test_run_dir_with_opt() {
let r = random_string(25);
with_var_unset(NETAVARK_PROXY_RUN_DIR_ENV, || {
assert_eq!(get_run_dir(Some(&r)), r)
});
}
#[test]
fn test_run_dir_as_none() {
with_var_unset(NETAVARK_PROXY_RUN_DIR_ENV, || {
assert_eq!(get_run_dir(None), NETAVARK_PROXY_RUN_DIR)
});
}
#[test]
fn test_get_cache_env() {
let r = random_string(25);
with_var(NETAVARK_PROXY_RUN_DIR_ENV, Some(&r), || {
assert_eq!(get_cache_fqname(None), Path::new(&r).join(CACHE_FILE_NAME));
});
}
#[test]
fn test_get_cache_with_opt() {
let r = random_string(25);
with_var_unset(NETAVARK_PROXY_RUN_DIR_ENV, || {
assert_eq!(
get_cache_fqname(Some(&r)),
Path::new(&r).join(CACHE_FILE_NAME)
)
})
}
#[test]
fn test_get_cache_as_none() {
with_var_unset(NETAVARK_PROXY_RUN_DIR_ENV, || {
assert_eq!(
get_cache_fqname(None),
Path::new(NETAVARK_PROXY_RUN_DIR).join(CACHE_FILE_NAME)
)
});
}
#[test]
fn test_get_proxy_sock_env() {
let r = random_string(25);
with_var(NETAVARK_PROXY_RUN_DIR_ENV, Some(&r), || {
assert_eq!(
get_proxy_sock_fqname(None),
Path::new(&r).join(PROXY_SOCK_NAME)
);
});
}
#[test]
fn test_get_proxy_sock_with_opt() {
let r = random_string(25);
with_var_unset(NETAVARK_PROXY_RUN_DIR_ENV, || {
assert_eq!(
get_proxy_sock_fqname(Some(&r)),
Path::new(&r).join(PROXY_SOCK_NAME)
)
})
}
#[test]
fn test_get_proxy_sock_as_none() {
with_var_unset(NETAVARK_PROXY_RUN_DIR_ENV, || {
assert_eq!(
get_proxy_sock_fqname(None),
Path::new(NETAVARK_PROXY_RUN_DIR).join(PROXY_SOCK_NAME)
)
});
}
}