CloudMandala/src/clouds.rs

177 lines
7.5 KiB
Rust

use std::fs; //, io};
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
use rfm::mkdir;
use std::collections::HashMap;
use serde_yaml::Value;
use serde_dhall;
// use std::process::{Command};
use std::collections::BTreeMap;
use anyhow::{anyhow,Result,Context,Error};
use tkdr::tera_lib::make_template_content;
use clds::pkgs::{get_pkgs_vers,PkgInfo,PkgVers};
use clds::clouds::defs::{
CfgRs,
CloudEnv,
Cloud,
ConfigResources,
Server,
TskSrvc,
MainResourcesConfig,
};
use clds::clouds::on_clouds::env_cloud;
use clds::tsksrvcs::run_tsksrvcs_on_providers;
use crate::defs::{load_key};
use crate::errors::AppError;
use crate::utils;
// use tempfile::tempfile;
// use std::fs::File;
//use base64_stream::FromBase64Writer;
/// On_cloud
/// Load env and config files
/// Load `tsksrvc` (can be group of tsksrvcs)
/// On each `element` in `config` run `tsksrvc`
pub async fn on_cloud(tsksrvc: &str, cmd: &str, nxt: &str, source: &str, listhosts: &str, force: u8) -> Result<String> {
let mut cloud = Cloud::default();
cloud.env = CloudEnv::new(force, load_key().await);
cloud.providers = Cloud::load_providers().await;
env_cloud(source, &mut cloud.env).await?;
get_pkgs_vers(&mut cloud).await?;
cloud.env.listhosts = String::from(listhosts);
let cfg_path = format!("{}/{}/{}/{}",&cloud.env.home,&source,&cloud.env.config_root,&cloud.env.config_path);
let mut cfg_data = fs::read_to_string(&cfg_path).with_context(|| format!("Failed to read 'cfg_path' from {}", &cfg_path))?;
let mut cfg: MainResourcesConfig = serde_yaml::from_str(&cfg_data)?;
let provider = cloud.providers.get(&cfg.provider).with_context(|| format!("Provider '{}'' not defined", &cfg.provider))?;
// Load tsksrvcs.yaml into TskSrvcs
// for (i, tsk) in tsksrvcs.tsksrvcsList.iter().enumerate() {
// if tsksrvc == "all" || tsk.name.as_str() == tsksrvc {
// match tsk.target.as_str() {
// "servers" => on_cloud_server(&mut cloud, i, tsk).await?,
// _ => println!("Target '{}' undefined from {}", &tsk.target, cloud.env.config_path),
// }
// }
// }
//let tsksrvcs_path = format!("{}/home/{}/tsksrvcs.yaml",&cloud.env.path,&source);
//let mut tsksrvcs_data = fs::read_to_string(&tsksrvcs_path).with_context(|| format!("Failed to read 'tsksrvcs_path' from {}", &tsksrvcs_path))?;
//let mut tsksrvcs: TskSrvcs = serde_yaml::from_str(&tsksrvcs_data)?; // .with_context(|| format!("Failed to parse 'tsksrvcs_path' from {}", &tsksrvcs_path))?;
run_tsksrvcs_on_providers(provider, &cfg_data, &cloud, tsksrvc, &cmd, &nxt, &cfg).await?;
// .map_err(|e| AppError::ErrorInternalServerError(format!("Template error {}",e)))?;
//utils::tera_render(tera: &mut Tera, tpl_context: tera::Context, tpl: &str, output_path: &str, append: bool).await?;
// dbg!(&cloud);
// for (i, elem) in config_res.servers.iter().enumerate() {
// dbg!(&elem);
// }
// // println!("DONE: {} - {}",&tsksrvc,&source);
// if &envmnt::get_or("WEB_MODE", "") == "" {
// // println!("{}",&str_config_res);
// println!("DONE: {} ",&cfg_path);
// }
Ok("done".to_string())
}
/*
pub fn get_packages_serde_value(src: &Option<HashMap<String,HashMap<String,serde_yaml::Value>>>, key: &str, target: &str, dflt: String) -> String {
let mut target_value= String::from("");
if let Some(pkgs) = &src {
if let Some(val) = pkgs.get(key) {
if let Some(item) = val.get(target) {
dbg!(item);
match item.as_str() {
Some(v) => target_value=v.to_string(),
None => target_value=dflt.to_owned(),
}
// target_value = tkdr::tera_lib::get_yaml_val(item,dflt);
};
}
}
target_value
}
pub async fn create_full_config(cloud: &mut Cloud) -> Result<()> {
let mut output_path = format!("{}/specs",&cloud.env.provision);
if ! Path::new(&output_path).exists() {
fs::create_dir(&output_path)?;
println!("{} created", &output_path);
}
output_path = format!("{}/specs/config.yaml",&cloud.env.provision);
if Path::new(&output_path).exists() && cloud.env.force < 1u8 {
println!("Found created {}", &output_path);
return Ok(());
}
let mut config_resources = cloud.config_resources.to_owned();
config_resources.servers = Vec::new();
let mut file =std::fs::File::create(&output_path).with_context(|| format!("Failed to open to file: {}",&output_path))?;
let mut str_config_resources = serde_yaml::to_string(&config_resources).with_context(|| format!("Failed creating yaml from config_resources in {}",&cloud.env.provision))?;
str_config_resources = str_config_resources.replace("servers: []","servers: \n");
file.write(&str_config_resources.as_bytes())?;
// fs.write apped to fs::write!(&output_path);
/*
for (i, elem) in cloud.config_resources.servers.iter().enumerate() {
if let Some(tpl) = &elem.tpl {
let tpl_path = get_env_path("",&tpl, &cloud.env.source , &cloud.env.tpls_path,true).await?;
let tpl_content= fs::read_to_string(&tpl_path).with_context(|| format!("Failed to read 'tpl_path' from {}", &tpl_path))?;
// println!("Template {} -> {}",&tpl, &tpl_path);
utils::tpl_data_server(&elem, &tpl_content, &output_path, true).await.with_context(|| format!("Failed 'ConfigResources' template {}",&tpl_path))?;
if let Some(specs) = &elem.spec {
if let Some(pkgs_tpl) = &specs.tplPkgs {
let pkgs_tpl_path = get_env_path("",&pkgs_tpl, &cloud.env.source , &cloud.env.tpls_path, true).await?;
let pkgs_tpl_content= fs::read_to_string(&pkgs_tpl_path).with_context(|| format!("Failed to read 'pkgs_tpl_path' from {}", &pkgs_tpl_path))?;
utils::tpl_data_map(&cloud.env.pkgs_vers, &pkgs_tpl_content, &output_path, true).await.with_context(|| format!("Failed render 'versions' on template {}",&pkgs_tpl_path))?;
// let mut file = OpenOptions::new().append(true).open(&output_path)?;
// file.write(&pkgs_tpl_content.as_bytes())?;
}
}
}
}
*/
println!("Full 'config_resources' created");
Ok(())
}
/// On_cloud_servers run tsksrvcs
pub async fn on_cloud_server(cloud: &mut Cloud, pos: usize, tsksrvc: &TskSrvc) -> Result<()> {
let mut tsksrvc_path = String::from("");
if tsksrvc.path.len() > 0 {
tsksrvc_path = get_env_path(format!("CLOUDS_TSKSRVC_{}",&tsksrvc.name).as_str(), &tsksrvc.path, "" , &cloud.env.root_tsksrvcs,true).await?;
}
match tsksrvc.name.as_str() {
"createserver" | "modifyip" | "startserver" => {
for (i, elem) in cloud.config_resources.servers.iter().enumerate() {
println!("TskSrvc {}th {} in {}th {}: {} ", pos+1, &tsksrvc.name,i+1, &tsksrvc.target, &elem.hostname);
println!("{}",&tsksrvc_path);
if let Some(provider) = &cloud.config_resources.provider {
match provider.as_str() {
"upcloud" => if let Some(provider_def) = cloud.providers.get(provider) {
let cmd = format!("{} {} {}",&provider_def.runner,&provider_def.args, &tsksrvc.name);
println!("Provider '{}' to create '{} -f {}/config_resources.yaml",provider,&cmd, &cloud.env.provision);
},
"manual" => {
println!("Provider '{}' create manually",&provider);
if tsksrvc.path.len() > 0 {
tkdr::utils::run_command(&tsksrvc.path,"","")?;
}
},
_ => println!("Provider '{}' to create '{}' undefined",&provider,&elem.hostname),
}
}
}
},
_ => println!("TskSrvc '{}' undefined on {}", &tsksrvc.name, &tsksrvc.target),
}
Ok(())
}
*/