2024-01-10 11:33:05 +00:00
|
|
|
pub(crate) mod config;
|
|
|
|
pub(crate) mod helpers;
|
|
|
|
pub(crate) mod mirror;
|
|
|
|
pub(crate) mod patch;
|
|
|
|
pub(crate) mod source;
|
2024-01-10 17:13:45 +00:00
|
|
|
pub(crate) mod template;
|
2024-01-10 11:33:05 +00:00
|
|
|
|
|
|
|
use clap::Parser;
|
|
|
|
use log::{error, info};
|
2024-01-10 14:50:56 +00:00
|
|
|
use std::collections::HashMap;
|
2024-01-10 21:48:56 +00:00
|
|
|
use std::{env, fs};
|
2024-01-10 11:33:05 +00:00
|
|
|
use std::{fs::create_dir, path::PathBuf, process::exit};
|
|
|
|
use tempfile::TempDir;
|
|
|
|
|
|
|
|
use crate::config::patch::init_git_repo;
|
|
|
|
|
|
|
|
/// Simple program to greet a person
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
#[command(author, version, about, long_about = None)]
|
|
|
|
struct Args {
|
|
|
|
/// Name of the working dir
|
|
|
|
#[arg(short, long)]
|
|
|
|
workdir: Option<String>,
|
|
|
|
/// Path to the configuration file
|
|
|
|
#[arg(short, long)]
|
|
|
|
config: String,
|
|
|
|
/// Dry run
|
|
|
|
#[arg(short, long, default_value = "false")]
|
|
|
|
dry_run: bool,
|
2024-01-10 21:48:56 +00:00
|
|
|
#[arg(long, default_value = "false")]
|
|
|
|
skip_prerequisites_check: bool,
|
2024-01-10 11:33:05 +00:00
|
|
|
/// Init git patch. Use it if you want to create git patch for a chart
|
|
|
|
/// It's going to pull a chart and init a git repo there, so you can
|
|
|
|
/// apply changes and create a patch file
|
|
|
|
/// It's not going to try mirroring changes, but will apply extensions
|
|
|
|
/// and patches that are already defined
|
|
|
|
#[arg(long)]
|
|
|
|
init_git_patch: Option<Vec<String>>,
|
|
|
|
}
|
|
|
|
|
2024-01-10 21:48:56 +00:00
|
|
|
fn check_prerequisites() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
info!("checking prerequisites");
|
|
|
|
let prerequisites = vec!["helm", "yq", "helm"];
|
|
|
|
for bin in prerequisites {
|
|
|
|
info!("checking {}", bin);
|
|
|
|
which::which(bin)?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-01-10 11:33:05 +00:00
|
|
|
fn main() {
|
2024-01-10 21:48:56 +00:00
|
|
|
// Prepare the logger
|
|
|
|
if env::var("RUST_LOG").is_err() {
|
|
|
|
env::set_var("RUST_LOG", "info")
|
|
|
|
}
|
2024-01-10 11:33:05 +00:00
|
|
|
env_logger::init();
|
2024-01-10 21:48:56 +00:00
|
|
|
|
2024-01-10 11:33:05 +00:00
|
|
|
let args = Args::parse();
|
2024-01-10 21:48:56 +00:00
|
|
|
if !args.skip_prerequisites_check {
|
|
|
|
if let Err(err) = check_prerequisites() {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2024-01-10 11:33:05 +00:00
|
|
|
// Prepare the workdir
|
|
|
|
let workdir_path = match args.workdir {
|
|
|
|
Some(res) => match create_dir(res.clone()) {
|
|
|
|
Ok(_) => {
|
|
|
|
let path = PathBuf::from(res);
|
2024-01-10 17:15:13 +00:00
|
|
|
let can_path = fs::canonicalize(path).ok().unwrap();
|
2024-01-10 11:33:05 +00:00
|
|
|
can_path.into_os_string().into_string().ok().unwrap()
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
let tmp_dir = match TempDir::new() {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
match tmp_dir.path().to_str() {
|
|
|
|
Some(res) => res.to_string(),
|
|
|
|
None => {
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Read the config
|
|
|
|
let config = match config::Config::new(args.config) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for mut chart in config.clone().charts {
|
2024-01-10 14:50:56 +00:00
|
|
|
chart.populate_variables(config.variables.clone());
|
2024-01-10 11:33:05 +00:00
|
|
|
match chart.populate_repository(config.repositories.clone()) {
|
|
|
|
Ok(_) => {
|
|
|
|
info!("repo is populated for chart {}", chart.name);
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match chart.populate_mirrors(config.mirrors.clone()) {
|
|
|
|
Ok(_) => {
|
|
|
|
info!("mirrors arepopulated for chart {}", chart.name)
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let chart_repo = match source::repo_from_chart(chart.clone()) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
2024-01-10 14:50:56 +00:00
|
|
|
let vars = match chart.variables {
|
|
|
|
Some(vars) => vars,
|
|
|
|
None => HashMap::new(),
|
|
|
|
};
|
|
|
|
match chart_repo.pull(workdir_path.clone(), vars) {
|
2024-01-10 11:33:05 +00:00
|
|
|
Ok(res) => {
|
|
|
|
info!(
|
|
|
|
"succesfully pulled chart {} into {}",
|
|
|
|
chart.name.clone(),
|
|
|
|
res.path,
|
|
|
|
);
|
|
|
|
if let Some(extensions) = chart.extensions.clone() {
|
|
|
|
for extension in extensions {
|
|
|
|
if let Err(err) = extension.apply(res.clone().path) {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(patches) = chart.patches.clone() {
|
|
|
|
for patch in patches {
|
|
|
|
if let Err(err) = patch.apply(res.clone().path) {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(init_git_patch) = args.init_git_patch.clone() {
|
|
|
|
if init_git_patch.contains(&chart.name) {
|
|
|
|
info!(
|
|
|
|
"init git patch mode is enabled, go to {} to make your changes",
|
|
|
|
res.path
|
|
|
|
);
|
|
|
|
match init_git_repo(res.path) {
|
|
|
|
Ok(_) => {
|
|
|
|
info!("not mirroring, because of the init git patch mode");
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(mirrors) = chart.mirror_objs.clone() {
|
|
|
|
for mirror_obj in mirrors {
|
|
|
|
match mirror::mirror_from_mirror_obj(mirror_obj.clone()) {
|
|
|
|
Ok(mirror) => {
|
|
|
|
match mirror.push(workdir_path.clone(), res.clone(), args.dry_run) {
|
|
|
|
Ok(_) => info!(
|
|
|
|
"mirrored {} to {}",
|
|
|
|
chart.name.clone(),
|
|
|
|
mirror_obj.name
|
|
|
|
),
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
error!("{}", err);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Populate charts
|
|
|
|
// Download helm charts from config
|
|
|
|
// If workdir is not provided, create a temporary di
|
|
|
|
}
|