From 5d146dd235c43c0cbff8de96a91737301556e3ee Mon Sep 17 00:00:00 2001 From: Rain Date: Mon, 6 Nov 2023 09:39:12 -0800 Subject: [PATCH] [wicket] move cli-related code to its own directory (#4429) This code lives next to the "ui" and "state" directories. --- wicket/src/cli/command.rs | 55 +++++++++++++++++++ wicket/src/cli/mod.rs | 18 ++++++ wicket/src/{ => cli}/preflight.rs | 0 wicket/src/{ => cli}/rack_setup.rs | 0 .../{ => cli}/rack_setup/config_template.toml | 0 .../src/{ => cli}/rack_setup/config_toml.rs | 0 wicket/src/{ => cli}/upload.rs | 0 wicket/src/dispatch.rs | 40 +------------- wicket/src/lib.rs | 4 +- 9 files changed, 76 insertions(+), 41 deletions(-) create mode 100644 wicket/src/cli/command.rs create mode 100644 wicket/src/cli/mod.rs rename wicket/src/{ => cli}/preflight.rs (100%) rename wicket/src/{ => cli}/rack_setup.rs (100%) rename wicket/src/{ => cli}/rack_setup/config_template.toml (100%) rename wicket/src/{ => cli}/rack_setup/config_toml.rs (100%) rename wicket/src/{ => cli}/upload.rs (100%) diff --git a/wicket/src/cli/command.rs b/wicket/src/cli/command.rs new file mode 100644 index 0000000000..34f041b203 --- /dev/null +++ b/wicket/src/cli/command.rs @@ -0,0 +1,55 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Code that manages command dispatch from a shell for wicket. + +use std::net::SocketAddrV6; + +use anyhow::{Context, Result}; +use clap::Parser; + +use super::{ + preflight::PreflightArgs, rack_setup::SetupArgs, upload::UploadArgs, +}; + +pub fn exec( + log: slog::Logger, + args: &str, + wicketd_addr: SocketAddrV6, +) -> Result<()> { + // The argument is in a quoted form, so split it using Unix shell semantics. + let args = shell_words::split(&args).with_context(|| { + format!("could not parse shell arguments from input {args}") + })?; + + // parse_from uses the the first argument as the command name. Insert "wicket" as + // the command name. + let args = ShellCommand::parse_from( + std::iter::once("wicket".to_owned()).chain(args), + ); + match args { + ShellCommand::UploadRepo(args) => args.exec(log, wicketd_addr), + ShellCommand::Setup(args) => args.exec(log, wicketd_addr), + ShellCommand::Preflight(args) => args.exec(log, wicketd_addr), + } +} + +/// Arguments passed to wicket. +/// +/// Wicket is designed to be used as a captive shell, set up via sshd +/// ForceCommand. If no arguments are specified, wicket behaves like a TUI. +/// However, if arguments are specified via SSH_ORIGINAL_COMMAND, wicketd +/// accepts an upload command. +#[derive(Debug, Parser)] +enum ShellCommand { + /// Upload a TUF repository to wicketd. + #[command(visible_alias = "upload")] + UploadRepo(UploadArgs), + /// Interact with rack setup configuration. + #[command(subcommand)] + Setup(SetupArgs), + /// Run checks prior to setting up the rack. + #[command(subcommand)] + Preflight(PreflightArgs), +} diff --git a/wicket/src/cli/mod.rs b/wicket/src/cli/mod.rs new file mode 100644 index 0000000000..7e8f6540ea --- /dev/null +++ b/wicket/src/cli/mod.rs @@ -0,0 +1,18 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// Copyright 2023 Oxide Computer Company + +//! Command-line interface to wicket. +//! +//! By default, the main interface to wicket is via a TUI. However, some +//! commands and use cases must be done via the CLI, and this module contains +//! support for that. + +mod command; +mod preflight; +mod rack_setup; +mod upload; + +pub use command::exec; diff --git a/wicket/src/preflight.rs b/wicket/src/cli/preflight.rs similarity index 100% rename from wicket/src/preflight.rs rename to wicket/src/cli/preflight.rs diff --git a/wicket/src/rack_setup.rs b/wicket/src/cli/rack_setup.rs similarity index 100% rename from wicket/src/rack_setup.rs rename to wicket/src/cli/rack_setup.rs diff --git a/wicket/src/rack_setup/config_template.toml b/wicket/src/cli/rack_setup/config_template.toml similarity index 100% rename from wicket/src/rack_setup/config_template.toml rename to wicket/src/cli/rack_setup/config_template.toml diff --git a/wicket/src/rack_setup/config_toml.rs b/wicket/src/cli/rack_setup/config_toml.rs similarity index 100% rename from wicket/src/rack_setup/config_toml.rs rename to wicket/src/cli/rack_setup/config_toml.rs diff --git a/wicket/src/upload.rs b/wicket/src/cli/upload.rs similarity index 100% rename from wicket/src/upload.rs rename to wicket/src/cli/upload.rs diff --git a/wicket/src/dispatch.rs b/wicket/src/dispatch.rs index e8191f59cb..3ef04ee302 100644 --- a/wicket/src/dispatch.rs +++ b/wicket/src/dispatch.rs @@ -8,13 +8,10 @@ use std::net::{Ipv6Addr, SocketAddrV6}; use anyhow::{bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; -use clap::Parser; use omicron_common::{address::WICKETD_PORT, FileKv}; use slog::Drain; -use crate::{ - preflight::PreflightArgs, rack_setup::SetupArgs, upload::UploadArgs, Runner, -}; +use crate::Runner; pub fn exec() -> Result<()> { let wicketd_addr = @@ -22,22 +19,8 @@ pub fn exec() -> Result<()> { // SSH_ORIGINAL_COMMAND contains additional arguments, if any. if let Ok(ssh_args) = std::env::var("SSH_ORIGINAL_COMMAND") { - // The argument is in a quoted form, so split it using Unix shell semantics. - let args = shell_words::split(&ssh_args).with_context(|| { - format!("could not parse shell arguments from input {ssh_args}") - })?; - let log = setup_log(&log_path()?, WithStderr::Yes)?; - // parse_from uses the the first argument as the command name. Insert "wicket" as - // the command name. - let args = ShellCommand::parse_from( - std::iter::once("wicket".to_owned()).chain(args), - ); - match args { - ShellCommand::UploadRepo(args) => args.exec(log, wicketd_addr), - ShellCommand::Setup(args) => args.exec(log, wicketd_addr), - ShellCommand::Preflight(args) => args.exec(log, wicketd_addr), - } + crate::cli::exec(log, &ssh_args, wicketd_addr) } else { // Do not expose log messages via standard error since they'll show up // on top of the TUI. @@ -46,25 +29,6 @@ pub fn exec() -> Result<()> { } } -/// Arguments passed to wicket. -/// -/// Wicket is designed to be used as a captive shell, set up via sshd -/// ForceCommand. If no arguments are specified, wicket behaves like a TUI. -/// However, if arguments are specified via SSH_ORIGINAL_COMMAND, wicketd -/// accepts an upload command. -#[derive(Debug, Parser)] -enum ShellCommand { - /// Upload a TUF repository to wicketd. - #[command(visible_alias = "upload")] - UploadRepo(UploadArgs), - /// Interact with rack setup configuration. - #[command(subcommand)] - Setup(SetupArgs), - /// Run checks prior to setting up the rack. - #[command(subcommand)] - Preflight(PreflightArgs), -} - fn setup_log( path: &Utf8Path, with_stderr: WithStderr, diff --git a/wicket/src/lib.rs b/wicket/src/lib.rs index a16ef2a3e1..6e760968f8 100644 --- a/wicket/src/lib.rs +++ b/wicket/src/lib.rs @@ -7,15 +7,13 @@ use std::time::Duration; +mod cli; mod dispatch; mod events; mod keymap; -mod preflight; -mod rack_setup; mod runner; mod state; mod ui; -mod upload; mod wicketd; pub const TICK_INTERVAL: Duration = Duration::from_millis(30);