diff --git a/Cargo.lock b/Cargo.lock index 476cf5448b..8b4915bbc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5054,18 +5054,25 @@ dependencies = [ "clap 4.4.3", "diesel", "dropshot", + "expectorate", "humantime", "nexus-client 0.1.0", "nexus-db-model", "nexus-db-queries", + "nexus-test-utils", + "nexus-test-utils-macros", "nexus-types", "omicron-common 0.1.0", + "omicron-nexus", "omicron-rpaths", + "omicron-test-utils", "pq-sys", + "regex", "serde", "serde_json", "slog", "strum", + "subprocess", "tabled", "textwrap 0.16.0", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 132fa55632..65caa502f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -154,7 +154,7 @@ chacha20poly1305 = "0.10.1" ciborium = "0.2.1" cfg-if = "1.0" chrono = { version = "0.4", features = [ "serde" ] } -clap = { version = "4.4", features = ["derive", "env"] } +clap = { version = "4.4", features = ["derive", "env", "wrap_help"] } cookie = "0.16" criterion = { version = "0.5.1", features = [ "async_tokio" ] } crossbeam = "0.8" diff --git a/omdb/Cargo.toml b/omdb/Cargo.toml index 0be0bdce6f..4b3ecd6e0e 100644 --- a/omdb/Cargo.toml +++ b/omdb/Cargo.toml @@ -31,6 +31,15 @@ textwrap.workspace = true tokio = { workspace = true, features = [ "full" ] } uuid.workspace = true +[dev-dependencies] +expectorate.workspace = true +nexus-test-utils.workspace = true +nexus-test-utils-macros.workspace = true +omicron-nexus.workspace = true +omicron-test-utils.workspace = true +regex.workspace = true +subprocess.workspace = true + # Disable doc builds by default for our binaries to work around issue # rust-lang/cargo#8373. These docs would not be very useful anyway. [[bin]] diff --git a/omdb/src/bin/omdb/db.rs b/omdb/src/bin/omdb/db.rs index e9f1911375..0ebf16d46b 100644 --- a/omdb/src/bin/omdb/db.rs +++ b/omdb/src/bin/omdb/db.rs @@ -210,7 +210,7 @@ async fn check_schema_version(datastore: &DataStore) { Ok(found_version) => { if found_version == expected_version { eprintln!( - "note: databaase schema version matches expected ({})", + "note: database schema version matches expected ({})", expected_version ); return; diff --git a/omdb/src/bin/omdb/nexus.rs b/omdb/src/bin/omdb/nexus.rs index 0d59b28142..704abf4af3 100644 --- a/omdb/src/bin/omdb/nexus.rs +++ b/omdb/src/bin/omdb/nexus.rs @@ -34,17 +34,17 @@ pub struct NexusArgs { #[derive(Debug, Subcommand)] enum NexusCommands { /// print information about background tasks - BackgroundTask(BackgroundTaskArgs), + BackgroundTasks(BackgroundTasksArgs), } #[derive(Debug, Args)] -struct BackgroundTaskArgs { +struct BackgroundTasksArgs { #[command(subcommand)] - command: BackgroundTaskCommands, + command: BackgroundTasksCommands, } #[derive(Debug, Subcommand)] -enum BackgroundTaskCommands { +enum BackgroundTasksCommands { /// Show documentation about background tasks Doc, /// Print a summary of the status of all background tasks @@ -70,26 +70,27 @@ impl NexusArgs { let client = nexus_client::Client::new(nexus_url, log.clone()); match &self.command { - NexusCommands::BackgroundTask(BackgroundTaskArgs { - command: BackgroundTaskCommands::Doc, - }) => cmd_nexus_background_task_doc(&client).await, - NexusCommands::BackgroundTask(BackgroundTaskArgs { - command: BackgroundTaskCommands::List, - }) => cmd_nexus_background_task_list(&client).await, - NexusCommands::BackgroundTask(BackgroundTaskArgs { - command: BackgroundTaskCommands::Show, - }) => cmd_nexus_background_task_show(&client).await, + NexusCommands::BackgroundTasks(BackgroundTasksArgs { + command: BackgroundTasksCommands::Doc, + }) => cmd_nexus_background_tasks_doc(&client).await, + NexusCommands::BackgroundTasks(BackgroundTasksArgs { + command: BackgroundTasksCommands::List, + }) => cmd_nexus_background_tasks_list(&client).await, + NexusCommands::BackgroundTasks(BackgroundTasksArgs { + command: BackgroundTasksCommands::Show, + }) => cmd_nexus_background_tasks_show(&client).await, } } } -/// Runs `omdb nexus background-task doc` -async fn cmd_nexus_background_task_doc( +/// Runs `omdb nexus background-tasks doc` +async fn cmd_nexus_background_tasks_doc( client: &nexus_client::Client, ) -> Result<(), anyhow::Error> { let response = client.bgtask_list().await.context("listing background tasks")?; let tasks = response.into_inner(); + let tasks: BTreeMap<_, _> = tasks.into_iter().collect(); for (_, bgtask) in &tasks { println!("task: {:?}", bgtask.name); println!( @@ -108,8 +109,8 @@ async fn cmd_nexus_background_task_doc( Ok(()) } -/// Runs `omdb nexus background-task list` -async fn cmd_nexus_background_task_list( +/// Runs `omdb nexus background-tasks list` +async fn cmd_nexus_background_tasks_list( client: &nexus_client::Client, ) -> Result<(), anyhow::Error> { let response = @@ -124,8 +125,8 @@ async fn cmd_nexus_background_task_list( Ok(()) } -/// Runs `omdb nexus background-task show` -async fn cmd_nexus_background_task_show( +/// Runs `omdb nexus background-tasks show` +async fn cmd_nexus_background_tasks_show( client: &nexus_client::Client, ) -> Result<(), anyhow::Error> { let response = diff --git a/omdb/tests/config.test.toml b/omdb/tests/config.test.toml new file mode 120000 index 0000000000..9a42a12b61 --- /dev/null +++ b/omdb/tests/config.test.toml @@ -0,0 +1 @@ +../../nexus/tests/config.test.toml \ No newline at end of file diff --git a/omdb/tests/env.out b/omdb/tests/env.out new file mode 100644 index 0000000000..237743be93 --- /dev/null +++ b/omdb/tests/env.out @@ -0,0 +1,74 @@ +EXECUTING COMMAND: omdb ["db", "--db-url", "postgresql://root@[::1]:REDACTED_PORT/omicron?sslmode=disable", "sleds"] +termination: Exited(0) +--------------------------------------------- +stdout: +SERIAL IP ROLE ID +sim-b6d65341 [::1]:REDACTED_PORT - REDACTED_UUID_REDACTED_UUID_REDACTED +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["db", "--db-url", "junk", "sleds"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +error: invalid value 'junk' for '--db-url ': invalid connection string: unexpected EOF + +For more information, try '--help'. +============================================= +EXECUTING COMMAND: omdb ["nexus", "--nexus-internal-url", "http://127.0.0.1:REDACTED_PORT", "background-tasks", "doc"] +termination: Exited(0) +--------------------------------------------- +stdout: +task: "dns_config_external" + watches external DNS data stored in CockroachDB + + +task: "dns_config_internal" + watches internal DNS data stored in CockroachDB + + +task: "dns_propagation_external" + propagates latest external DNS configuration (from "dns_config_external" + background task) to the latest list of DNS servers (from + "dns_servers_external" background task) + + +task: "dns_propagation_internal" + propagates latest internal DNS configuration (from "dns_config_internal" + background task) to the latest list of DNS servers (from + "dns_servers_internal" background task) + + +task: "dns_servers_external" + watches list of external DNS servers stored in CockroachDB + + +task: "dns_servers_internal" + watches list of internal DNS servers stored in CockroachDB + + +task: "external_endpoints" + reads config for silos and TLS certificates to determine the right set of + HTTP endpoints, their HTTP server names, and which TLS certificates to use + on each one + + +--------------------------------------------- +stderr: +============================================= +EXECUTING COMMAND: omdb ["nexus", "--nexus-internal-url", "junk", "background-tasks", "doc"] +termination: Exited(1) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Error: listing background tasks + +Caused by: + 0: Communication Error: builder error: relative URL without a base + 1: builder error: relative URL without a base + 2: relative URL without a base +============================================= diff --git a/omdb/tests/successes.out b/omdb/tests/successes.out new file mode 100644 index 0000000000..90e399f246 --- /dev/null +++ b/omdb/tests/successes.out @@ -0,0 +1,201 @@ +EXECUTING COMMAND: omdb ["db", "dns", "show"] +termination: Exited(0) +--------------------------------------------- +stdout: +GROUP ZONE ver UPDATED REASON +internal control-plane.oxide.internal 1 rack setup +external oxide-dev.test 2 create silo: "test-suite-silo" +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["db", "dns", "diff", "external", "2"] +termination: Exited(0) +--------------------------------------------- +stdout: +DNS zone: oxide-dev.test (External) +requested version: 2 (created at ) +version created by Nexus: REDACTED_UUID_REDACTED_UUID_REDACTED +version created because: create silo: "test-suite-silo" +changes: names added: 1, names removed: 0 + ++ test-suite-silo.sys A 127.0.0.1 +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["db", "dns", "names", "external", "2"] +termination: Exited(0) +--------------------------------------------- +stdout: +External zone: oxide-dev.test + NAME RECORDS + test-suite-silo.sys A 127.0.0.1 +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["db", "services", "list-instances"] +termination: Exited(0) +--------------------------------------------- +stdout: +SERVICE INSTANCE_ID ADDR SLED_SERIAL +CruciblePantry REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT sim-b6d65341 +Dendrite REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT sim-b6d65341 +Dendrite REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT sim-b6d65341 +ExternalDns REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT sim-b6d65341 +InternalDns REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT sim-b6d65341 +Nexus REDACTED_UUID_REDACTED_UUID_REDACTED [::ffff:127.0.0.1]:REDACTED_PORT sim-b6d65341 +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["db", "services", "list-by-sled"] +termination: Exited(0) +--------------------------------------------- +stdout: +sled: sim-b6d65341 (id REDACTED_UUID_REDACTED_UUID_REDACTED) + + SERVICE INSTANCE_ID ADDR + CruciblePantry REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT + Dendrite REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT + Dendrite REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT + ExternalDns REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT + InternalDns REDACTED_UUID_REDACTED_UUID_REDACTED [::1]:REDACTED_PORT + Nexus REDACTED_UUID_REDACTED_UUID_REDACTED [::ffff:127.0.0.1]:REDACTED_PORT + +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["db", "sleds"] +termination: Exited(0) +--------------------------------------------- +stdout: +SERIAL IP ROLE ID +sim-b6d65341 [::1]:REDACTED_PORT - REDACTED_UUID_REDACTED_UUID_REDACTED +--------------------------------------------- +stderr: +note: database schema version matches expected (4.0.0) +============================================= +EXECUTING COMMAND: omdb ["nexus", "background-tasks", "doc"] +termination: Exited(0) +--------------------------------------------- +stdout: +task: "dns_config_external" + watches external DNS data stored in CockroachDB + + +task: "dns_config_internal" + watches internal DNS data stored in CockroachDB + + +task: "dns_propagation_external" + propagates latest external DNS configuration (from "dns_config_external" + background task) to the latest list of DNS servers (from + "dns_servers_external" background task) + + +task: "dns_propagation_internal" + propagates latest internal DNS configuration (from "dns_config_internal" + background task) to the latest list of DNS servers (from + "dns_servers_internal" background task) + + +task: "dns_servers_external" + watches list of external DNS servers stored in CockroachDB + + +task: "dns_servers_internal" + watches list of internal DNS servers stored in CockroachDB + + +task: "external_endpoints" + reads config for silos and TLS certificates to determine the right set of + HTTP endpoints, their HTTP server names, and which TLS certificates to use + on each one + + +--------------------------------------------- +stderr: +============================================= +EXECUTING COMMAND: omdb ["nexus", "background-tasks", "show"] +termination: Exited(0) +--------------------------------------------- +stdout: +task: "dns_config_internal" + configured period: every 1m + currently executing: no + last completed activation: iter 3, triggered by an explicit signal + started at (s ago) and ran for ms + last generation found: 1 + +task: "dns_servers_internal" + configured period: every 1m + currently executing: no + last completed activation: iter 3, triggered by an explicit signal + started at (s ago) and ran for ms + servers found: 1 + + DNS_SERVER_ADDR + [::1]:REDACTED_PORT + +task: "dns_propagation_internal" + configured period: every 1m + currently executing: no + last completed activation: iter 5, triggered by a dependent task completing + started at (s ago) and ran for ms + attempt to propagate generation: 1 + + DNS_SERVER_ADDR LAST_RESULT + [::1]:REDACTED_PORT success + + +task: "dns_config_external" + configured period: every 1m + currently executing: no + last completed activation: iter 3, triggered by an explicit signal + started at (s ago) and ran for ms + last generation found: 2 + +task: "dns_servers_external" + configured period: every 1m + currently executing: no + last completed activation: iter 3, triggered by an explicit signal + started at (s ago) and ran for ms + servers found: 1 + + DNS_SERVER_ADDR + [::1]:REDACTED_PORT + +task: "dns_propagation_external" + configured period: every 1m + currently executing: no + last completed activation: iter 5, triggered by a dependent task completing + started at (s ago) and ran for ms + attempt to propagate generation: 2 + + DNS_SERVER_ADDR LAST_RESULT + [::1]:REDACTED_PORT success + + +task: "external_endpoints" + configured period: every 1m + currently executing: no + last completed activation: iter 3, triggered by an explicit signal + started at (s ago) and ran for ms + external API endpoints: 2 ('*' below marks default) + + SILO_ID DNS_NAME + REDACTED_UUID_REDACTED_UUID_REDACTED default-silo.sys.oxide-dev.test + * REDACTED_UUID_REDACTED_UUID_REDACTED test-suite-silo.sys.oxide-dev.test + + warnings: 2 + warning: silo REDACTED_UUID_REDACTED_UUID_REDACTED with DNS name "default-silo.sys.oxide-dev.test" has no usable certificates + warning: silo REDACTED_UUID_REDACTED_UUID_REDACTED with DNS name "test-suite-silo.sys.oxide-dev.test" has no usable certificates + + TLS certificates: 0 + +--------------------------------------------- +stderr: +============================================= diff --git a/omdb/tests/test_all_output.rs b/omdb/tests/test_all_output.rs new file mode 100644 index 0000000000..031bc225a6 --- /dev/null +++ b/omdb/tests/test_all_output.rs @@ -0,0 +1,254 @@ +// 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/. + +//! Smoke tests for the `omdb` tool +//! +//! Feel free to change the tool's output. This test just makes it easy to make +//! sure you're only breaking what you intend. + +use expectorate::assert_contents; +use nexus_test_utils_macros::nexus_test; +use omicron_test_utils::dev::test_cmds::path_to_executable; +use omicron_test_utils::dev::test_cmds::run_command; +use std::fmt::Write; +use std::path::Path; +use subprocess::Exec; + +/// name of the "omdb" executable +const CMD_OMDB: &str = env!("CARGO_BIN_EXE_omdb"); + +type ControlPlaneTestContext = + nexus_test_utils::ControlPlaneTestContext; + +#[tokio::test] +async fn test_omdb_usage_errors() { + let cmd_path = path_to_executable(CMD_OMDB); + let mut output = String::new(); + let invocations: &[&[&'static str]] = &[ + // No arguments + &[], + // Help output + &["--help"], + // Bogus command + &["not-a-command"], + // Bogus argument + &["--not-a-command"], + // Command help output + &["db"], + &["db", "--help"], + &["db", "dns"], + &["db", "dns", "show"], + &["db", "dns", "diff"], + &["db", "dns", "names"], + &["db", "services"], + &["nexus"], + &["nexus", "background-tasks"], + ]; + + for args in invocations { + do_run(&mut output, |exec| exec, &cmd_path, args).await; + } + + assert_contents("tests/usage_errors.out", &output); +} + +#[nexus_test] +async fn test_omdb_success_cases(cptestctx: &ControlPlaneTestContext) { + let cmd_path = path_to_executable(CMD_OMDB); + let postgres_url = cptestctx.database.listen_url(); + let nexus_internal_url = + format!("http://{}/", cptestctx.internal_client.bind_address); + let mut output = String::new(); + let invocations: &[&[&'static str]] = &[ + &["db", "dns", "show"], + &["db", "dns", "diff", "external", "2"], + &["db", "dns", "names", "external", "2"], + &["db", "services", "list-instances"], + &["db", "services", "list-by-sled"], + &["db", "sleds"], + &["nexus", "background-tasks", "doc"], + &["nexus", "background-tasks", "show"], + ]; + + for args in invocations { + println!("running commands with args: {:?}", args); + let p = postgres_url.to_string(); + let u = nexus_internal_url.clone(); + do_run( + &mut output, + move |exec| exec.env("OMDB_DB_URL", &p).env("OMDB_NEXUS_URL", &u), + &cmd_path, + args, + ) + .await; + } + + assert_contents("tests/successes.out", &output); +} + +/// Verify that we properly deal with cases where: +/// +/// - a URL is specified on the command line +/// - a URL is specified in both places +/// +/// for both of the URLs that we accept. We don't need to check the cases where +/// (1) no URL is specified in either place because that's covered by the usage +/// test above, nor (2) the URL is specified only in the environment because +/// that's covered by the success tests above. +#[nexus_test] +async fn test_omdb_env_settings(cptestctx: &ControlPlaneTestContext) { + let cmd_path = path_to_executable(CMD_OMDB); + let postgres_url = cptestctx.database.listen_url().to_string(); + let nexus_internal_url = + format!("http://{}", cptestctx.internal_client.bind_address); + let mut output = String::new(); + + // Database URL + // Case 1: specified on the command line + let args = &["db", "--db-url", &postgres_url, "sleds"]; + do_run(&mut output, |exec| exec, &cmd_path, args).await; + + // Case 2: specified in both places. + let args = &["db", "--db-url", "junk", "sleds"]; + let p = postgres_url.clone(); + do_run( + &mut output, + move |exec| exec.env("ODMB_DB_URL", &p), + &cmd_path, + args, + ) + .await; + + // Nexus URL + // Case 1: specified on the command line + let args = &[ + "nexus", + "--nexus-internal-url", + &nexus_internal_url.clone(), + "background-tasks", + "doc", + ]; + do_run(&mut output, |exec| exec, &cmd_path.clone(), args).await; + + // Case 2: specified in both places. + let args = + &["nexus", "--nexus-internal-url", "junk", "background-tasks", "doc"]; + let p = postgres_url.clone(); + do_run( + &mut output, + move |exec| exec.env("ODMB_DB_URL", &p), + &cmd_path, + args, + ) + .await; + + assert_contents("tests/env.out", &output); +} + +async fn do_run( + output: &mut String, + modexec: F, + cmd_path: &Path, + args: &[&str], +) where + F: FnOnce(Exec) -> Exec + Send + 'static, +{ + println!("running command with args: {:?}", args); + write!( + output, + "EXECUTING COMMAND: {} {:?}\n", + cmd_path.file_name().expect("missing command").to_string_lossy(), + args.iter().map(|r| redact_variable(r)).collect::>(), + ) + .unwrap(); + + // Using `subprocess`, the child process will be spawned synchronously. In + // some cases it then tries to make an HTTP request back into this process. + // But if the executor is blocked on the child process, the HTTP server + // acceptor won't run and we'll deadlock. So we use spawn_blocking() to run + // the child process from a different thread. tokio requires that these be + // 'static (it does not know that we're going to wait synchronously for the + // task) so we need to create owned versions of these arguments. + let cmd_path = cmd_path.to_owned(); + let owned_args: Vec<_> = args.into_iter().map(|s| s.to_string()).collect(); + let (exit_status, stdout_text, stderr_text) = + tokio::task::spawn_blocking(move || { + let exec = modexec( + Exec::cmd(cmd_path) + // Set RUST_BACKTRACE for consistency between CI and + // developers' local runs. We set it to 0 only to match + // what someone would see who wasn't debugging it, but we + // could as well use 1 or "full" to store that instead. + .env("RUST_BACKTRACE", "0") + .args(&owned_args), + ); + run_command(exec) + }) + .await + .unwrap(); + + write!(output, "termination: {:?}\n", exit_status).unwrap(); + write!(output, "---------------------------------------------\n").unwrap(); + write!(output, "stdout:\n").unwrap(); + output.push_str(&redact_variable(&stdout_text)); + write!(output, "---------------------------------------------\n").unwrap(); + write!(output, "stderr:\n").unwrap(); + output.push_str(&stderr_text); + write!(output, "=============================================\n").unwrap(); +} + +/// Redacts text from stdout/stderr that may change from invocation to invocation +/// (e.g., assigned TCP port numbers, timestamps) +/// +/// This allows use to use expectorate to verify the shape of the CLI output. +fn redact_variable(input: &str) -> String { + // Replace TCP port numbers. We include the localhost characters to avoid + // catching any random sequence of numbers. + let s = regex::Regex::new(r"\[::1\]:\d{4,5}") + .unwrap() + .replace_all(input, "[::1]:REDACTED_PORT") + .to_string(); + let s = regex::Regex::new(r"\[::ffff:127.0.0.1\]:\d{4,5}") + .unwrap() + .replace_all(&s, "[::ffff:127.0.0.1]:REDACTED_PORT") + .to_string(); + let s = regex::Regex::new(r"127\.0\.0\.1:\d{4,5}") + .unwrap() + .replace_all(&s, "127.0.0.1:REDACTED_PORT") + .to_string(); + + // Replace uuids. + let s = regex::Regex::new( + "[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-\ + [a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}", + ) + .unwrap() + .replace_all(&s, "REDACTED_UUID_REDACTED_UUID_REDACTED") + .to_string(); + + // Replace timestamps. + let s = regex::Regex::new(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z") + .unwrap() + .replace_all(&s, "") + .to_string(); + + let s = regex::Regex::new(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z") + .unwrap() + .replace_all(&s, "") + .to_string(); + + // Replace formatted durations. These are pretty specific to the background + // task output. + let s = regex::Regex::new(r"\d+s ago") + .unwrap() + .replace_all(&s, "s ago") + .to_string(); + + let s = regex::Regex::new(r"\d+ms") + .unwrap() + .replace_all(&s, "ms") + .to_string(); + + s +} diff --git a/omdb/tests/usage_errors.out b/omdb/tests/usage_errors.out new file mode 100644 index 0000000000..860c0efe21 --- /dev/null +++ b/omdb/tests/usage_errors.out @@ -0,0 +1,224 @@ +EXECUTING COMMAND: omdb [] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Omicron debugger (unstable) + +Usage: omdb [OPTIONS] + +Commands: + db Query the control plane database (CockroachDB) + nexus Debug a specific Nexus instance + help Print this message or the help of the given subcommand(s) + +Options: + --log-level log level filter [env: LOG_LEVEL=] [default: warn] + -h, --help Print help (see more with '--help') +============================================= +EXECUTING COMMAND: omdb ["--help"] +termination: Exited(0) +--------------------------------------------- +stdout: +Omicron debugger (unstable) + +This tool provides commands for directly querying Omicron components about their internal state +using internal APIs. This is a prototype. The commands and output are unstable and may change. + +Usage: omdb [OPTIONS] + +Commands: + db Query the control plane database (CockroachDB) + nexus Debug a specific Nexus instance + help Print this message or the help of the given subcommand(s) + +Options: + --log-level + log level filter + + [env: LOG_LEVEL=] + [default: warn] + + -h, --help + Print help (see a summary with '-h') +--------------------------------------------- +stderr: +============================================= +EXECUTING COMMAND: omdb ["not-a-command"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +error: unrecognized subcommand 'not-a-command' + +Usage: omdb [OPTIONS] + +For more information, try '--help'. +============================================= +EXECUTING COMMAND: omdb ["--not-a-command"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +error: unexpected argument '--not-a-command' found + +Usage: omdb [OPTIONS] + +For more information, try '--help'. +============================================= +EXECUTING COMMAND: omdb ["db"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Query the control plane database (CockroachDB) + +Usage: omdb db [OPTIONS] + +Commands: + dns Print information about internal and external DNS + services Print information about control plane services + sleds Print information about sleds + help Print this message or the help of the given subcommand(s) + +Options: + --db-url URL of the database SQL interface [env: OMDB_DB_URL=] + --fetch-limit limit to apply to queries that fetch rows [default: 100] + -h, --help Print help +============================================= +EXECUTING COMMAND: omdb ["db", "--help"] +termination: Exited(0) +--------------------------------------------- +stdout: +Query the control plane database (CockroachDB) + +Usage: omdb db [OPTIONS] + +Commands: + dns Print information about internal and external DNS + services Print information about control plane services + sleds Print information about sleds + help Print this message or the help of the given subcommand(s) + +Options: + --db-url URL of the database SQL interface [env: OMDB_DB_URL=] + --fetch-limit limit to apply to queries that fetch rows [default: 100] + -h, --help Print help +--------------------------------------------- +stderr: +============================================= +EXECUTING COMMAND: omdb ["db", "dns"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Print information about internal and external DNS + +Usage: omdb db dns + +Commands: + show Summarize current version of all DNS zones + diff Show what changed in a given DNS version + names Show the full contents of a given DNS zone and version + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help +============================================= +EXECUTING COMMAND: omdb ["db", "dns", "show"] +termination: Exited(1) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Error: database URL must be specified with --db-url or OMDB_DB_URL +============================================= +EXECUTING COMMAND: omdb ["db", "dns", "diff"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +error: the following required arguments were not provided: + + + +Usage: omdb db dns diff + +For more information, try '--help'. +============================================= +EXECUTING COMMAND: omdb ["db", "dns", "names"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +error: the following required arguments were not provided: + + + +Usage: omdb db dns names + +For more information, try '--help'. +============================================= +EXECUTING COMMAND: omdb ["db", "services"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Print information about control plane services + +Usage: omdb db services + +Commands: + list-instances List service instances + list-by-sled List service instances, grouped by sled + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help +============================================= +EXECUTING COMMAND: omdb ["nexus"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +Debug a specific Nexus instance + +Usage: omdb nexus [OPTIONS] + +Commands: + background-tasks print information about background tasks + help Print this message or the help of the given subcommand(s) + +Options: + --nexus-internal-url URL of the Nexus internal API [env: + OMDB_NEXUS_URL=] + -h, --help Print help +============================================= +EXECUTING COMMAND: omdb ["nexus", "background-tasks"] +termination: Exited(2) +--------------------------------------------- +stdout: +--------------------------------------------- +stderr: +print information about background tasks + +Usage: omdb nexus background-tasks + +Commands: + doc Show documentation about background tasks + list Print a summary of the status of all background tasks + show Print human-readable summary of the status of each background task + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help +=============================================