diff --git a/src/tools/kata-ctl/src/args.rs b/src/tools/kata-ctl/src/args.rs index 38a9c50b85..14318772bf 100644 --- a/src/tools/kata-ctl/src/args.rs +++ b/src/tools/kata-ctl/src/args.rs @@ -10,10 +10,15 @@ use clap::{Args, Parser, Subcommand, ValueEnum}; use thiserror::Error; #[derive(Parser, Debug)] -#[clap(name = "kata-ctl", author, about = "Kata Containers control tool")] +#[clap( + name = "kata-ctl", + author, + about = "Kata Containers control tool", + arg_required_else_help = true +)] pub struct KataCtlCli { #[clap(subcommand)] - pub command: Commands, + pub command: Option, #[clap(short, long, value_enum, value_parser = parse_log_level)] /// Sets the minimum log level required for log messages to be displayed. Default is 'info'. /// Valid values are: trace, debug, info, warning, error, critical @@ -21,6 +26,10 @@ pub struct KataCtlCli { #[clap(short, long, action)] /// If enabled, log messages will be JSON formatted for easier machine parsing pub json_logging: bool, + + /// If specified, display a list of config file locations. + #[clap(long, action)] + pub show_default_config_paths: bool, } fn parse_log_level(arg: &str) -> Result { diff --git a/src/tools/kata-ctl/src/main.rs b/src/tools/kata-ctl/src/main.rs index 2d2476eca2..55bf02a92b 100644 --- a/src/tools/kata-ctl/src/main.rs +++ b/src/tools/kata-ctl/src/main.rs @@ -20,12 +20,12 @@ mod utils; use crate::log_parser::log_parser; use anyhow::Result; -use clap::{crate_name, Parser}; +use args::{Commands, KataCtlCli}; +use clap::{crate_name, CommandFactory, Parser}; +use kata_types::config::TomlConfig; use std::io; use std::process::exit; -use args::{Commands, KataCtlCli}; - use ops::check_ops::{ handle_check, handle_factory, handle_iptables, handle_metrics, handle_monitor, handle_version, }; @@ -43,6 +43,14 @@ macro_rules! sl { fn real_main() -> Result<()> { let args = KataCtlCli::parse(); + if args.show_default_config_paths { + TomlConfig::get_default_config_file_list() + .iter() + .for_each(|p| println!("{}", p.display())); + + return Ok(()); + } + let log_level = args.log_level.unwrap_or(slog::Level::Info); let (logger, _guard) = if args.json_logging { @@ -53,17 +61,35 @@ fn real_main() -> Result<()> { let _guard = slog_scope::set_global_logger(logger); - let res = match args.command { - Commands::Check(args) => handle_check(args), - Commands::DirectVolume(args) => handle_direct_volume(args), - Commands::Exec(args) => handle_exec(args), - Commands::Env(args) => handle_env(args), - Commands::Factory => handle_factory(), - Commands::Iptables(args) => handle_iptables(args), - Commands::Metrics(args) => handle_metrics(args), - Commands::Monitor(args) => handle_monitor(args), - Commands::Version => handle_version(), - Commands::LogParser(args) => log_parser(args), + let res = if let Some(command) = args.command { + match command { + Commands::Check(args) => handle_check(args), + Commands::DirectVolume(args) => handle_direct_volume(args), + Commands::Exec(args) => handle_exec(args), + Commands::Env(args) => handle_env(args), + Commands::Factory => handle_factory(), + Commands::Iptables(args) => handle_iptables(args), + Commands::Metrics(args) => handle_metrics(args), + Commands::Monitor(args) => handle_monitor(args), + Commands::Version => handle_version(), + Commands::LogParser(args) => log_parser(args), + } + } else { + // The user specified an option, but not a subcommand. We've already + // handled show_default_config_paths, so this is an invalid CLI hence + // display usage and exit. + + let help = KataCtlCli::command().render_help().to_string(); + + eprintln!("ERROR: need command"); + + eprintln!("{help}"); + + // We need to exit here rather than returning an error to match clap's + // standard behaviour. + // + // Note: the return value matches the clap-internal USAGE_CODE. + exit(2); }; // Log errors here, then let the logger go out of scope in main() to ensure