mirror of
https://github.com/CloudNebulaProject/zmgr.git
synced 2026-04-10 13:10:42 +00:00
Add --dry-run (-n) flag to create and destroy commands
Shows the exact dladm/zonecfg/zoneadm commands, IPAM allocation, and registry writes that would happen — without executing anything. Useful for validating template + pool config before committing to a zone install. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
abdce9c927
commit
5242450dd3
1 changed files with 70 additions and 7 deletions
77
src/main.rs
77
src/main.rs
|
|
@ -32,6 +32,10 @@ struct Cli {
|
|||
#[arg(long, default_value = "/etc/zmgr")]
|
||||
registry: String,
|
||||
|
||||
/// Show what would be done without executing system commands
|
||||
#[arg(long, short = 'n')]
|
||||
dry_run: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
|
@ -124,10 +128,14 @@ fn main() -> miette::Result<()> {
|
|||
let cli = Cli::parse();
|
||||
let registry = std::path::PathBuf::from(&cli.registry);
|
||||
|
||||
let dry_run = cli.dry_run;
|
||||
|
||||
match cli.command {
|
||||
Commands::Init { force } => cmd_init(®istry, force),
|
||||
Commands::Create { name, template } => cmd_create(®istry, &name, template.as_deref()),
|
||||
Commands::Destroy { name } => cmd_destroy(®istry, &name),
|
||||
Commands::Create { name, template } => {
|
||||
cmd_create(®istry, &name, template.as_deref(), dry_run)
|
||||
}
|
||||
Commands::Destroy { name } => cmd_destroy(®istry, &name, dry_run),
|
||||
Commands::List => cmd_list(®istry),
|
||||
Commands::Status { name } => cmd_status(®istry, name.as_deref()),
|
||||
Commands::Import { name } => cmd_import(®istry, name.as_deref()),
|
||||
|
|
@ -172,7 +180,12 @@ fn cmd_init(registry: &Path, force: bool) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_create(registry: &Path, name: &str, template_name: Option<&str>) -> Result<()> {
|
||||
fn cmd_create(
|
||||
registry: &Path,
|
||||
name: &str,
|
||||
template_name: Option<&str>,
|
||||
dry_run: bool,
|
||||
) -> Result<()> {
|
||||
config::ensure_initialized(registry)?;
|
||||
|
||||
if Zone::exists(registry, name) {
|
||||
|
|
@ -194,9 +207,6 @@ fn cmd_create(registry: &Path, name: &str, template_name: Option<&str>) -> Resul
|
|||
let address = format!("{ip}/{prefix_len}");
|
||||
let vnic = format!("{name}0");
|
||||
|
||||
// Create VNIC
|
||||
exec::dladm_create_vnic(&vnic, &pool.stub)?;
|
||||
|
||||
// Build zonecfg commands
|
||||
let autoboot = if tmpl.autoboot { "true" } else { "false" };
|
||||
let zonecfg_cmds = format!(
|
||||
|
|
@ -215,6 +225,40 @@ fn cmd_create(registry: &Path, name: &str, template_name: Option<&str>) -> Resul
|
|||
cfg.zonepath_prefix, tmpl.brand, tmpl.ip_type, pool.gateway
|
||||
);
|
||||
|
||||
if dry_run {
|
||||
println!("[dry-run] Would create zone '{name}'");
|
||||
println!();
|
||||
println!(" template: {tmpl_name}");
|
||||
println!(" brand: {}", tmpl.brand);
|
||||
println!(" address: {address}");
|
||||
println!(" vnic: {vnic} (on stub {})", pool.stub);
|
||||
println!(" gateway: {}", pool.gateway);
|
||||
println!(" zonepath: {}/{name}", cfg.zonepath_prefix);
|
||||
println!(" autoboot: {}", tmpl.autoboot);
|
||||
println!();
|
||||
println!("Commands that would be executed:");
|
||||
println!();
|
||||
println!(" dladm create-vnic -l {} {vnic}", pool.stub);
|
||||
println!();
|
||||
println!(" zonecfg -z {name} <<EOF");
|
||||
for line in zonecfg_cmds.lines() {
|
||||
println!(" {line}");
|
||||
}
|
||||
println!(" EOF");
|
||||
println!();
|
||||
println!(" zoneadm -z {name} install");
|
||||
if tmpl.autoboot {
|
||||
println!(" zoneadm -z {name} boot");
|
||||
}
|
||||
println!();
|
||||
println!("Registry entry that would be written:");
|
||||
println!(" {}/zones/{name}.kdl", registry.display());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Create VNIC
|
||||
exec::dladm_create_vnic(&vnic, &pool.stub)?;
|
||||
|
||||
exec::zonecfg_create(name, &zonecfg_cmds)?;
|
||||
exec::zoneadm_install(name)?;
|
||||
|
||||
|
|
@ -249,11 +293,30 @@ fn cmd_create(registry: &Path, name: &str, template_name: Option<&str>) -> Resul
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_destroy(registry: &Path, name: &str) -> Result<()> {
|
||||
fn cmd_destroy(registry: &Path, name: &str, dry_run: bool) -> Result<()> {
|
||||
config::ensure_initialized(registry)?;
|
||||
|
||||
let zone = Zone::load(registry, name)?;
|
||||
|
||||
if dry_run {
|
||||
println!("[dry-run] Would destroy zone '{name}'");
|
||||
println!();
|
||||
println!(" template: {}", zone.template);
|
||||
println!(" address: {}", zone.address);
|
||||
println!(" vnic: {}", zone.vnic);
|
||||
println!();
|
||||
println!("Commands that would be executed:");
|
||||
println!();
|
||||
println!(" zoneadm -z {name} halt");
|
||||
println!(" zoneadm -z {name} uninstall -F");
|
||||
println!(" zonecfg -z {name} delete -F");
|
||||
println!(" dladm delete-vnic {}", zone.vnic);
|
||||
println!();
|
||||
println!("Registry entry that would be removed:");
|
||||
println!(" {}/zones/{name}.kdl", registry.display());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Halt if running (ignore errors — zone may already be halted)
|
||||
let _ = exec::zoneadm_halt(name);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue