use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use std::{
fs,
io::{self, Read},
path::{Path, PathBuf},
};
use tabled::Table;
#[derive(Parser)]
#[command(author, version, about)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Install {
file: Option<PathBuf>,
#[arg(long, required = true)]
set: String,
},
List,
Delete {
name: String,
},
}
fn process_jsonnet_file(path: &PathBuf) -> Result<String> {
let content = fs::read_to_string(path)
.with_context(|| format!("Failed to read file: {}", path.display()))?;
let import_paths = if let Some(parent) = path.parent() {
vec![parent.to_path_buf()]
} else {
vec![]
};
nethermit::jsonnet_to_yaml(&content, &import_paths)
}
fn process_stdin() -> Result<String> {
let mut buffer = String::new();
io::stdin()
.read_to_string(&mut buffer)
.context("Failed to read from stdin")?;
let import_paths = vec![PathBuf::from(".")];
nethermit::jsonnet_to_yaml(&buffer, &import_paths)
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
let client = nethermit::RealKubeClient::new().await?;
match cli.command {
Commands::Install { file, set } => {
if nethermit::set_exists(&client, &set).await? {
return Err(anyhow::anyhow!(
"{}",
nethermit::format_error(&format!("Set '{}' already exists", set))
));
}
let yaml = match file {
Some(ref path) if path == Path::new("-") => process_stdin()?,
Some(ref path) => process_jsonnet_file(path)?,
None => process_stdin()?,
};
println!(
"{}",
nethermit::format_info("Generated YAML configuration:")
);
println!("{yaml}");
println!(
"{}",
nethermit::format_info("Applying configuration to Kubernetes cluster...")
);
let pb = nethermit::create_spinner("Installing resources");
nethermit::apply_kubernetes(&yaml, Some(&set)).await?;
pb.finish_with_message(nethermit::format_success(&format!(
"Successfully installed set '{}'",
set
)));
}
Commands::List => {
let sets = nethermit::list_sets_info(&client).await?;
if sets.is_empty() {
println!("{}", nethermit::format_info("No sets installed"));
} else {
println!("{}", nethermit::format_info("Installed sets:"));
let table = Table::new(sets).to_string();
println!("{table}");
}
}
Commands::Delete { name } => {
let pb = nethermit::create_spinner(&format!("Deleting resources for set '{}'", name));
match nethermit::delete_set_resources(&client, &name).await {
Ok(_) => {
pb.finish_with_message(nethermit::format_success(&format!(
"Successfully deleted set '{}'",
name
)));
}
Err(e) => {
pb.finish_with_message(nethermit::format_error(&format!(
"Failed to delete set '{}': {}",
name, e
)));
return Err(e);
}
}
}
}
Ok(())
}