Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better CLI documentation #1269

Merged
merged 3 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions rust/agama-cli/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ const DEFAULT_FILE_MODE: u32 = 0o600;

#[derive(Subcommand, Debug)]
pub enum AuthCommands {
/// Authenticate with Agama's server and store the credentials
/// Authenticate with Agama's server and store the token.
///
/// It reads the password from the standard input. If it is not available,
/// it asks the user.
/// This command tries to get the password from the standard input. If it is not there, it asks
/// the user interactively. Upon successful login, it stores the token in .agama/agama-jwt. The
/// token will be automatically sent to authenticate the following requests.
Login,
/// Deauthenticate by removing the credentials
/// Deauthenticate by removing the token.
Logout,
/// Prints currently stored credentials to the standard output
/// Print the used token to the standard output.
Show,
}

Expand Down
67 changes: 50 additions & 17 deletions rust/agama-cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,69 @@ use clap::Subcommand;

#[derive(Subcommand, Debug)]
pub enum Commands {
/// Change or show installation settings
/// Change or show the installation settings.
///
/// You can set any Agama configuration value from the command-line. You can change individual
/// values the "add" or "set" commands. Or modify many of them at a time by loading a so-called
/// profile through the "load" command.
///
/// Use "show" to display the current configuration in JSON format.
#[command(subcommand)]
Config(ConfigCommands),

/// Display information about installation settings (e.g., possible values)
Info {
/// Configuration keys (e.g., software.products)
keys: Vec<String>,
},
/// Start probing
/// Analyze the system.
///
/// In Agama's jargon, the term 'probing' refers to the process of 'analyzing' the system. This
/// includes reading software repositories, analyzing storage devices, and more. The 'probe'
/// command initiates this analysis process and returns immediately.

/// TODO: do we really need a "probe" action?
Probe,
// Start Installation

/// Start the system installation.
///
/// This command starts the installation process. Beware it is a destructive operation because
/// it will set up the storage devices, install the packages, etc.
///
/// When the preconditions for the installation are not met, it informs the user and returns,
/// making no changes to the system.
Install,
/// Autoinstallation profile handling

/// Manage auto-installation profiles (retrieving, applying, etc.).
#[command(subcommand)]
Profile(ProfileCommands),
/// Configuration for questions that come from installer

/// Handle installer questions.
///
/// Questions are raised when an unexpected (by the user) situation happens in the installer:
/// like if an encrypted partition is detected and cannot be inspected,
/// if a repository is signed by an unknown GPG key, or if the installer is not sure
/// if multipath should be activated.
/// Agama might require user intervention at any time. The reasons include providing some
/// missing information (e.g., the password to decrypt a file system) or deciding what to do in
/// case of an error (e.g., cannot connect to the repository).
///
/// For more details see official agama documentation for Questions.
/// This command allows answering such questions directly from the command-line.
#[command(subcommand)]
Questions(QuestionsCommands),
/// Collects logs

/// Collect the installer logs.
///
/// The installer logs are stored in a compressed archive for further inspection. The file
/// includes system and Agama-specific logs and configuration files. They are crucial to
/// troubleshoot and debug problems.
#[command(subcommand)]
Logs(LogsCommands),
/// Request an action on the web server like Login / Logout

/// Authenticate with Agama's server.
///
/// Unless you are executing this program as root, you need to authenticate with Agama's server
/// for most operations. You can log in by specifying the root password through the "auth login"
/// command. Upon successful authentication, the server returns a JSON Web Token (JWT) which is
/// stored to authenticate the following requests.
///
/// If you run this program as root, you can skip the authentication step because it
/// automatically uses the master token at /run/agama/token. Only the root user must have access
/// to such a file.
///
/// You can logout at any time by using the "auth logout" command, although this command does
/// not affect the root user.
#[command(subcommand)]
Auth(AuthCommands),
}
27 changes: 20 additions & 7 deletions rust/agama-cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,29 @@ use std::{collections::HashMap, error::Error, io, str::FromStr};

#[derive(Subcommand, Debug)]
pub enum ConfigCommands {
/// Add an element to a collection
/// Add an element to a collection.
///
/// In case of collections, this command allows adding a new element. For instance, let's add a
/// new item to the list of software patterns:
///
/// $ agama config add software.patterns value=gnome
Add { key: String, values: Vec<String> },

/// Set one or many installation settings
Set {
/// key-value pairs (e.g., user.name="Jane Doe")
values: Vec<String>,
},
/// Shows the value of one or many configuration settings
///
/// For scalar values, this command allows setting a new value. For instance, let's change the
/// product to install:
///
/// $ agama config set product.id=Tumbleweed
Set { values: Vec<String> },

/// Shows the value of the configuration settings.
///
/// It is possible that many configuration settings do not have a value. Those settings
/// are not included in the output.
Show,
/// Loads the configuration from a JSON file

/// Loads the configuration from a JSON file.
Load { path: String },
}

Expand Down
8 changes: 4 additions & 4 deletions rust/agama-cli/src/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ use tempfile::TempDir;
// definition of "agama logs" subcommands, see clap crate for details
#[derive(Subcommand, Debug)]
pub enum LogsCommands {
/// Collects and stores logs in a tar archive
/// Collect and store the logs in a tar archive.
Store {
#[clap(long, short = 'v')]
/// Verbose output
verbose: bool,
#[clap(long, short = 'd')]
/// Path to destination directory. Optionally with the archive file name at the end.
/// An extension will be appended automatically depending on used compression.
/// Path to destination directory and, optionally, the archive file name. The extension will
/// be added automatically.
destination: Option<PathBuf>,
},
/// List logs which will be collected
/// List the logs to collect
List,
}

Expand Down
9 changes: 7 additions & 2 deletions rust/agama-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ use std::{
time::Duration,
};

/// Agama's command-line interface
///
/// This program allows inspecting or changing Agama's configuration, handling installation
/// profiles, starting the installation, monitoring the process, etc.
///
/// Please, use the "help" command to learn more.
#[derive(Parser)]
#[command(name = "agama", version, about, long_about = None)]
#[command(name = "agama", about, long_about, max_term_width = 100)]
struct Cli {
#[command(subcommand)]
pub command: Commands,
Expand Down Expand Up @@ -138,7 +144,6 @@ async fn run_command(cli: Cli) -> anyhow::Result<()> {
Commands::Questions(subcommand) => run_questions_cmd(subcommand).await,
Commands::Logs(subcommand) => run_logs_cmd(subcommand).await,
Commands::Auth(subcommand) => run_auth_cmd(subcommand).await,
_ => unimplemented!(),
}
}

Expand Down
18 changes: 9 additions & 9 deletions rust/agama-cli/src/questions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@ use clap::{Args, Subcommand, ValueEnum};

#[derive(Subcommand, Debug)]
pub enum QuestionsCommands {
/// Sets the mode for answering questions.
///
/// It allows to decide if questions will be interactive or
/// if they should not block installation.
/// Set the mode for answering questions.
Mode(ModesArgs),
/// Loads predefined answers to questions.

/// Load predefined answers.
///
/// It allows to predefine answers for certain questions to skip
/// them in interactive mode or change answer in automatic mode.
/// It allows predifining answers for specific questions in order to skip them in interactive
imobachgs marked this conversation as resolved.
Show resolved Hide resolved
/// mode or change the answer in automatic mode.
///
/// For more details and examples see official Agama documentation.
/// Please check Agama documentation for more details and examples:
/// https://github.com/openSUSE/agama/blob/master/doc/questions.md
Answers {
/// Local path to file with answers in YAML format
/// Path to a file containing the answers in YAML format.
path: String,
},
}
Expand All @@ -31,7 +29,9 @@ pub struct ModesArgs {

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum Modes {
/// Ask the user and block the installation.
Interactive,
/// Do not block the installation.
NonInteractive,
}

Expand Down