refactor!: initial commit, setup cli

This commit is contained in:
2026-01-23 22:30:14 -08:00
parent 58ead2bb23
commit 80ae32d799
27 changed files with 1110 additions and 772 deletions

View File

@@ -0,0 +1,15 @@
[package]
name = "homelab-cli"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.100"
clap = { version = "4.5.54", features = ["derive"] }
dialoguer = "0.12.0"
k8s-openapi = { version = "0.27.0", features = ["latest", "schemars", "v1_35"] }
kube = { version = "3.0.0", features = ["runtime", "derive"] }
schemars = "1.2.0"
thiserror = "2.0.18"
thiserror-ext = "0.3.0"
tokio = { version = "1.49.0", features = ["macros", "rt"] }

View File

@@ -0,0 +1,29 @@
use clap::{Args, Subcommand};
use kube::Api;
use crate::{AppState, State};
#[derive(Debug, Args)]
pub struct MinecraftCommand {
#[command(subcommand)]
command: MinecraftSubcommand,
}
#[derive(Debug, Subcommand)]
enum MinecraftSubcommand {
Backup {
/// the world to backup
#[arg(short, long)]
world: String,
},
}
impl MinecraftCommand {
pub async fn run(&self, app_state: State) {
match &self.command {
MinecraftSubcommand::Backup { world } => backup_world(app_state, &world),
}
}
}
pub fn backup_world(app_state: State, world: &str) {}

View File

@@ -0,0 +1,8 @@
use clap::Subcommand;
mod minecraft;
#[derive(Subcommand, Debug)]
pub enum Commands {
/// minecraft management
Minecraft(minecraft::MinecraftCommand),
}

View File

@@ -0,0 +1,10 @@
use thiserror::Error;
#[derive(Error, Debug, thiserror_ext::Box)]
#[thiserror_ext(newtype(name = Error))]
pub enum ErrorKind {
#[error("kube error: {0}")]
Kube(#[from] kube::Error),
}
pub type Result<T> = core::result::Result<T, Error>;

View File

@@ -0,0 +1,56 @@
mod commands;
mod error;
use std::{ops::Deref, sync::Arc};
use clap::{CommandFactory, Parser};
use crate::{commands::Commands, error::Result};
#[derive(Parser, Debug)]
#[command(version, long_about = "homelab cli")]
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
}
struct AppState {
client: kube::Client,
}
#[derive(Clone)]
struct State(Arc<AppState>);
impl State {
pub fn new(inner: AppState) -> Self {
Self(Arc::new(inner))
}
}
impl Deref for State {
type Target = AppState;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AppState {
pub async fn new() -> Result<Self> {
Ok(Self {
client: kube::Client::try_default().await?,
})
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
let app_state = State::new(AppState::new().await?);
match cli.command {
Some(Commands::Minecraft(cmd)) => cmd.run(app_state.clone()).await,
_ => Cli::command().print_long_help()?,
};
Ok(())
}