diff --git a/src/cli/bootupctl.rs b/src/cli/bootupctl.rs index 7f2d7507..f462b2c8 100644 --- a/src/cli/bootupctl.rs +++ b/src/cli/bootupctl.rs @@ -49,10 +49,6 @@ impl CtlCommand { /// CLI sub-commands. #[derive(Debug, Parser)] pub enum CtlVerb { - // FIXME(lucab): drop this after refreshing - // https://github.com/coreos/fedora-coreos-config/pull/595 - #[clap(name = "backend", hide = true, subcommand)] - Backend(CtlBackend), #[clap(name = "status", about = "Show components status")] Status(StatusOpts), #[clap(name = "update", about = "Update all components")] @@ -61,6 +57,14 @@ pub enum CtlVerb { AdoptAndUpdate(AdoptAndUpdateOpts), #[clap(name = "validate", about = "Validate system state")] Validate, + /// Low-level commands for building and installing OS images + /// + /// These act on an OS tree or target root rather than on the running + /// system, and are intended for image build and installation tooling + /// (e.g. `bootc install` or disk image builders). To update the + /// bootloader of a booted system, use `update` or `adopt-and-update`. + #[clap(name = "backend", subcommand)] + Backend(super::bootupd::DVerb), #[clap( name = "migrate-static-grub-config", hide = true, @@ -69,17 +73,6 @@ pub enum CtlVerb { MigrateStaticGrubConfig, } -#[derive(Debug, Parser)] -pub enum CtlBackend { - #[clap(name = "generate-update-metadata", hide = true)] - Generate(super::bootupd::GenerateOpts), - #[clap(name = "install", hide = true)] - Install(super::bootupd::InstallOpts), - #[clap(hide = true)] - #[cfg(efi_arch)] - SetDefaultBootloader(super::bootupd::DefaultBootloaderOpts), -} - #[derive(Debug, Parser)] pub struct StatusOpts { /// If there are updates available, output `Updates available: ` to standard output; @@ -123,16 +116,7 @@ impl CtlCommand { CtlVerb::Update(opts) => Self::run_update(opts), CtlVerb::AdoptAndUpdate(opts) => Self::run_adopt_and_update(opts), CtlVerb::Validate => Self::run_validate(), - CtlVerb::Backend(CtlBackend::Generate(opts)) => { - super::bootupd::DCommand::run_generate_meta(opts) - } - CtlVerb::Backend(CtlBackend::Install(opts)) => { - super::bootupd::DCommand::run_install(opts) - } - #[cfg(efi_arch)] - CtlVerb::Backend(CtlBackend::SetDefaultBootloader(opts)) => { - super::bootupd::DCommand::set_default_bootloader(opts) - } + CtlVerb::Backend(verb) => verb.run(), CtlVerb::MigrateStaticGrubConfig => Self::run_migrate_static_grub_config(), } } diff --git a/src/cli/bootupd.rs b/src/cli/bootupd.rs index a9b8951b..4d57637f 100644 --- a/src/cli/bootupd.rs +++ b/src/cli/bootupd.rs @@ -36,10 +36,21 @@ impl DCommand { /// CLI sub-commands. #[derive(Debug, Parser)] pub enum DVerb { - #[clap(name = "generate-update-metadata", about = "Generate metadata")] + /// Generate update metadata from the bootloader files in an OS tree + /// + /// Run this at image build time. It records the bootloader component + /// versions (e.g. from the RPM database) under /usr/lib/bootupd/updates, + /// which `install` and `update` later use as their source. + #[clap(name = "generate-update-metadata")] GenerateUpdateMetadata(GenerateOpts), - #[clap(name = "install", about = "Install components")] + /// Install bootloader components to a target root + /// + /// Used when creating a disk image or installing a system: copies the + /// update payload from the source root into the target's ESP and/or + /// boot partition, and installs to the target block device(s) as needed. + #[clap(name = "install")] Install(InstallOpts), + /// Set the default bootloader on EFI systems #[cfg(efi_arch)] SetDefaultBootloader(DefaultBootloaderOpts), } @@ -94,7 +105,7 @@ pub(crate) struct InstallOpts { #[derive(Debug, Parser)] pub struct GenerateOpts { - /// Physical root mountpoint + /// Root of the OS tree (only `/` is currently supported) #[clap(value_parser)] sysroot: Option, } @@ -108,15 +119,22 @@ pub struct DefaultBootloaderOpts { pub(crate) bootloader: Bootloader, } +impl DVerb { + /// Run this verb; shared by `bootupd` and `bootupctl backend`. + pub(crate) fn run(self) -> Result<()> { + match self { + DVerb::Install(opts) => DCommand::run_install(opts), + DVerb::GenerateUpdateMetadata(opts) => DCommand::run_generate_meta(opts), + #[cfg(efi_arch)] + DVerb::SetDefaultBootloader(opts) => DCommand::set_default_bootloader(opts), + } + } +} + impl DCommand { /// Run CLI application. pub fn run(self) -> Result<()> { - match self.cmd { - DVerb::Install(opts) => Self::run_install(opts), - DVerb::GenerateUpdateMetadata(opts) => Self::run_generate_meta(opts), - #[cfg(efi_arch)] - DVerb::SetDefaultBootloader(opts) => Self::set_default_bootloader(opts), - } + self.cmd.run() } /// Runner for `generate-install-metadata` verb. diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 02212b56..6b505797 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -58,6 +58,23 @@ mod tests { bootupd::DCommand::command().debug_assert(); } + #[test] + fn backend_is_documented() { + use clap::CommandFactory; + let ctl = bootupctl::CtlCommand::command(); + let backend = ctl.find_subcommand("backend").unwrap(); + assert!(!backend.is_hide_set()); + assert!(backend.get_about().is_some()); + for verb in backend.get_subcommands() { + assert!(!verb.is_hide_set(), "{} is hidden", verb.get_name()); + assert!( + verb.get_about().is_some(), + "{} has no help", + verb.get_name() + ); + } + } + #[test] fn test_multicall_dispatch() { {