From 9df4131e6066b1bd0ad456c72d03241117696e97 Mon Sep 17 00:00:00 2001 From: Marko Mikulicic Date: Thu, 11 Mar 2021 16:23:22 +0100 Subject: [PATCH] feat: Add server remote [set|remove|list] commands --- Cargo.lock | 1 + Cargo.toml | 2 + src/commands/server.rs | 10 +++- src/commands/server_remote.rs | 76 ++++++++++++++++++++++++ src/main.rs | 3 +- tests/end_to_end_cases/management_cli.rs | 59 ++++++++++++++++++ 6 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 src/commands/server_remote.rs diff --git a/Cargo.lock b/Cargo.lock index 50de29dc12..e1101ea91b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1507,6 +1507,7 @@ dependencies = [ "panic_logging", "parking_lot", "predicates", + "prettytable-rs", "prost", "query", "rand 0.7.3", diff --git a/Cargo.toml b/Cargo.toml index 47a3118d39..efd5b79e1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,8 @@ http = "0.2.0" hyper = "0.14" opentelemetry = { version = "0.12", default-features = false, features = ["trace", "tokio-support"] } opentelemetry-jaeger = { version = "0.11", features = ["tokio"] } +# used by arrow/datafusion anyway +prettytable-rs = "0.8" prost = "0.7" # Forked to upgrade hyper and tokio routerify = { git = "https://github.com/influxdata/routerify", rev = "274e250" } diff --git a/src/commands/server.rs b/src/commands/server.rs index de8afcf86a..d270bf2969 100644 --- a/src/commands/server.rs +++ b/src/commands/server.rs @@ -1,7 +1,7 @@ //! Implementation of command line option for manipulating and showing server //! config -use crate::commands::logging::LoggingLevel; +use crate::commands::{logging::LoggingLevel, server_remote}; use crate::influxdb_ioxd; use clap::arg_enum; use std::{net::SocketAddr, net::ToSocketAddrs, path::PathBuf}; @@ -20,8 +20,10 @@ pub const FALLBACK_AWS_REGION: &str = "us-east-1"; #[derive(Debug, Error)] pub enum Error { - #[error("Server error: {0}")] + #[error("Run: {0}")] ServerError(#[from] influxdb_ioxd::Error), + #[error("Remote: {0}")] + RemoteError(#[from] server_remote::Error), } pub type Result = std::result::Result; @@ -30,6 +32,7 @@ pub type Result = std::result::Result; #[structopt(name = "server", about = "IOx server commands")] pub enum Config { Run(RunConfig), + Remote(crate::commands::server_remote::Config), } #[derive(Debug, StructOpt)] @@ -231,9 +234,10 @@ Possible values (case insensitive): pub jaeger_host: Option, } -pub async fn command(logging_level: LoggingLevel, config: Config) -> Result<()> { +pub async fn command(logging_level: LoggingLevel, url: String, config: Config) -> Result<()> { match config { Config::Run(config) => Ok(influxdb_ioxd::main(logging_level, config).await?), + Config::Remote(config) => Ok(server_remote::command(url, config).await?), } } diff --git a/src/commands/server_remote.rs b/src/commands/server_remote.rs new file mode 100644 index 0000000000..5a6c4fef1c --- /dev/null +++ b/src/commands/server_remote.rs @@ -0,0 +1,76 @@ +use influxdb_iox_client::{connection::Builder, management}; +use structopt::StructOpt; +use thiserror::Error; + +use prettytable::{format, Cell, Row, Table}; + +#[derive(Debug, Error)] +pub enum Error { + #[error("Error connecting to IOx: {0}")] + ConnectionError(#[from] influxdb_iox_client::connection::Error), + + #[error("Update remote error: {0}")] + UpdateError(#[from] management::UpdateRemoteError), + + #[error("List remote error: {0}")] + ListError(#[from] management::ListRemotesError), +} + +pub type Result = std::result::Result; + +#[derive(Debug, StructOpt)] +#[structopt( + name = "remote", + about = "Manage configuration about other IOx servers" +)] +pub enum Config { + /// Set connection parameters for a remote IOx server. + Set { id: u32, connection_string: String }, + /// Remove a reference to a remote IOx server. + Remove { id: u32 }, + /// List configured remote IOx server. + List, +} + +pub async fn command(url: String, config: Config) -> Result<()> { + let connection = Builder::default().build(url).await?; + + match config { + Config::Set { + id, + connection_string, + } => { + let mut client = management::Client::new(connection); + client.update_remote(id, connection_string).await?; + } + Config::Remove { id } => { + let mut client = management::Client::new(connection); + client.delete_remote(id).await?; + } + Config::List => { + let mut client = management::Client::new(connection); + + let remotes = client.list_remotes().await?; + if remotes.is_empty() { + println!("no remotes configured"); + } else { + let mut table = Table::new(); + table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE); + table.set_titles(Row::new(vec![ + Cell::new("ID"), + Cell::new("Connection string"), + ])); + + for i in remotes { + table.add_row(Row::new(vec![ + Cell::new(&format!("{}", i.id)), + Cell::new(&i.connection_string), + ])); + } + print!("{}", table); + } + } + }; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 0f9d1d601d..3d7e10b201 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ mod commands { pub mod logging; pub mod meta; pub mod server; + pub mod server_remote; pub mod stats; pub mod writer; } @@ -185,7 +186,7 @@ fn main() -> Result<(), std::io::Error> { Command::Server(config) => { // Note don't set up basic logging here, different logging rules apply in server // mode - if let Err(e) = commands::server::command(logging_level, *config).await { + if let Err(e) = commands::server::command(logging_level, host, *config).await { eprintln!("Server command failed: {}", e); std::process::exit(ReturnCode::Failure as _) } diff --git a/tests/end_to_end_cases/management_cli.rs b/tests/end_to_end_cases/management_cli.rs index c28c5fe56a..81532fbf3b 100644 --- a/tests/end_to_end_cases/management_cli.rs +++ b/tests/end_to_end_cases/management_cli.rs @@ -10,6 +10,7 @@ pub async fn test() { test_writer_id(addr).await; test_create_database(addr).await; + test_remotes(addr).await; } async fn test_writer_id(addr: &str) { @@ -81,3 +82,61 @@ async fn test_create_database(addr: &str) { .success() .stdout(predicate::str::contains(format!("name: \"{}\"", db))); } + +async fn test_remotes(addr: &str) { + Command::cargo_bin("influxdb_iox") + .unwrap() + .arg("server") + .arg("remote") + .arg("list") + .arg("--host") + .arg(addr) + .assert() + .success() + .stdout(predicate::str::contains("no remotes configured")); + + Command::cargo_bin("influxdb_iox") + .unwrap() + .arg("server") + .arg("remote") + .arg("set") + .arg("1") + .arg("http://1.2.3.4:1234") + .arg("--host") + .arg(addr) + .assert() + .success(); + + Command::cargo_bin("influxdb_iox") + .unwrap() + .arg("server") + .arg("remote") + .arg("list") + .arg("--host") + .arg(addr) + .assert() + .success() + .stdout(predicate::str::contains("http://1.2.3.4:1234")); + + Command::cargo_bin("influxdb_iox") + .unwrap() + .arg("server") + .arg("remote") + .arg("remove") + .arg("1") + .arg("--host") + .arg(addr) + .assert() + .success(); + + Command::cargo_bin("influxdb_iox") + .unwrap() + .arg("server") + .arg("remote") + .arg("list") + .arg("--host") + .arg(addr) + .assert() + .success() + .stdout(predicate::str::contains("no remotes configured")); +}