mod cli; use std::process::Command; use clap::{CommandFactory, Parser}; use clap_complete::{Shell, generate as generate_complete}; use crete::cluster::Cluster; use crete::environment::PathEnvironment; use crete::tftp::ServerError; use crete::{get_configs_path, get_repo_path, set_repo_path, tftp}; use minijinja::context; use thiserror::Error; use crate::cli::{Cli, Commands, GlobalOpts}; #[derive(Debug, Error)] enum Error { #[error("No clusters where found")] NoClustersFound, #[error("Server error: {0}")] Server(#[from] ServerError), } fn run_command(mut command: Command) { let output = command.output().unwrap(); if !output.stdout.is_empty() { println!("{}", String::from_utf8_lossy(&output.stdout).trim_end()); } if !output.stderr.is_empty() { println!("{}", String::from_utf8_lossy(&output.stderr).trim_end()); } } fn generate(opts: &GlobalOpts) -> Result<(), Error> { set_repo_path(&opts.repo); let clusters = Cluster::get_all(); if clusters.is_empty() { return Err(Error::NoClustersFound); } let path = opts.repo.join("rendered"); if path.exists() { std::fs::remove_dir_all(&path).unwrap(); } std::fs::create_dir(&path).unwrap(); // Render templates let template_env = PathEnvironment::new(&get_repo_path().join("templates")); for template_name in &template_env { let template = template_env.get_template(&template_name).unwrap(); let content = template .render(context! { clusters, root => opts.repo }) .unwrap(); std::fs::write(path.join(template_name), content).unwrap(); } // Remove existing config files and create output directory let path = get_configs_path(); if path.exists() { std::fs::remove_dir_all(&path).unwrap(); } std::fs::create_dir(&path).unwrap(); // Generate config files for cluster in clusters { for node in cluster.nodes() { run_command(node.talosctl_gen_config_command(&cluster)); } run_command(cluster.talosctl_gen_config_command()); run_command(cluster.talosctl_add_endpoint_command()); run_command(cluster.talosctl_merge_command()); } Ok(()) } #[tokio::main] async fn main() -> Result<(), Error> { let cli = Cli::parse(); match cli.command { Commands::Generate => generate(&cli.global_opts)?, Commands::ShellCompletions => generate_complete( Shell::from_env().unwrap_or(Shell::Bash), &mut Cli::command(), "crete", &mut std::io::stdout(), ), Commands::Serve => { tftp::serve(|filename| match filename { "ipxe.pxe" => Some(include_bytes!("../bin/ipxe.pxe").into()), "test" => Some(vec![1, 2, 3, 4]), _ => None, }) .await? } }; Ok(()) }