From 88a8ca91a28afe0da63debb448b2d0a8060f99e5 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:33:13 -0400 Subject: [PATCH] Chore/use rich printer for network container (#1638) * Use rich printer in network container shared * Cleanup container retry logging --------- Co-authored-by: Nando Vieira --- .../src/commands/network/container.rs | 2 +- .../src/commands/network/container/logs.rs | 10 ++-- .../src/commands/network/container/shared.rs | 50 ++++++++++--------- .../src/commands/network/container/start.rs | 6 ++- .../src/commands/network/container/stop.rs | 2 +- 5 files changed, 41 insertions(+), 29 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container.rs b/cmd/soroban-cli/src/commands/network/container.rs index 463dbbdc8..d14dc72e4 100644 --- a/cmd/soroban-cli/src/commands/network/container.rs +++ b/cmd/soroban-cli/src/commands/network/container.rs @@ -41,7 +41,7 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match &self { - Cmd::Logs(cmd) => cmd.run().await?, + Cmd::Logs(cmd) => cmd.run(global_args).await?, Cmd::Start(cmd) => cmd.run(global_args).await?, Cmd::Stop(cmd) => cmd.run(global_args).await?, } diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index 99b36af9b..aaccffdde 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,6 +1,9 @@ use futures_util::TryStreamExt; -use crate::commands::network::container::shared::Error as ConnectionError; +use crate::{ + commands::{global, network::container::shared::Error as ConnectionError}, + print, +}; use super::shared::{Args, Name}; @@ -23,9 +26,10 @@ pub struct Cmd { } impl Cmd { - pub async fn run(&self) -> Result<(), Error> { + pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let print = print::Print::new(global_args.quiet); let container_name = Name(self.name.clone()).get_internal_container_name(); - let docker = self.container_args.connect_to_docker().await?; + let docker = self.container_args.connect_to_docker(&print).await?; let logs_stream = &mut docker.logs( &container_name, Some(bollard::container::LogsOptions { diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index f819f3ed3..38cb17af2 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -6,6 +6,8 @@ use clap::ValueEnum; // Need to add this for windows, since we are only using this crate for the unix fn try_docker_desktop_socket use home::home_dir; +use crate::print; + pub const DOCKER_HOST_HELP: &str = "Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock"; // DEFAULT_DOCKER_HOST is from the bollard crate on the main branch, which has not been released yet: https://github.com/fussybeaver/bollard/blob/0972b1aac0ad5c08798e100319ddd0d2ee010365/src/docker.rs#L64 @@ -46,7 +48,8 @@ impl Args { .unwrap_or_default() } - pub(crate) async fn connect_to_docker(&self) -> Result { + #[allow(unused_variables)] + pub(crate) async fn connect_to_docker(&self, print: &print::Print) -> Result { // if no docker_host is provided, use the default docker host: // "unix:///var/run/docker.sock" on unix machines // "npipe:////./pipe/docker_engine" on windows machines @@ -89,7 +92,7 @@ impl Args { // if on unix, try to connect to the default docker desktop socket #[cfg(unix)] { - let docker_desktop_connection = try_docker_desktop_socket(&host)?; + let docker_desktop_connection = try_docker_desktop_socket(&host, print)?; match check_docker_connection(&docker_desktop_connection).await { Ok(()) => Ok(docker_desktop_connection), Err(err) => Err(err)?, @@ -138,40 +141,41 @@ impl Name { } #[cfg(unix)] -fn try_docker_desktop_socket(host: &str) -> Result { +fn try_docker_desktop_socket( + host: &str, + print: &print::Print, +) -> Result { let default_docker_desktop_host = format!("{}/.docker/run/docker.sock", home_dir().unwrap().display()); - println!("Failed to connect to DOCKER_HOST: {host}.\nTrying to connect to the default Docker Desktop socket at {default_docker_desktop_host}."); + print.warnln(format!("Failed to connect to Docker daemon at {host}.")); + + print.infoln(format!( + "Attempting to connect to the default Docker Desktop socket at {default_docker_desktop_host} instead." + )); Docker::connect_with_unix( &default_docker_desktop_host, DEFAULT_TIMEOUT, API_DEFAULT_VERSION, - ) + ).map_err(|e| { + print.errorln(format!( + "Failed to connect to the Docker daemon at {host:?}. Is the docker daemon running?" + )); + print.infoln( + "Running a local Stellar network requires a Docker-compatible container runtime." + ); + print.infoln( + "Please note that if you are using Docker Desktop, you may need to utilize the `--docker-host` flag to pass in the location of the docker socket on your machine." + ); + e + }) } // When bollard is not able to connect to the docker daemon, it returns a generic ConnectionRefused error // This method attempts to connect to the docker daemon and returns a more specific error message async fn check_docker_connection(docker: &Docker) -> Result<(), bollard::errors::Error> { - // This is a bit hacky, but the `client_addr` field is not directly accessible from the `Docker` struct, but we can access it from the debug string representation of the `Docker` struct - let docker_debug_string = format!("{docker:#?}"); - let start_of_client_addr = docker_debug_string.find("client_addr: ").unwrap(); - let end_of_client_addr = docker_debug_string[start_of_client_addr..] - .find(',') - .unwrap(); - // Extract the substring containing the value of client_addr - let client_addr = &docker_debug_string - [start_of_client_addr + "client_addr: ".len()..start_of_client_addr + end_of_client_addr] - .trim() - .trim_matches('"'); - match docker.version().await { Ok(_version) => Ok(()), - Err(err) => { - println!( - "⛔️ Failed to connect to the Docker daemon at {client_addr:?}. Is the docker daemon running?\nℹ️ Running a local Stellar network requires a Docker-compatible container runtime.\nℹ️ Please note that if you are using Docker Desktop, you may need to utilize the `--docker-host` flag to pass in the location of the docker socket on your machine.\n" - ); - Err(err) - } + Err(err) => Err(err), } } diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index a4d840f0f..2f16d3c1e 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -79,7 +79,11 @@ impl Runner { self.print .infoln(format!("Starting {} network", &self.args.network)); - let docker = self.args.container_args.connect_to_docker().await?; + let docker = self + .args + .container_args + .connect_to_docker(&self.print) + .await?; let image = self.get_image_name(); let mut stream = docker.create_image( diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 87d6ba495..77f674c46 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -34,7 +34,7 @@ impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { let print = print::Print::new(global_args.quiet); let container_name = Name(self.name.clone()); - let docker = self.container_args.connect_to_docker().await?; + let docker = self.container_args.connect_to_docker(&print).await?; print.infoln(format!( "Stopping {} container",