use clap::Parser;
use clap::Subcommand;
use scuffle::Scf;
use scuffle::SmfDegradeFlags;
use scuffle::SmfEnableDisableFlags;
use scuffle::SmfMaintainFlags;
#[derive(Parser)]
#[command(about = "Control the SMF state of an instance")]
struct Args {
#[arg(long, short)]
zone: Option<String>,
fmri: String,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
Enable(EnableDisableArgs),
Disable(EnableDisableArgs),
Refresh,
Restart,
Maintain(MaintainArgs),
Degrade(DegradeArgs),
Restore,
State,
}
#[derive(clap::Args)]
struct EnableDisableArgs {
#[arg(short = 't', long, conflicts_with = "at_next_boot")]
temporary: bool,
#[arg(short = 'n', long)]
at_next_boot: bool,
#[arg(short = 'c', long)]
comment: Option<String>,
}
impl EnableDisableArgs {
fn to_flags(&self) -> Option<SmfEnableDisableFlags> {
if self.temporary {
Some(SmfEnableDisableFlags::Temporary)
} else if self.at_next_boot {
Some(SmfEnableDisableFlags::AtNextBoot)
} else {
None
}
}
}
#[derive(clap::Args)]
struct MaintainArgs {
#[arg(short = 'i', long)]
immediate: bool,
#[arg(short = 't', long)]
temporary: bool,
}
impl MaintainArgs {
fn to_flags(&self) -> Option<SmfMaintainFlags> {
let mut flags = SmfMaintainFlags::empty();
if self.immediate {
flags |= SmfMaintainFlags::Immediate;
}
if self.temporary {
flags |= SmfMaintainFlags::Temporary;
}
(!flags.is_empty()).then_some(flags)
}
}
#[derive(clap::Args)]
struct DegradeArgs {
#[arg(short = 'i', long)]
immediate: bool,
}
impl DegradeArgs {
fn to_flags(&self) -> Option<SmfDegradeFlags> {
self.immediate.then_some(SmfDegradeFlags::Immediate)
}
}
fn main() -> anyhow::Result<()> {
let args = Args::parse();
let scf = match args.zone.as_deref() {
Some(z) => Scf::connect_zone(z),
None => Scf::connect_current_zone(),
}?;
let mut instance = scf.instance_from_fmri(&args.fmri)?;
let fmri = instance.fmri().to_string();
match args.command {
Command::Enable(opts) => {
instance.smf_enable(opts.to_flags(), opts.comment.as_deref())?;
println!("enabled {fmri}");
}
Command::Disable(opts) => {
instance.smf_disable(opts.to_flags(), opts.comment.as_deref())?;
println!("disabled {fmri}");
}
Command::Refresh => {
instance.smf_refresh()?;
println!("refreshed {fmri}");
}
Command::Restart => {
instance.smf_restart()?;
println!("restarted {fmri}");
}
Command::Maintain(opts) => {
instance.smf_maintain(opts.to_flags())?;
println!("marked {fmri} as maintenance");
}
Command::Degrade(opts) => {
instance.smf_degrade(opts.to_flags())?;
println!("marked {fmri} as degraded");
}
Command::Restore => {
instance.smf_restore()?;
println!("restored {fmri}");
}
Command::State => {
println!("{}", instance.smf_state()?);
}
}
Ok(())
}