mod commands;
mod observability;
mod rootpath;
mod workload;
use anyhow::{Context, Result};
use clap::{Args, CommandFactory, Parser, Subcommand};
use libcontainer::syscall::syscall::create_syscall;
use liboci_cli::{CommonCmd, GlobalOpts, StandardCmd};
use crate::commands::info;
#[derive(Args, Debug)]
struct YoukiExtendOpts {
#[arg(long)]
pub systemd_log: bool,
#[arg(long)]
pub log_level: Option<String>,
}
#[derive(Parser, Debug)]
#[command(author = env!("CARGO_PKG_AUTHORS"))]
#[command(version, disable_version_flag = true)]
struct Opts {
#[command(flatten)]
global: GlobalOpts,
#[command(flatten)]
youki_extend: YoukiExtendOpts,
#[command(subcommand)]
subcmd: Option<YoukiSubCommand>,
#[arg(short, long)]
version: bool,
}
#[derive(Subcommand, Debug)]
enum YoukiSubCommand {
#[command(flatten)]
Standard(Box<liboci_cli::StandardCmd>),
#[command(flatten)]
Common(Box<liboci_cli::CommonCmd>),
Info(info::Info),
Completion(commands::completion::Completion),
}
fn main() -> Result<()> {
pentacle::ensure_sealed().context("failed to seal /proc/self/exe")?;
let opts = Opts::parse();
if opts.version {
info::print_youki();
return Ok(());
}
let mut app = Opts::command();
let syscall = create_syscall();
observability::init(&opts).map_err(|err| {
eprintln!("failed to initialize observability: {}", err);
err
})?;
tracing::debug!(
"started by user {} with {:?}",
syscall.get_euid(),
std::env::args_os()
);
let root_path = rootpath::determine(opts.global.root, &*syscall)?;
let systemd_cgroup = opts.global.systemd_cgroup;
let cmd_result = match opts.subcmd {
Some(YoukiSubCommand::Standard(cmd)) => match *cmd {
StandardCmd::Create(create) => {
commands::create::create(create, root_path, systemd_cgroup)
}
StandardCmd::Start(start) => commands::start::start(start, root_path),
StandardCmd::Kill(kill) => commands::kill::kill(kill, root_path),
StandardCmd::Delete(delete) => commands::delete::delete(delete, root_path),
StandardCmd::State(state) => commands::state::state(state, root_path),
},
Some(YoukiSubCommand::Common(cmd)) => match *cmd {
CommonCmd::Checkpointt(checkpoint) => {
commands::checkpoint::checkpoint(checkpoint, root_path)
}
CommonCmd::Events(events) => commands::events::events(events, root_path),
CommonCmd::Exec(exec) => match commands::exec::exec(exec, root_path) {
Ok(exit_code) => std::process::exit(exit_code),
Err(e) => {
tracing::error!("error in executing command: {:?}", e);
std::process::exit(-1);
}
},
CommonCmd::Features(features) => commands::features::features(features),
CommonCmd::List(list) => commands::list::list(list, root_path),
CommonCmd::Pause(pause) => commands::pause::pause(pause, root_path),
CommonCmd::Ps(ps) => commands::ps::ps(ps, root_path),
CommonCmd::Resume(resume) => commands::resume::resume(resume, root_path),
CommonCmd::Run(run) => match commands::run::run(run, root_path, systemd_cgroup) {
Ok(exit_code) => std::process::exit(exit_code),
Err(e) => {
tracing::error!("error in executing command: {:?}", e);
std::process::exit(-1);
}
},
CommonCmd::Spec(spec) => commands::spec_json::spec(spec, &*syscall),
CommonCmd::Update(update) => commands::update::update(update, root_path),
},
Some(YoukiSubCommand::Info(info)) => commands::info::info(info),
Some(YoukiSubCommand::Completion(completion)) => {
commands::completion::completion(completion, &mut app)
}
None => app
.print_help()
.map_err(|e| anyhow::anyhow!("failed to print help: {e}")),
};
if let Err(ref e) = cmd_result {
tracing::error!("error in executing command: {:?}", e);
}
cmd_result
}