use std::env;
use std::fs;
use std::path::Path;
use crate::common::check_directory_path;
use crate::error::KcfgError;
use crate::KUBECONFIG;
use clap::Parser;
use lazy_static::lazy_static;
use regex::Regex;
const HOME: &str = "HOME";
lazy_static! {
static ref REGEX_FILE_SPLIT: Regex = Regex::new(r#"([\w\.-]+)(\.yaml|\.yml)$"#,).unwrap();
}
macro_rules! skip_none {
($res:expr) => {
match $res {
Some(val) => val,
None => continue,
}
};
}
#[derive(Clone, Parser, Debug)]
pub struct UseOptions {
#[clap(short, long, default_value = "~/.kube")]
directory: String,
#[clap(value_delimiter(','))]
input: Vec<String>,
}
pub fn router(params: UseOptions) -> Result<String, KcfgError> {
if params.input.is_empty() {
return Err(KcfgError::MissingInput);
}
let path_str = if params.directory.starts_with("~/") {
let home_var = env::var(HOME).map_err(|e| KcfgError::EnvVarError {
source: e,
var: HOME.to_string(),
})?;
params.directory.replace('~', &home_var)
} else {
params.directory
};
check_directory_path(&path_str)?;
let path = Path::new(&path_str);
let starting_string = params.input.join(".");
let directories = fs::read_dir(path)?.into_iter().filter_map(|e| e.ok());
for directory in directories {
let p = directory.path();
let captured = skip_none!(REGEX_FILE_SPLIT.captures(
p.to_str()
.ok_or_else(|| KcfgError::InvalidPath(p.clone()))?,
));
let name = skip_none!(captured.get(1)).as_str().to_string();
let ext = skip_none!(captured.get(2)).as_str().to_string();
if starting_string == name {
return Ok(format!(
"export {}={}/{}{}",
KUBECONFIG, path_str, name, ext
));
}
if name.starts_with(&format!("{}.", starting_string)) {
return Ok(name[starting_string.len() + 1..].to_string());
}
}
Err(KcfgError::ConfigNotFound(params.input))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_fail_with_no_input() {
let params = UseOptions {
directory: "test".to_string(),
input: vec![],
};
match router(params) {
Ok(_) => panic!("Test should have failed"),
Err(e) => {
if !matches!(e, KcfgError::MissingInput) {
panic!("Test failed with wrong error");
}
}
}
}
}