use anyhow::{anyhow,Result,Context, Error}; use std::{fs}; //,io}; use std::fs::OpenOptions; use std::io::{Write}; use std::path::Path; use rfm::mkdir; use std::str; use std::process::{Command}; // use std::ffi::OsString; use reqenv::ReqEnv; use crate::utils::{liveness_check}; use crate::clouds::defs::{ CloudEnv, Cloud, Provider, TskSrvc, MainResourcesConfig, }; use crate::defs::{ IsCritical, KloudHome, KloudCheckHome, SSHAccess, Cntrllr, CloudGroup, CloudCheckGroup, CloudItem, CloudCheckItem }; use crate::clouds::defs::{TsksrvcInfo}; use crate::clouds::upcloud::{get_upcloud_info,run_on_upcloud}; /// On_cloud /// load __`item`__ form `envmnt` with `dflt` /// Check if path from `source` exits for `item` or fallback to check from `root` path. /// __`item`__ path is requiered to exist pub async fn get_env_path(item: &str, dflt: &str, source: &str, root: &str, is_tpl: bool) -> Result { let mut base = dflt.to_owned(); if item.len() > 0 { base=envmnt::get_or(item,dflt); } if Path::new(&base).has_root() { if Path::new(&base).exists() { return Ok(base); } else { return Err(anyhow!("Path {} not found", &base)); } } #[allow(unused_assignments)] let mut item_path= String::from(""); if source.len() > 0 { item_path = format!("{}/{}",&source,&base); } else { item_path = format!("{}",&base); } if ! Path::new(&item_path).exists() { item_path=format!("{}/{}",root,&base); if is_tpl && ! Path::new(&item_path).exists() { item_path=format!("{}/{}",&source,&base); if ! Path::new(&item_path).exists() { item_path=format!("{}/{}",&root,&base); } } if ! Path::new(&item_path).exists() { return Err(anyhow!("Path '{}' not found in {} - {}", &base,&source,&root)); } } // println!("Path: {} src {} root {} item {}", &base, &source, &root, item_path); Ok(base) } /// env_cloud /// Scanning environment from __CLOUD_PATH__ overloaded with __CLOUD_HOME__ `source` CliOpts argument (-s) in case /// Load path from `envmnt` and __`get_env_path`___ /// __`source`__ path is mandatory pub async fn env_cloud(source: &str, cloud_env: &mut CloudEnv) -> Result<()> { cloud_env.path = envmnt::get_or("ROOT_KLDS", ""); if cloud_env.path.is_empty() { return Err(anyhow!("Clouds Root Path {} not found", &cloud_env.source_path)); } cloud_env.home=get_env_path("KLDS_HOME","home", "", &cloud_env.path,false).await?; cloud_env.monitor_run=envmnt::get_or("KLD_MONITOR_RUN","kloud_mon"); cloud_env.source=source.to_owned(); cloud_env.config_root = envmnt::get_or("KLD_CONFIG_ROOT", "config"); if source == "*" { cloud_env.config_path = envmnt::get_or("KLD_CONFIG", "config.yaml"); cloud_env.config_json_path = envmnt::get_or("KLD_CONFIG_JSON", "config.json"); return Ok(()) } let arr_source: Vec<&str> = source.split_terminator("/").collect(); if let Some(name) = arr_source.get(0) { cloud_env.cloud= format!("{}",&name); } if let Some(group) = arr_source.get(1) { cloud_env.group = format!("{}",&group); } if let Some(target) = arr_source.get(2) { cloud_env.target = format!("{}",&target); } cloud_env.source_path = format!("{}/{}",&cloud_env.home,&source); if ! Path::new(&cloud_env.source_path).exists() { return Err(anyhow!("Clouds Source Path {} not found", &cloud_env.source_path)); } cloud_env.config_path=get_env_path("KLDS_CONFIG","config.yaml", format!("{}/{}",&cloud_env.source_path,&cloud_env.config_root).as_str(), &cloud_env.path,false).await?; cloud_env.config_json_path=get_env_path("KLDS_CONFIG_JSON","config.json", format!("{}/{}",&cloud_env.source_path,&cloud_env.config_root).as_str(), &cloud_env.path,false).await?; if cloud_env.group.is_empty() { cloud_env.provision=format!("{}/{}/{}/{}",&cloud_env.home,&cloud_env.cloud,envmnt::get_or("CLOUD_PROVISION","provision"),&cloud_env.target); } else { cloud_env.provision=format!("{}/{}/{}/{}/{}",&cloud_env.home,&cloud_env.cloud,&cloud_env.group,envmnt::get_or("CLOUD_PROVISION","provision"),&cloud_env.target); } if ! Path::new(&cloud_env.provision).exists() { let dir_path_buf = Path::new(&cloud_env.provision).to_path_buf(); let dirs: Vec<&std::path::PathBuf> = vec![&dir_path_buf]; mkdir(&dirs).with_context(|| format!("\nFailed to create dir path {}", &cloud_env.provision))?; if envmnt::get_isize("DEBUG",0) > 1 { println!("{} created", &cloud_env.provision); } } cloud_env.wk_path = envmnt::get_or("KLDS_WKDIR", "/tmp"); cloud_env.tsksrvcs_path=get_env_path("KLDS_TSKSRVCS","tsksrvcs", &cloud_env.source_path,&cloud_env.path,false).await?; cloud_env.versions=get_env_path("KLDS_VERSIONS","versions.yaml", &cloud_env.source_path,&cloud_env.path,false).await?; Ok(()) } pub async fn clear_specs(source: &str) -> Result<()> { let env_path = envmnt::get_or("ROOT_KLDS", "clouds"); let env_home = get_env_path("KLDS_HOME","home", "", &env_path,false).await?; let env_source=format!("{}/{}",&env_home,&source); if ! Path::new(&env_source).exists() { return Ok(()); } let env_provision=format!("{}/{}",&env_source,envmnt::get_or("KLDS_PROVISION","provision")); let env_specs=format!("{}/specs",env_provision); if Path::new(&env_specs).exists() { if envmnt::get_isize("DEBUG",0) > 1 { println!("Delete {}/specs",env_provision); } fs::remove_dir_all(&env_specs)?; } Ok(()) } pub async fn load_config_data(cloud: &Cloud, source: &str) -> Result { // dbg!(&cloud); let cfg_path = format!("{}/{}/{}/{}",&cloud.env.home,&source,&cloud.env.config_root,&cloud.env.config_path); let cfg_data = fs::read_to_string(&cfg_path).with_context(|| format!("Failed to read 'cfg_path' from {}", &cfg_path))?; Ok(cfg_data) } pub async fn load_config_json_data(cloud: &Cloud, source: &str) -> Result { let cfg_path = format!("{}/{}/{}/{}",&cloud.env.home,&source,&cloud.env.config_root,&cloud.env.config_json_path); let cfg_data = fs::read_to_string(&cfg_path).with_context(|| format!("Failed to read json 'cfg_path' from {}", &cfg_path))?; Ok(cfg_data.replace("\n","")) } pub async fn load_cloud_env(cloud: &mut Cloud, source: &str) -> Result<()> { env_cloud(source, &mut cloud.env).await?; Ok(()) } pub async fn load_cloud_config(cloud: &mut Cloud, source: &str) -> Result<(KloudHome,Provider,String), Error> { // dbg!(&cloud.env); let cfg_data = load_config_data(&cloud,source).await?; let cfg: KloudHome = serde_yaml::from_str(&cfg_data)?; let cfg_provider = format!("{}",cfg.provider[0]); let provider = cloud.providers.get(&cfg_provider).with_context(|| format!("Provider '{}'' not defined", &cfg_provider))?; Ok((cfg, provider.to_owned(), cfg_data)) } pub async fn load_cloud_check_config(cloud: &mut Cloud, source: &str) -> Result<(KloudCheckHome,Provider,String), Error> { // dbg!(&cloud.env); let cfg_data = load_config_data(&cloud,source).await?; let cfg: KloudCheckHome = serde_yaml::from_str(&cfg_data)?; let cfg_provider = format!("{}",cfg.provider[0]); let provider = cloud.providers.get(&cfg_provider).with_context(|| format!("Provider '{}'' not defined", &cfg_provider))?; Ok((cfg, provider.to_owned(), cfg_data)) } pub async fn load_cloud_name_config(cloud: &mut Cloud, source: &str) -> Result<(MainResourcesConfig,Provider,String), Error> { // dbg!(&cloud.env); let cfg_data = load_config_data(&cloud,source).await?; let cfg: MainResourcesConfig = serde_yaml::from_str(&cfg_data)?; let provider = cloud.providers.get(&cfg.provider).with_context(|| format!("Provider '{}'' not defined", &cfg.provider))?; Ok((cfg, provider.to_owned(), cfg_data)) } pub async fn get_cloud_monitor_info(cloud: &mut Cloud, source: &str) -> Result { let cloud_home_path = format!("{}/{}",&cloud.env.home,&source); let monitor_path = format!("{}/{}",&cloud_home_path,&cloud.env.monitor_run); if Path::new(&monitor_path).exists() { let output = Command::new("bash") .arg(format!("{}",&monitor_path)) .arg("-o") .arg("json") .arg(format!("{}",&source)) .output()?; if !&output.status.success() { return Err(anyhow!("Run {} for {} failed: {}",&cloud.env.monitor_run,&source,&output.status)); } return Ok(str::from_utf8(&output.stdout).unwrap_or_else(|_| "").to_owned()); } Ok("".to_owned()) } pub async fn get_cloud_home_list(cloud: &Cloud) -> Result> { let kloud_files: Vec = fs::read_dir(&cloud.env.home)? .filter_map(|res| match res.map(|e| e.file_name()) { Ok(entry) => { // for e.path() // let file_path = entry.as_path().display().to_string(); let file_path = format!("{}",entry.to_owned().into_string().unwrap_or_else(|_|String::from(""))); let cfg_path = format!("{}/{}/{}/{}",&cloud.env.home,&file_path,&cloud.env.config_root,&cloud.env.config_path); let first_char = file_path.chars().next().unwrap_or_default().to_string(); if first_char.as_str() != "_" && first_char.as_str() != "." && Path::new(&cfg_path).exists() { Some(file_path) } else { None } }, Err(e) => { eprintln!("Error filter_map {}",e); None } } ) .collect(); Ok(kloud_files.to_owned()) } pub fn run_ssh_on_srvr(hostname: &str,tsksrvc_name: &str, tsksrvc_cmd: &str, ssh_access: &SSHAccess) -> Result { let debug = envmnt::get_isize("DEBUG",0); if debug > 0 { println!("Checking connection to {}@{} on {} for {} ",ssh_access.user,ssh_access.host,ssh_access.port,&tsksrvc_name); println!("ssh {} /var/lib/klouds/bin/{}_info.sh yaml",&hostname,&tsksrvc_name); } let output = Command::new("ssh") .arg("-q") .arg("-o") .arg("StrictHostKeyChecking=accept-new") .arg("-p") .arg(format!("{}",ssh_access.port)) .arg(format!("{}@{}",ssh_access.user,ssh_access.host)) .arg("sudo") .arg(format!("/var/lib/klouds/bin/{}_info.sh",&tsksrvc_name)) .arg("yaml") .arg(format!("{}",&tsksrvc_cmd)) // .arg(format!("ssh {} /var/lib/klouds/bin/{}_info.sh yaml",&hostname,&tsksrvc_name)) .output()?; //dbg!(&output); if !&output.status.success() { return Err(anyhow!("Connection to '{}' for tsksrvc '{}' failed: {}",&hostname,&tsksrvc_name,&output.status)); } let res = str::from_utf8(&output.stdout).unwrap_or_else(|_| ""); let info: serde_yaml::Value = serde_yaml::from_str(&res) .unwrap_or_else(|e| { eprintln!("serde_yaml: {}",e); serde_yaml::Value::default() }); Ok(info.to_owned()) } pub async fn parse_srvr_tsksrvcs(hostname: &str, sshaccess: &SSHAccess, tsksrvcs: &Vec,req_tsksrvcs: &str) -> Vec { let mut tsksrvcs_info: Vec = Vec::new(); for tsk in req_tsksrvcs.split(",") { match format!("{}",&tsk).as_str() { "os" => { let os_name = String::from("os"); tsksrvcs_info.push( TsksrvcInfo { name: format!("{}",&os_name), info: run_ssh_on_srvr(&hostname, &os_name, "", &sshaccess) .unwrap_or_else(|e| { eprintln!("run_ssh_on_srvr os: {}",e); serde_yaml::Value::default() }), }); }, "floatip" => { let floatip_name = String::from("floatip"); tsksrvcs_info.push( TsksrvcInfo { name: format!("{}",&floatip_name), info: run_ssh_on_srvr(&hostname, &floatip_name, "", &sshaccess) .unwrap_or_else(|e| { eprintln!("run_ssh_on_srvr floatip: {}",e); serde_yaml::Value::default() }), }); }, "kubernetes_pods" => { let k8_name = String::from("kubernetes"); tsksrvcs_info.push(TsksrvcInfo { name: format!("{}_pods",&k8_name), info: run_ssh_on_srvr(&hostname, &k8_name, "pods", &sshaccess) .unwrap_or_else(|e| { eprintln!("run_ssh_on_srvr kubernetes_pods: {}",e); serde_yaml::Value::default() }), }); }, _ => { continue; } }; } for tsksrvc in tsksrvcs.iter() { match format!("{}",&tsksrvc.name).as_str() { "pause" => continue, "scale" => continue, "systemfix" => continue, "os" => continue, _ => { let name = format!("{}",&tsksrvc.name); if req_tsksrvcs == "all" || req_tsksrvcs.contains(&name) { // TODO ssh &srv.hostname to get &name in "yaml" //println!("{} {} {}",&hostname,sshaccess.user,&tksrvc.name); tsksrvcs_info.push(TsksrvcInfo { name: format!("{}",&tsksrvc.name), info: run_ssh_on_srvr(&hostname, &name, "", &sshaccess) .unwrap_or_else(|e| { eprintln!("run_ssh_on_srvr for {}: {}",&tsksrvc.name,e); serde_yaml::Value::default() }), }); } } }; } tsksrvcs_info.to_owned() } pub async fn liveness_srvr_tsksrvcs(source: &str, cntrllrs: &Vec, tsksrvcs: &Vec, req_tsksrvc: &str) -> Vec { let mut tsksrvcs_info: Vec = Vec::new(); let debug=envmnt::get_isize("DEBUG",0); for tsksrvc in tsksrvcs.iter() { match format!("{}",&tsksrvc.name).as_str() { "pause" => continue, "scale" => continue, "systemfix" => continue, _ => { let name = format!("{}",&tsksrvc.name); if tsksrvc.liveness.is_empty() || (req_tsksrvc != "" && !req_tsksrvc.contains(&name)) { continue; } let serverstring = format!("{}",&tsksrvc.liveness); if debug > 2 { println!("livenes: {} -> {}",&tsksrvc.name,&serverstring); } let res_info = match liveness_check(&source,&cntrllrs,&serverstring,&name).await { Ok(_) => "ok", Err(e) => { if tsksrvc.critical == IsCritical::yes { let monitor_name = "WUJI_MONITOR"; println!("{} critical livenes: {} -> {}",envmnt::get_or(&monitor_name,""),&tsksrvc.name,&serverstring); } if debug > 0 { eprint!("liveness_check error: {}",e); } "err" }, }; // println!("{} info: {}",&tsksrvc.name,&res_info); tsksrvcs_info.push(TsksrvcInfo { name: format!("{}",&tsksrvc.name), info: serde_yaml::from_str(res_info).unwrap_or_else(|e| { eprintln!("Serde liveness Error: {} {} -> {}",&source,&serverstring,e); serde_yaml::Value::default() }), }); }, } } tsksrvcs_info.to_owned() } pub async fn get_provider_info(provider: &str, hostname: &str, cmd: &str , cfg_path: &str) -> String { match provider { "upcloud" => { get_upcloud_info(hostname,cmd,cfg_path).await }, _ => String::from("") } } pub async fn run_on_provider(reqname: &str, req_tsksrvc: &str, req_srvrs: &str, provider: Provider, source: &str, cfg_data: String, env_cloud: &Cloud) -> String { match provider.name.as_str() { "upcloud" => { // TODO clean SSH keys or encrypt content // dbg!(&cloud_config); run_on_upcloud(reqname,req_tsksrvc,req_srvrs, source, cfg_data, env_cloud).await }, _ => { let result = format!("Errors on {} provider {} not found",&source,&provider.name); if envmnt::get_isize("DEBUG",0) > 1 { println!("{}",&result); } result } } } pub async fn on_cloud_name_req(reqname: &str,env_cloud: &Cloud,_reqenv: &ReqEnv,req_tsksrvc: &str, req_srvrs: &str, source: &str) -> String { let mut cloud = env_cloud.to_owned(); load_cloud_env(&mut cloud, &source).await .unwrap_or_else(|e| { eprintln!("load_cloud_env: {}",e); }); let (cfg,provider,cfg_data) = load_cloud_name_config(&mut cloud, &source).await .unwrap_or_else(|e| { eprintln!("load_cloud_name_config: {}",e); (MainResourcesConfig::default(),Provider::default(),String::from("")) }); if cfg.mainName.is_empty() || cfg_data.is_empty() { let result = format!("Errors loading {}",&source); if envmnt::get_isize("DEBUG",0) > 1 { println!("{}",&result); } return result; } run_on_provider(&reqname,&req_tsksrvc,&req_srvrs,provider,&source,cfg_data,&cloud).await } pub async fn create_cloud_config(reqname: &str,req_tsksrvcs: &str,reqenv: &ReqEnv, entries: Vec,mut cloud: Cloud) -> String { let config = reqenv.config(); let debug = envmnt::get_isize("DEBUG",0); let check_path = format!("{}/clouds.json",&config.check_path); let mut check_entries: Vec = Vec::new(); let mut no_check_entries = true; if reqname != "check_job" { if Path::new(&check_path).exists() { // Load & Parse reuse liveness and monitor let check_data = fs::read_to_string(&check_path).unwrap_or_else(|e|{ eprintln!("Failed to read 'check_path' from {}: {}", &check_path,e); String::from("") }); if !check_data.is_empty() { check_entries = serde_json::from_str(&check_data).unwrap_or_else(|e| { eprintln!("Error loading check_entries ({}): {}",&check_path,e); Vec::new() }); no_check_entries=false; if debug> 0 { println!("Using check_entries from {}",&check_path); } // dbg!("{:#?}",&check_entries); } } } let mut entries_cfgs: Vec = Vec::new(); for (idx, entry) in entries.iter().enumerate() { let (mut cfg,_provider,cfg_data) = load_cloud_config(&mut cloud, &entry).await .unwrap_or_else(|e| { eprintln!("Load_cloud_config: {}",e); (KloudHome::default(),Provider::default(),String::from("")) }); if cfg.name.is_empty() || cfg_data.is_empty() { let result = format!("Errors loading {}",&entry); if debug > 0 { println!("{}",&result); } continue; } if req_tsksrvcs.contains("monitor") { if no_check_entries { cfg.monitor_info = Some(get_cloud_monitor_info(&mut cloud, &entry).await .unwrap_or_else(|e| { eprintln!("Error {} monitor_info {} -> {}",&entry,&cloud.env.monitor_run,e); String::from("") })); } else if check_entries.len() > 0 && check_entries.len() < idx { cfg.monitor_info = check_entries[idx].monitor_info.to_owned(); } } if reqname.contains("provision") || req_tsksrvcs.contains("resources") || req_tsksrvcs.contains("resources") || req_tsksrvcs.contains("liveness") { let mut groups: Vec = Vec::new(); // cfg.groups = cfg.groups.map(|grp| grp.with_resources(grp.path.to_owned())).collect(); for (grp_idx,grp) in cfg.groups.iter().enumerate() { let mut items: Vec = Vec::new(); for (itm_idx,itm) in grp.items.iter().enumerate() { let resources: Option; let liveness: Option; let provision: Option; if req_tsksrvcs.contains("liveness") { if no_check_entries { liveness = Some(on_cloud_name_req("liveness",&cloud,&reqenv,"","",&itm.path).await); } else if check_entries.len() > 0 && check_entries.len() < idx { liveness = check_entries[idx].groups[grp_idx].items[itm_idx].liveness.to_owned(); } else { liveness = Some(String::from("")); } } else { liveness = itm.liveness.to_owned(); } if reqname.contains("provision") || req_tsksrvcs.contains("provision") { provision = Some(on_cloud_name_req("provision",&cloud,&reqenv,"","",&itm.path).await); } else { provision = itm.provision.to_owned(); } if req_tsksrvcs.contains("resources") { resources = Some(load_config_json_data(&cloud,&itm.path).await .unwrap_or_else(|e| { eprintln!("Error loading resources -> {}",e); String::from("") })); } else { resources = itm.resources.to_owned(); } items.push(CloudItem { name: itm.name.to_owned(), info: itm.info.to_owned(), path: itm.path.to_owned(), resources, liveness, provision, graph: itm.graph.to_owned(), critical: itm.critical.to_owned(), }); } groups.push(CloudGroup { name: grp.name.to_owned(), info: grp.info.to_owned(), path: grp.path.to_owned(), // TODO check this for group resources: grp.resources.to_owned(), liveness: grp.liveness.to_owned(), provision: grp.provision.to_owned(), items, graph: grp.graph.to_owned(), prices: grp.prices.to_owned(), }); } cfg.groups=groups; } entries_cfgs.push(cfg.to_owned()); } serde_json::to_string(&entries_cfgs).unwrap_or_else(|_| String::from("")).replace("\n","") } pub async fn create_cloud_check(req_tsksrvcs: &str,reqenv: &ReqEnv,entries: Vec,mut cloud: Cloud) -> String { let mut cfg_entries: Vec = Vec::new(); for entry in entries.iter() { let (mut cfg,_provider,cfg_data) = load_cloud_check_config(&mut cloud, &entry).await .unwrap_or_else(|e| { eprintln!("load_cloud_check_config: {}",e); (KloudCheckHome::default(),Provider::default(),String::from("")) }); if cfg.name.is_empty() || cfg_data.is_empty() { let result = format!("Errors loading {}",&entry); if envmnt::get_isize("DEBUG",0) > 0 { println!("{}",&result); } continue; } if req_tsksrvcs.contains("monitor") { cfg.monitor_info = Some(get_cloud_monitor_info(&mut cloud, &entry).await .unwrap_or_else(|e| { eprintln!("Error {} monitor_info {} -> {}",&entry,&cloud.env.monitor_run,e); String::from("") })); } if req_tsksrvcs.contains("liveness") { let mut groups: Vec = Vec::new(); // cfg.groups = cfg.groups.map(|grp| grp.with_resources(grp.path.to_owned())).collect(); for grp in cfg.groups.iter() { let mut items: Vec = Vec::new(); for itm in grp.items.iter() { let liveness: Option; if req_tsksrvcs.contains("liveness") { liveness = Some(on_cloud_name_req("liveness",&cloud,&reqenv,"","",&itm.path).await); } else { liveness = itm.liveness.to_owned(); } items.push(CloudCheckItem { name: itm.name.to_owned(), info: itm.info.to_owned(), path: itm.path.to_owned(), liveness, critical: itm.critical.to_owned(), }); } groups.push(CloudCheckGroup { name: grp.name.to_owned(), info: grp.info.to_owned(), path: grp.path.to_owned(), // TODO check this for group liveness: grp.liveness.to_owned(), items, }); } cfg.groups=groups; } cfg_entries.push(cfg.to_owned()); } serde_json::to_string(&cfg_entries).unwrap_or_else(|_| String::from("")).replace("\n","") } pub async fn on_cloud_req(reqname: &str,env_cloud: &Cloud,reqenv: &ReqEnv,req_tsksrvcs: &str,_req_srvrs: &str, source: &str) -> String { //println!("{}",&reqname); let config = reqenv.config(); // let lock_path = format!("{}/{}_{}{}",&config.cache_lock_path,&reqname,&req_tsksrvcs.replace(",","_"),&config.cache_lock_ext); // if Path::new(&lock_path).exists() || reqname.ends_with("_job") { if ! reqname.ends_with("_job") { let output_path = format!("{}/{}_{}.json",&config.cache_path,&reqname,&req_tsksrvcs.replace(",","_")); if Path::new(&output_path).exists() { if envmnt::get_isize("DEBUG",0) > 0 { println!("Using cache: {} at {}",&output_path,envmnt::get_or(format!("LAST_CACHE_{}",&output_path), "")); } let output_data = fs::read_to_string(&output_path).with_context(|| format!("Failed to read json cache 'outut_path' from {}", &output_path)) .unwrap_or_else(|e| { eprintln!("read file {}: {}",&output_path,e); String::from("") }); return output_data; } } let mut cloud = env_cloud.to_owned(); load_cloud_env(&mut cloud, &source).await .unwrap_or_else(|e| { eprintln!("load_cloud_env {}",e); }); let entries: Vec; if source == "*" { entries = get_cloud_home_list(&cloud).await .unwrap_or_else(|e| { eprintln!("get_cloud_home_list: {}",e); Vec::new() }); } else { entries = vec!(source.to_string()); } if reqname == "check_job" { create_cloud_check(req_tsksrvcs,reqenv,entries,cloud).await } else { create_cloud_config(reqname,req_tsksrvcs,reqenv,entries,cloud).await } } pub async fn get_cloud_cache_req(reqenv: &ReqEnv,cloud: &Cloud, reqname: &str, reqname_job: &str, tsksrvcs: &str) -> Result<()> { let debug = envmnt::get_isize("DEBUG",0); if debug > 0 { println!("cloud cache {} ... {:?} ",reqname,chrono::Utc::now()); } let config = reqenv.config(); let lock_path = format!("{}/{}_{}.{}",&config.cache_lock_path,&reqname,&tsksrvcs.replace(",","_"),&config.cache_lock_ext); let output_path = format!("{}/{}_{}.json",&config.cache_path,&reqname,&tsksrvcs.replace(",","_")); if Path::new(&lock_path).exists() { if envmnt::get_or(format!("LAST_CACHE_{}",&output_path),"") != "" { if debug > 0 { println!("Lock found {} ",&lock_path); } // return Err(anyhow!("Lock found {} ",&lock_path)); return Ok(()) } else { println!("Not LAST_CACHE environment found for lock: {} ",&lock_path); } } // println!("Lock NOT found {} ",&lock_path); let now = chrono::Utc::now().timestamp(); envmnt::set(format!("LAST_CACHE_{}",&output_path), format!("{}",&now)); let result = on_cloud_req(&reqname_job,&cloud,&reqenv,tsksrvcs,"","*").await; if Path::new(&output_path).exists() { fs::remove_file(&output_path)?; } let mut file = OpenOptions::new().write(true).create(true).open(&output_path)?; file.write_all(result.as_bytes())?; if debug > 0 { println!("{}: [cloud config] -> {}\n",&now,&output_path); } Ok(()) } pub async fn make_cloud_cache(reqenv: &ReqEnv,cloud: &Cloud) -> Result<()> { if envmnt::get_isize("DEBUG",0) > 0 { println!("Making cloud cache {:?} ... ",chrono::Utc::now()); } get_cloud_cache_req(reqenv,cloud, "config", "config_job", "monitor,resources,liveness,provision").await.unwrap_or_else(|e| println!("Error cache config: {}",e)); Ok(()) } pub async fn run_clouds_check(reqenv: &ReqEnv,cloud: &Cloud) -> Result<()> { let debug = envmnt::get_isize("DEBUG",0); if debug > 0 { println!("cloud check ... {:?} ",chrono::Utc::now()); } let config = reqenv.config(); let output_path = format!("{}/clouds.json",&config.check_path); let now = chrono::Utc::now().timestamp(); envmnt::set(format!("LAST_CHECK{}",&output_path), format!("{}",&now)); let result = on_cloud_req("check_job",&cloud,&reqenv,"monitor,liveness","","*").await; // println!("{}",&output_path); if Path::new(&output_path).exists() { fs::remove_file(&output_path)?; } let mut file = OpenOptions::new().write(true).create(true).open(&output_path)?; file.write_all(result.as_bytes())?; if debug > 0 { println!("{}: [cloud check] -> {}\n",&now,&output_path); } Ok(()) }