From d26eb225b54bda7012e53e8e7ba993ca0f299da8 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Fri, 28 Jun 2024 18:04:15 -0400 Subject: [PATCH 01/32] Return a better error message when stopping container that doesn't exist --- .../src/commands/network/container/stop.rs | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index c511b5e4d..5455ab22c 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -5,7 +5,17 @@ use crate::commands::network::container::shared::{ #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Failed to stop container: {0}")] - StopContainerError(#[from] ConnectionError), + StopConnectionContainerError(#[from] ConnectionError), + + #[error("Container {container_name} not found")] + ContainerNotFoundError { + container_name: String, + #[source] + source: bollard::errors::Error, + }, + + #[error("Failed to stop container: {0}")] + StopContainerError(#[from] bollard::errors::Error), } #[derive(Debug, clap::Parser, Clone)] @@ -22,7 +32,20 @@ impl Cmd { let container_name = format!("stellar-{}", self.network); let docker = connect_to_docker(&self.docker_host).await?; println!("ℹ️ Stopping container: {container_name}"); - docker.stop_container(&container_name, None).await.unwrap(); + docker + .stop_container(&container_name, None) + .await + .map_err(|e| { + let msg = e.to_string(); + if msg.contains("No such container") { + Error::ContainerNotFoundError { + container_name: container_name.clone(), + source: e, + } + } else { + Error::StopContainerError(e) + } + })?; println!("✅ Container stopped: {container_name}"); Ok(()) } From 321a48ff8b3f7ebc5993c4faf741083c658024da Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:22:22 -0400 Subject: [PATCH 02/32] Fix doc strings for network container commands --- cmd/soroban-cli/src/commands/network/container.rs | 4 ++-- cmd/soroban-cli/src/commands/network/container/start.rs | 2 +- cmd/soroban-cli/src/commands/network/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container.rs b/cmd/soroban-cli/src/commands/network/container.rs index 16e5d73be..a65140469 100644 --- a/cmd/soroban-cli/src/commands/network/container.rs +++ b/cmd/soroban-cli/src/commands/network/container.rs @@ -16,11 +16,11 @@ pub enum Cmd { /// /// Start a container running a Stellar node, RPC, API, and friendbot (faucet). /// - /// `stellar network start NETWORK [OPTIONS]` + /// `stellar network container start NETWORK [OPTIONS]` /// /// By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: /// - /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` + /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(start::Cmd), /// Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it. Stop(stop::Cmd), diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index cc9619f1d..508c11815 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -106,7 +106,7 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { .await?; println!("✅ Container started: {container_name}"); let stop_message = format!( - "ℹ️ To stop this container run: stellar network stop {network} {additional_flags}", + "ℹ️ To stop this container run: stellar network container stop {network} {additional_flags}", network = &cmd.network, additional_flags = if cmd.docker_host.is_some() { format!("--docker-host {}", cmd.docker_host.as_ref().unwrap()) diff --git a/cmd/soroban-cli/src/commands/network/mod.rs b/cmd/soroban-cli/src/commands/network/mod.rs index 435492295..1c34f92c8 100644 --- a/cmd/soroban-cli/src/commands/network/mod.rs +++ b/cmd/soroban-cli/src/commands/network/mod.rs @@ -38,7 +38,7 @@ pub enum Cmd { /// /// By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: /// - /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` + /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(container::StartCmd), /// ⚠️ Deprecated: use `stellar container stop` instead /// From ae4ea7f8ce7008a526d2a3b91e7d75cad8c5cad5 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:35:32 -0400 Subject: [PATCH 03/32] Pull shared container args to shared.rs --- .../src/commands/network/container/logs.rs | 12 +++++++----- .../src/commands/network/container/shared.rs | 11 +++++++++++ .../src/commands/network/container/start.rs | 16 +++++++++------- .../src/commands/network/container/stop.rs | 12 +++++++----- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index e37ceb098..d59867950 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,9 +1,11 @@ use futures_util::TryStreamExt; use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, DOCKER_HOST_HELP, + connect_to_docker, Error as ConnectionError, Network, }; +use super::shared::ContainerArgs; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] @@ -15,17 +17,17 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { + #[command(flatten)] + pub container_args: ContainerArgs, + /// Network to tail pub network: Network, - - #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] - pub docker_host: Option, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { let container_name = format!("stellar-{}", self.network); - let docker = connect_to_docker(&self.docker_host).await?; + let docker = connect_to_docker(&self.container_args.docker_host).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 9da8a1bea..a8dcce2b0 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -31,6 +31,17 @@ pub enum Error { UnsupportedURISchemeError { uri: String }, } +#[derive(Debug, clap::Parser, Clone)] +pub struct ContainerArgs { + /// Optional argument to specify the container name + #[arg(short = 'c', long, required_unless_present = "network")] + pub container_name: Option, + + /// 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 + #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] + pub docker_host: Option, +} + #[derive(ValueEnum, Debug, Clone, PartialEq)] pub enum Network { Local, diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 508c11815..c5d5b2bdf 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -8,9 +8,11 @@ use bollard::{ use futures_util::TryStreamExt; use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, DOCKER_HOST_HELP, + connect_to_docker, Error as ConnectionError, Network, }; +use super::shared::ContainerArgs; + const DEFAULT_PORT_MAPPING: &str = "8000:8000"; const DOCKER_IMAGE: &str = "docker.io/stellar/quickstart"; @@ -25,12 +27,12 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { + #[command(flatten)] + pub container_args: ContainerArgs, + /// Network to start pub network: Network, - #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] - pub docker_host: Option, - /// Optional argument to specify the limits for the local network only #[arg(short = 'l', long)] pub limits: Option, @@ -56,7 +58,7 @@ impl Cmd { } async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { - let docker = connect_to_docker(&cmd.docker_host).await?; + let docker = connect_to_docker(&cmd.container_args.docker_host).await?; let image = get_image_name(cmd); docker @@ -108,8 +110,8 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { let stop_message = format!( "ℹ️ To stop this container run: stellar network container stop {network} {additional_flags}", network = &cmd.network, - additional_flags = if cmd.docker_host.is_some() { - format!("--docker-host {}", cmd.docker_host.as_ref().unwrap()) + additional_flags = if cmd.container_args.docker_host.is_some() { + format!("--docker-host {}", cmd.container_args.docker_host.as_ref().unwrap()) } else { String::new() } diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 5455ab22c..31c36010a 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,7 +1,9 @@ use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, DOCKER_HOST_HELP, + connect_to_docker, Error as ConnectionError, Network, }; +use super::shared::ContainerArgs; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Failed to stop container: {0}")] @@ -20,17 +22,17 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { + #[command(flatten)] + pub container_args: ContainerArgs, + /// Network to stop pub network: Network, - - #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] - pub docker_host: Option, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { let container_name = format!("stellar-{}", self.network); - let docker = connect_to_docker(&self.docker_host).await?; + let docker = connect_to_docker(&self.container_args.docker_host).await?; println!("ℹ️ Stopping container: {container_name}"); docker .stop_container(&container_name, None) From 5c67caf78c62176a1b069563ec8d907420722f3a Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:34:00 -0400 Subject: [PATCH 04/32] Allow for overwriting the default container name with -c --- .../src/commands/network/container/logs.rs | 10 ++-- .../src/commands/network/container/shared.rs | 10 +++- .../src/commands/network/container/start.rs | 52 ++++++++++++++++--- .../src/commands/network/container/stop.rs | 10 ++-- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index d59867950..549a8e2bc 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -4,7 +4,7 @@ use crate::commands::network::container::shared::{ connect_to_docker, Error as ConnectionError, Network, }; -use super::shared::ContainerArgs; +use super::shared::{get_container_name, ContainerArgs}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -20,13 +20,15 @@ pub struct Cmd { #[command(flatten)] pub container_args: ContainerArgs, - /// Network to tail - pub network: Network, + /// Network container to tail (used in container name generation) + #[arg(required_unless_present = "container_name")] + pub network: Option, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = format!("stellar-{}", self.network); + let container_name = + get_container_name(self.container_args.container_name.clone(), self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index a8dcce2b0..6b2e282c8 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -42,7 +42,7 @@ pub struct ContainerArgs { pub docker_host: Option, } -#[derive(ValueEnum, Debug, Clone, PartialEq)] +#[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] pub enum Network { Local, Testnet, @@ -159,3 +159,11 @@ async fn check_docker_connection(docker: &Docker) -> Result<(), bollard::errors: } } } + +pub fn get_container_name(container_name_arg: Option, network: Option) -> String { + if let Some(container_name) = container_name_arg { + container_name.to_string() + } else { + format!("stellar-{}", network.unwrap()) + } +} diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index c5d5b2bdf..d176ecc4c 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -8,7 +8,7 @@ use bollard::{ use futures_util::TryStreamExt; use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, + connect_to_docker, get_container_name, Error as ConnectionError, Network, }; use super::shared::ContainerArgs; @@ -89,7 +89,8 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { ..Default::default() }; - let container_name = format!("stellar-{}", cmd.network); + let container_name = + get_container_name(cmd.container_args.container_name.clone(), Some(cmd.network)); let create_container_response = docker .create_container( Some(CreateContainerOptions { @@ -107,18 +108,55 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { ) .await?; println!("✅ Container started: {container_name}"); + print_log_message(cmd); + print_stop_message(cmd); + Ok(()) +} + +fn print_stop_message(cmd: &Cmd) { let stop_message = format!( - "ℹ️ To stop this container run: stellar network container stop {network} {additional_flags}", - network = &cmd.network, + "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", + arg = if cmd.container_args.container_name.is_some() { + format!( + "--container-name {}", + cmd.container_args.container_name.clone().unwrap() + ) + } else { + cmd.network.to_string() + }, additional_flags = if cmd.container_args.docker_host.is_some() { - format!("--docker-host {}", cmd.container_args.docker_host.as_ref().unwrap()) + format!( + "--docker-host {}", + cmd.container_args.docker_host.as_ref().unwrap() + ) } else { String::new() } ); - println!("{stop_message}"); - Ok(()) +} + +fn print_log_message(cmd: &Cmd) { + let log_message = format!( + "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", + arg = if cmd.container_args.container_name.is_some() { + format!( + "--container-name {}", + cmd.container_args.container_name.clone().unwrap() + ) + } else { + cmd.network.to_string() + }, + additional_flags = if cmd.container_args.docker_host.is_some() { + format!( + "--docker-host {}", + cmd.container_args.docker_host.as_ref().unwrap() + ) + } else { + String::new() + } + ); + println!("{log_message}"); } fn get_container_args(cmd: &Cmd) -> Vec { diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 31c36010a..95585bc5a 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,5 +1,5 @@ use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, + connect_to_docker, get_container_name, Error as ConnectionError, Network, }; use super::shared::ContainerArgs; @@ -25,13 +25,15 @@ pub struct Cmd { #[command(flatten)] pub container_args: ContainerArgs, - /// Network to stop - pub network: Network, + /// Network to stop (used in container name generation) + #[arg(required_unless_present = "container_name")] + pub network: Option, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = format!("stellar-{}", self.network); + let container_name = + get_container_name(self.container_args.container_name.clone(), self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; println!("ℹ️ Stopping container: {container_name}"); docker From 70b6c39528639d60b446c7559841e351d57c6e78 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:46:47 -0400 Subject: [PATCH 05/32] Check in generated doc updates --- FULL_HELP_DOCS.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 4f3a52b3c..62719586a 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1060,7 +1060,7 @@ Start a container running a Stellar node, RPC, API, and friendbot (faucet). By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: -`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` +`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` **Usage:** `stellar network start [OPTIONS] ` @@ -1073,6 +1073,7 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** +* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1089,17 +1090,18 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network started with `network start`. For example, if you ran `stellar network start local`, you can use `stellar network stop local` to stop it. -**Usage:** `stellar network stop [OPTIONS] ` +**Usage:** `stellar network stop [OPTIONS] [NETWORK]` ###### **Arguments:** -* `` — Network to stop +* `` — Network to stop (used in container name generation) Possible values: `local`, `testnet`, `futurenet`, `pubnet` ###### **Options:** +* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1122,17 +1124,18 @@ Commands to start, stop and get logs for a quickstart container Tail logs of a running network container -**Usage:** `stellar network container logs [OPTIONS] ` +**Usage:** `stellar network container logs [OPTIONS] [NETWORK]` ###### **Arguments:** -* `` — Network to tail +* `` — Network container to tail (used in container name generation) Possible values: `local`, `testnet`, `futurenet`, `pubnet` ###### **Options:** +* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1143,11 +1146,11 @@ Start network Start a container running a Stellar node, RPC, API, and friendbot (faucet). -`stellar network start NETWORK [OPTIONS]` +`stellar network container start NETWORK [OPTIONS]` By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: -`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` +`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` **Usage:** `stellar network container start [OPTIONS] ` @@ -1160,6 +1163,7 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** +* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1174,17 +1178,18 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it -**Usage:** `stellar network container stop [OPTIONS] ` +**Usage:** `stellar network container stop [OPTIONS] [NETWORK]` ###### **Arguments:** -* `` — Network to stop +* `` — Network to stop (used in container name generation) Possible values: `local`, `testnet`, `futurenet`, `pubnet` ###### **Options:** +* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 From 89bceecc713180112b2236eea3420820d30affbb Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:02:56 -0400 Subject: [PATCH 06/32] Refactor printlns --- .../src/commands/network/container/start.rs | 64 +++++++------------ .../src/commands/network/container/stop.rs | 2 +- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index d176ecc4c..b50b7848d 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -113,52 +113,36 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { Ok(()) } -fn print_stop_message(cmd: &Cmd) { - let stop_message = format!( - "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", - arg = if cmd.container_args.container_name.is_some() { - format!( - "--container-name {}", - cmd.container_args.container_name.clone().unwrap() - ) - } else { - cmd.network.to_string() - }, - additional_flags = if cmd.container_args.docker_host.is_some() { - format!( - "--docker-host {}", - cmd.container_args.docker_host.as_ref().unwrap() - ) - } else { - String::new() - } - ); - println!("{stop_message}"); -} - fn print_log_message(cmd: &Cmd) { let log_message = format!( - "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", - arg = if cmd.container_args.container_name.is_some() { - format!( - "--container-name {}", - cmd.container_args.container_name.clone().unwrap() - ) - } else { - cmd.network.to_string() - }, - additional_flags = if cmd.container_args.docker_host.is_some() { - format!( - "--docker-host {}", - cmd.container_args.docker_host.as_ref().unwrap() - ) - } else { - String::new() - } + "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", + arg = cmd.container_args.container_name.as_ref().map_or_else( + || cmd.network.to_string(), + |container_name| format!("--container-name {}", container_name) + ), + additional_flags = cmd.container_args.docker_host.as_ref().map_or_else( + || String::new(), + |docker_host| format!("--docker-host {}", docker_host) + ) ); println!("{log_message}"); } +fn print_stop_message(cmd: &Cmd) { + let stop_message = format!( + "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", + arg = cmd.container_args.container_name.as_ref().map_or_else( + || cmd.network.to_string(), + |container_name| format!("--container-name {}", container_name) + ), + additional_flags = cmd.container_args.docker_host.as_ref().map_or_else( + || String::new(), + |docker_host| format!("--docker-host {}", docker_host) + ) + ); + println!("{stop_message}"); +} + fn get_container_args(cmd: &Cmd) -> Vec { [ format!("--{}", cmd.network), diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 95585bc5a..1b37cb5ed 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -35,7 +35,7 @@ impl Cmd { let container_name = get_container_name(self.container_args.container_name.clone(), self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; - println!("ℹ️ Stopping container: {container_name}"); + println!("ℹ️ Stopping container: {container_name}"); docker .stop_container(&container_name, None) .await From d800be548d770ef57e6c511747f03f8d7743297b Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:15:01 -0400 Subject: [PATCH 07/32] Clippy & cleanup errors --- .../src/commands/network/container/start.rs | 23 +++++++++++-------- .../src/commands/network/container/stop.rs | 18 +++++++-------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index b50b7848d..c48cd7092 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -19,10 +19,10 @@ const DOCKER_IMAGE: &str = "docker.io/stellar/quickstart"; #[derive(thiserror::Error, Debug)] pub enum Error { #[error("⛔ ️Failed to connect to docker: {0}")] - ConnectionError(#[from] ConnectionError), + DockerConnectionFailed(#[from] ConnectionError), #[error("⛔ ️Failed to create container: {0}")] - BollardErr(#[from] bollard::errors::Error), + CreateContainerFailed(#[from] bollard::errors::Error), } #[derive(Debug, clap::Parser, Clone)] @@ -118,11 +118,11 @@ fn print_log_message(cmd: &Cmd) { "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", arg = cmd.container_args.container_name.as_ref().map_or_else( || cmd.network.to_string(), - |container_name| format!("--container-name {}", container_name) + |container_name| format!("--container-name {container_name}") ), additional_flags = cmd.container_args.docker_host.as_ref().map_or_else( - || String::new(), - |docker_host| format!("--docker-host {}", docker_host) + String::new, + |docker_host| format!("--docker-host {docker_host}") ) ); println!("{log_message}"); @@ -133,12 +133,15 @@ fn print_stop_message(cmd: &Cmd) { "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", arg = cmd.container_args.container_name.as_ref().map_or_else( || cmd.network.to_string(), - |container_name| format!("--container-name {}", container_name) + |container_name| format!("--container-name {container_name}") ), - additional_flags = cmd.container_args.docker_host.as_ref().map_or_else( - || String::new(), - |docker_host| format!("--docker-host {}", docker_host) - ) + additional_flags = cmd + .container_args + .docker_host + .as_ref() + .map_or_else(String::new, |docker_host| format!( + "--docker-host {docker_host}" + )) ); println!("{stop_message}"); } diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 1b37cb5ed..847086504 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,23 +1,23 @@ use crate::commands::network::container::shared::{ - connect_to_docker, get_container_name, Error as ConnectionError, Network, + connect_to_docker, get_container_name, Error as BollardConnectionError, Network, }; use super::shared::ContainerArgs; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("Failed to stop container: {0}")] - StopConnectionContainerError(#[from] ConnectionError), + #[error("⛔ Failed to connect to docker: {0}")] + DockerConnectionFailed(#[from] BollardConnectionError), - #[error("Container {container_name} not found")] - ContainerNotFoundError { + #[error("⛔ Container {container_name} not found")] + ContainerNotFound { container_name: String, #[source] source: bollard::errors::Error, }, - #[error("Failed to stop container: {0}")] - StopContainerError(#[from] bollard::errors::Error), + #[error("⛔ Failed to stop container: {0}")] + ContainerStopFailed(#[from] bollard::errors::Error), } #[derive(Debug, clap::Parser, Clone)] @@ -42,12 +42,12 @@ impl Cmd { .map_err(|e| { let msg = e.to_string(); if msg.contains("No such container") { - Error::ContainerNotFoundError { + Error::ContainerNotFound { container_name: container_name.clone(), source: e, } } else { - Error::StopContainerError(e) + Error::ContainerStopFailed(e) } })?; println!("✅ Container stopped: {container_name}"); From 196c5e5dfb528c5135b5346706e0a1f85f503345 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:21:04 -0400 Subject: [PATCH 08/32] Rename ContainerArgs -> Args --- cmd/soroban-cli/src/commands/network/container/logs.rs | 4 ++-- cmd/soroban-cli/src/commands/network/container/shared.rs | 2 +- cmd/soroban-cli/src/commands/network/container/start.rs | 4 ++-- cmd/soroban-cli/src/commands/network/container/stop.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index 549a8e2bc..c6d623e61 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -4,7 +4,7 @@ use crate::commands::network::container::shared::{ connect_to_docker, Error as ConnectionError, Network, }; -use super::shared::{get_container_name, ContainerArgs}; +use super::shared::{get_container_name, Args}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -18,7 +18,7 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { #[command(flatten)] - pub container_args: ContainerArgs, + pub container_args: Args, /// Network container to tail (used in container name generation) #[arg(required_unless_present = "container_name")] diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 6b2e282c8..ac59474b3 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -32,7 +32,7 @@ pub enum Error { } #[derive(Debug, clap::Parser, Clone)] -pub struct ContainerArgs { +pub struct Args { /// Optional argument to specify the container name #[arg(short = 'c', long, required_unless_present = "network")] pub container_name: Option, diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index c48cd7092..b6b376e6a 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -11,7 +11,7 @@ use crate::commands::network::container::shared::{ connect_to_docker, get_container_name, Error as ConnectionError, Network, }; -use super::shared::ContainerArgs; +use super::shared::Args; const DEFAULT_PORT_MAPPING: &str = "8000:8000"; const DOCKER_IMAGE: &str = "docker.io/stellar/quickstart"; @@ -28,7 +28,7 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { #[command(flatten)] - pub container_args: ContainerArgs, + pub container_args: Args, /// Network to start pub network: Network, diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 847086504..eb7083681 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -2,7 +2,7 @@ use crate::commands::network::container::shared::{ connect_to_docker, get_container_name, Error as BollardConnectionError, Network, }; -use super::shared::ContainerArgs; +use super::shared::Args; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -23,7 +23,7 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { #[command(flatten)] - pub container_args: ContainerArgs, + pub container_args: Args, /// Network to stop (used in container name generation) #[arg(required_unless_present = "container_name")] From 07ccbda48542e45a3bce5324ef52dfcde241a67f Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:22:42 -0400 Subject: [PATCH 09/32] Update cmd/soroban-cli/src/commands/network/container/start.rs Co-authored-by: Willem Wyndham --- cmd/soroban-cli/src/commands/network/container/start.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index b6b376e6a..0bc47f663 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -120,10 +120,9 @@ fn print_log_message(cmd: &Cmd) { || cmd.network.to_string(), |container_name| format!("--container-name {container_name}") ), - additional_flags = cmd.container_args.docker_host.as_ref().map_or_else( - String::new, + additional_flags = cmd.container_args.docker_host.as_ref().map( |docker_host| format!("--docker-host {docker_host}") - ) + ).unwrap_or_default() ); println!("{log_message}"); } From 523adb2f169019b921c7bd8f6698d1687ac5bb51 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:25:56 -0400 Subject: [PATCH 10/32] Use expect instead of unwrap in get_container_name --- cmd/soroban-cli/src/commands/network/container/shared.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index ac59474b3..c0c83bee3 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -164,6 +164,9 @@ pub fn get_container_name(container_name_arg: Option, network: Option Date: Mon, 15 Jul 2024 12:30:45 -0400 Subject: [PATCH 11/32] Add get_additional_flags fn on Args to reduce duplication --- .../src/commands/network/container/shared.rs | 9 +++++++++ .../src/commands/network/container/start.rs | 12 ++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index c0c83bee3..fa3092461 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -42,6 +42,15 @@ pub struct Args { pub docker_host: Option, } +impl Args { + pub(crate) fn get_additional_flags(&self) -> String { + self.docker_host + .as_ref() + .map(|docker_host| format!("--docker-host {docker_host}")) + .unwrap_or_default() + } +} + #[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] pub enum Network { Local, diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 0bc47f663..1db1d0167 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -120,9 +120,7 @@ fn print_log_message(cmd: &Cmd) { || cmd.network.to_string(), |container_name| format!("--container-name {container_name}") ), - additional_flags = cmd.container_args.docker_host.as_ref().map( - |docker_host| format!("--docker-host {docker_host}") - ).unwrap_or_default() + additional_flags = cmd.container_args.get_additional_flags(), ); println!("{log_message}"); } @@ -134,13 +132,7 @@ fn print_stop_message(cmd: &Cmd) { || cmd.network.to_string(), |container_name| format!("--container-name {container_name}") ), - additional_flags = cmd - .container_args - .docker_host - .as_ref() - .map_or_else(String::new, |docker_host| format!( - "--docker-host {docker_host}" - )) + additional_flags = cmd.container_args.get_additional_flags(), ); println!("{stop_message}"); } From ce13f843288f4dd350141c20c04e03d910472fed Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:35:46 -0400 Subject: [PATCH 12/32] Add get_container_name_arg fn on Args to reduce duplication --- .../src/commands/network/container/shared.rs | 7 +++++++ .../src/commands/network/container/start.rs | 10 ++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index fa3092461..8c81c9724 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -49,6 +49,13 @@ impl Args { .map(|docker_host| format!("--docker-host {docker_host}")) .unwrap_or_default() } + + pub(crate) fn get_container_name_arg(&self, network: Network) -> String { + self.container_name.as_ref().map_or_else( + || network.to_string(), + |container_name| format!("--container-name {container_name}"), + ) + } } #[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 1db1d0167..26fb976a1 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -116,10 +116,7 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { fn print_log_message(cmd: &Cmd) { let log_message = format!( "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", - arg = cmd.container_args.container_name.as_ref().map_or_else( - || cmd.network.to_string(), - |container_name| format!("--container-name {container_name}") - ), + arg = cmd.container_args.get_container_name_arg(cmd.network), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -128,10 +125,7 @@ fn print_log_message(cmd: &Cmd) { fn print_stop_message(cmd: &Cmd) { let stop_message = format!( "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", - arg = cmd.container_args.container_name.as_ref().map_or_else( - || cmd.network.to_string(), - |container_name| format!("--container-name {container_name}") - ), + arg = cmd.container_args.get_container_name_arg(cmd.network), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{stop_message}"); From 2a16a42b8049a3d2ec86630af990a4ca8e5ad9f9 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:05:20 -0400 Subject: [PATCH 13/32] Apply suggestions from code review Impl get_container_name in Args struct Co-authored-by: Willem Wyndham --- .../src/commands/network/container/logs.rs | 5 ++- .../src/commands/network/container/shared.rs | 31 +++++++++++-------- .../src/commands/network/container/start.rs | 9 +++--- .../src/commands/network/container/stop.rs | 5 ++- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index c6d623e61..c21511295 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -4,7 +4,7 @@ use crate::commands::network::container::shared::{ connect_to_docker, Error as ConnectionError, Network, }; -use super::shared::{get_container_name, Args}; +use super::shared::Args; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -27,8 +27,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = - get_container_name(self.container_args.container_name.clone(), self.network); + let container_name = self.container_args.get_container_name(self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 8c81c9724..06eace70d 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -50,9 +50,25 @@ impl Args { .unwrap_or_default() } - pub(crate) fn get_container_name_arg(&self, network: Network) -> String { + pub(crate) fn get_container_name(&self, network: Option) -> String { self.container_name.as_ref().map_or_else( - || network.to_string(), + || { + format!( + "stellar-{}", + network.expect("Container name and/or network are required.") + ) + }, + |container_name| container_name.to_string(), + ) + } + + pub(crate) fn get_container_name_arg(&self, network: Option) -> String { + self.container_name.as_ref().map_or_else( + || { + network + .expect("Container name and/or network are required.") + .to_string() + }, |container_name| format!("--container-name {container_name}"), ) } @@ -175,14 +191,3 @@ async fn check_docker_connection(docker: &Docker) -> Result<(), bollard::errors: } } } - -pub fn get_container_name(container_name_arg: Option, network: Option) -> String { - if let Some(container_name) = container_name_arg { - container_name.to_string() - } else { - format!( - "stellar-{}", - network.expect("Container name and/or network are required.") - ) - } -} diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 26fb976a1..f9b5efdf0 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -8,7 +8,7 @@ use bollard::{ use futures_util::TryStreamExt; use crate::commands::network::container::shared::{ - connect_to_docker, get_container_name, Error as ConnectionError, Network, + connect_to_docker, Error as ConnectionError, Network, }; use super::shared::Args; @@ -89,8 +89,7 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { ..Default::default() }; - let container_name = - get_container_name(cmd.container_args.container_name.clone(), Some(cmd.network)); + let container_name = cmd.container_args.get_container_name(Some(cmd.network)); let create_container_response = docker .create_container( Some(CreateContainerOptions { @@ -116,7 +115,7 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { fn print_log_message(cmd: &Cmd) { let log_message = format!( "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", - arg = cmd.container_args.get_container_name_arg(cmd.network), + arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -125,7 +124,7 @@ fn print_log_message(cmd: &Cmd) { fn print_stop_message(cmd: &Cmd) { let stop_message = format!( "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", - arg = cmd.container_args.get_container_name_arg(cmd.network), + arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{stop_message}"); diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index eb7083681..596fcab41 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,5 +1,5 @@ use crate::commands::network::container::shared::{ - connect_to_docker, get_container_name, Error as BollardConnectionError, Network, + connect_to_docker, Error as BollardConnectionError, Network, }; use super::shared::Args; @@ -32,8 +32,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = - get_container_name(self.container_args.container_name.clone(), self.network); + let container_name = self.container_args.get_container_name(self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; println!("ℹ️ Stopping container: {container_name}"); docker From 8704b32641728080a1137ab884a1fa22453000d2 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:01:25 -0400 Subject: [PATCH 14/32] Add a comment explaining get_container_name_arg --- cmd/soroban-cli/src/commands/network/container/shared.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 06eace70d..d2d0ccef7 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -62,6 +62,10 @@ impl Args { ) } + // This method is used in start.rs to create a message for the user to let them know how to stop the container they + // just started, and how to view its logs. For both `stop` and `logs` the user is able to pass in either the network + // (and we generate the container name) or the container name directly. Which is why we need to check if the + // container_name is present or not here. pub(crate) fn get_container_name_arg(&self, network: Option) -> String { self.container_name.as_ref().map_or_else( || { From 479fb13fb941e97abf7aa725fd7182d2e4975f00 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:34:11 -0400 Subject: [PATCH 15/32] Clean up doc comments --- cmd/soroban-cli/src/commands/network/container.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container.rs b/cmd/soroban-cli/src/commands/network/container.rs index a65140469..511c0e11b 100644 --- a/cmd/soroban-cli/src/commands/network/container.rs +++ b/cmd/soroban-cli/src/commands/network/container.rs @@ -10,10 +10,8 @@ pub type StopCmd = stop::Cmd; #[derive(Debug, clap::Subcommand)] pub enum Cmd { - /// Tail logs of a running network container + /// Get logs from a running network container Logs(logs::Cmd), - /// Start network - /// /// Start a container running a Stellar node, RPC, API, and friendbot (faucet). /// /// `stellar network container start NETWORK [OPTIONS]` @@ -22,7 +20,7 @@ pub enum Cmd { /// /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(start::Cmd), - /// Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it. + /// Stop a network container started with `network container start`. Stop(stop::Cmd), } From 305c2815b4d969ce8a09f0708f2997fb690b2de4 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:39:20 -0400 Subject: [PATCH 16/32] Simplify stop and logs commmands Instead of allowing these commands to take in either --network or --container_name this commit change these commands to just require the name of the container This commit also renames the container_name args to name --- .../src/commands/network/container/logs.rs | 11 +++---- .../src/commands/network/container/shared.rs | 31 ------------------- .../src/commands/network/container/start.rs | 21 ++++++++++--- .../src/commands/network/container/stop.rs | 9 +++--- 4 files changed, 24 insertions(+), 48 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index c21511295..6c8158832 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,8 +1,6 @@ use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, -}; +use crate::commands::network::container::shared::{connect_to_docker, Error as ConnectionError}; use super::shared::Args; @@ -20,14 +18,13 @@ pub struct Cmd { #[command(flatten)] pub container_args: Args, - /// Network container to tail (used in container name generation) - #[arg(required_unless_present = "container_name")] - pub network: Option, + /// Container to get logs from + pub name: String, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.container_args.get_container_name(self.network); + let container_name = self.name.clone(); let docker = connect_to_docker(&self.container_args.docker_host).await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index d2d0ccef7..bf37dc7a2 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -33,10 +33,6 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Args { - /// Optional argument to specify the container name - #[arg(short = 'c', long, required_unless_present = "network")] - pub container_name: Option, - /// 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 #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] pub docker_host: Option, @@ -49,33 +45,6 @@ impl Args { .map(|docker_host| format!("--docker-host {docker_host}")) .unwrap_or_default() } - - pub(crate) fn get_container_name(&self, network: Option) -> String { - self.container_name.as_ref().map_or_else( - || { - format!( - "stellar-{}", - network.expect("Container name and/or network are required.") - ) - }, - |container_name| container_name.to_string(), - ) - } - - // This method is used in start.rs to create a message for the user to let them know how to stop the container they - // just started, and how to view its logs. For both `stop` and `logs` the user is able to pass in either the network - // (and we generate the container name) or the container name directly. Which is why we need to check if the - // container_name is present or not here. - pub(crate) fn get_container_name_arg(&self, network: Option) -> String { - self.container_name.as_ref().map_or_else( - || { - network - .expect("Container name and/or network are required.") - .to_string() - }, - |container_name| format!("--container-name {container_name}"), - ) - } } #[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index f9b5efdf0..fcb0429d4 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -33,6 +33,10 @@ pub struct Cmd { /// Network to start pub network: Network, + /// Optional argument to specify the container name + #[arg(long)] + pub name: Option, + /// Optional argument to specify the limits for the local network only #[arg(short = 'l', long)] pub limits: Option, @@ -89,7 +93,7 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { ..Default::default() }; - let container_name = cmd.container_args.get_container_name(Some(cmd.network)); + let container_name = get_container_name(cmd); let create_container_response = docker .create_container( Some(CreateContainerOptions { @@ -112,10 +116,17 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { Ok(()) } +fn get_container_name(cmd: &Cmd) -> String { + cmd.name.as_ref().map_or_else( + || format!("stellar-{}", cmd.network), + std::string::ToString::to_string, + ) +} + fn print_log_message(cmd: &Cmd) { let log_message = format!( - "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", - arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), + "ℹ️ To see the logs for this container run: stellar network container logs {name} {additional_flags}", + name = get_container_name(cmd), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -123,8 +134,8 @@ fn print_log_message(cmd: &Cmd) { fn print_stop_message(cmd: &Cmd) { let stop_message = format!( - "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", - arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), + "ℹ️ To stop this container run: stellar network container stop {name} {additional_flags}", + name = get_container_name(cmd), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{stop_message}"); diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 596fcab41..63b7e6ac8 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,5 +1,5 @@ use crate::commands::network::container::shared::{ - connect_to_docker, Error as BollardConnectionError, Network, + connect_to_docker, Error as BollardConnectionError, }; use super::shared::Args; @@ -25,14 +25,13 @@ pub struct Cmd { #[command(flatten)] pub container_args: Args, - /// Network to stop (used in container name generation) - #[arg(required_unless_present = "container_name")] - pub network: Option, + /// Container to stop + pub name: String, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.container_args.get_container_name(self.network); + let container_name = self.name.clone(); let docker = connect_to_docker(&self.container_args.docker_host).await?; println!("ℹ️ Stopping container: {container_name}"); docker From 2f17a584f3d3f7b0ff56870a75fa5a38bce41f2d Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:45:38 -0400 Subject: [PATCH 17/32] Update the docs --- FULL_HELP_DOCS.md | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 62719586a..0a277898e 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1073,8 +1073,8 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** -* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 +* `--name ` — Optional argument to specify the container name * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1090,18 +1090,14 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network started with `network start`. For example, if you ran `stellar network start local`, you can use `stellar network stop local` to stop it. -**Usage:** `stellar network stop [OPTIONS] [NETWORK]` +**Usage:** `stellar network stop [OPTIONS] ` ###### **Arguments:** -* `` — Network to stop (used in container name generation) - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to stop ###### **Options:** -* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1114,36 +1110,30 @@ Commands to start, stop and get logs for a quickstart container ###### **Subcommands:** -* `logs` — Tail logs of a running network container -* `start` — Start network -* `stop` — Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it +* `logs` — Get logs of a running network container +* `start` — Start a container running a Stellar node, RPC, API, and friendbot (faucet) +* `stop` — Stop a network container started with `network container start` ## `stellar network container logs` -Tail logs of a running network container +Get logs of a running network container -**Usage:** `stellar network container logs [OPTIONS] [NETWORK]` +**Usage:** `stellar network container logs [OPTIONS] ` ###### **Arguments:** -* `` — Network container to tail (used in container name generation) - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to get logs from ###### **Options:** -* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 ## `stellar network container start` -Start network - Start a container running a Stellar node, RPC, API, and friendbot (faucet). `stellar network container start NETWORK [OPTIONS]` @@ -1163,8 +1153,8 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** -* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 +* `--name ` — Optional argument to specify the container name * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1176,20 +1166,16 @@ By default, when starting a testnet container, without any optional arguments, i ## `stellar network container stop` -Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it +Stop a network container started with `network container start` -**Usage:** `stellar network container stop [OPTIONS] [NETWORK]` +**Usage:** `stellar network container stop [OPTIONS] ` ###### **Arguments:** -* `` — Network to stop (used in container name generation) - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to stop ###### **Options:** -* `-c`, `--container-name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 From 299e036faa22568f23afda7f7ffb590ba59d7bda Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:34:28 -0400 Subject: [PATCH 18/32] Revert "Simplify stop and logs commmands" This reverts commit d21365a0404be7a37201626dd1ecf073b706e089. --- .../src/commands/network/container/logs.rs | 11 ++++--- .../src/commands/network/container/shared.rs | 31 +++++++++++++++++++ .../src/commands/network/container/start.rs | 21 +++---------- .../src/commands/network/container/stop.rs | 9 +++--- 4 files changed, 48 insertions(+), 24 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index 6c8158832..c21511295 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,6 +1,8 @@ use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{connect_to_docker, Error as ConnectionError}; +use crate::commands::network::container::shared::{ + connect_to_docker, Error as ConnectionError, Network, +}; use super::shared::Args; @@ -18,13 +20,14 @@ pub struct Cmd { #[command(flatten)] pub container_args: Args, - /// Container to get logs from - pub name: String, + /// Network container to tail (used in container name generation) + #[arg(required_unless_present = "container_name")] + pub network: Option, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.name.clone(); + let container_name = self.container_args.get_container_name(self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index bf37dc7a2..d2d0ccef7 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -33,6 +33,10 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Args { + /// Optional argument to specify the container name + #[arg(short = 'c', long, required_unless_present = "network")] + pub container_name: Option, + /// 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 #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] pub docker_host: Option, @@ -45,6 +49,33 @@ impl Args { .map(|docker_host| format!("--docker-host {docker_host}")) .unwrap_or_default() } + + pub(crate) fn get_container_name(&self, network: Option) -> String { + self.container_name.as_ref().map_or_else( + || { + format!( + "stellar-{}", + network.expect("Container name and/or network are required.") + ) + }, + |container_name| container_name.to_string(), + ) + } + + // This method is used in start.rs to create a message for the user to let them know how to stop the container they + // just started, and how to view its logs. For both `stop` and `logs` the user is able to pass in either the network + // (and we generate the container name) or the container name directly. Which is why we need to check if the + // container_name is present or not here. + pub(crate) fn get_container_name_arg(&self, network: Option) -> String { + self.container_name.as_ref().map_or_else( + || { + network + .expect("Container name and/or network are required.") + .to_string() + }, + |container_name| format!("--container-name {container_name}"), + ) + } } #[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index fcb0429d4..f9b5efdf0 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -33,10 +33,6 @@ pub struct Cmd { /// Network to start pub network: Network, - /// Optional argument to specify the container name - #[arg(long)] - pub name: Option, - /// Optional argument to specify the limits for the local network only #[arg(short = 'l', long)] pub limits: Option, @@ -93,7 +89,7 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { ..Default::default() }; - let container_name = get_container_name(cmd); + let container_name = cmd.container_args.get_container_name(Some(cmd.network)); let create_container_response = docker .create_container( Some(CreateContainerOptions { @@ -116,17 +112,10 @@ async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { Ok(()) } -fn get_container_name(cmd: &Cmd) -> String { - cmd.name.as_ref().map_or_else( - || format!("stellar-{}", cmd.network), - std::string::ToString::to_string, - ) -} - fn print_log_message(cmd: &Cmd) { let log_message = format!( - "ℹ️ To see the logs for this container run: stellar network container logs {name} {additional_flags}", - name = get_container_name(cmd), + "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", + arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -134,8 +123,8 @@ fn print_log_message(cmd: &Cmd) { fn print_stop_message(cmd: &Cmd) { let stop_message = format!( - "ℹ️ To stop this container run: stellar network container stop {name} {additional_flags}", - name = get_container_name(cmd), + "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", + arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), additional_flags = cmd.container_args.get_additional_flags(), ); println!("{stop_message}"); diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 63b7e6ac8..596fcab41 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,5 +1,5 @@ use crate::commands::network::container::shared::{ - connect_to_docker, Error as BollardConnectionError, + connect_to_docker, Error as BollardConnectionError, Network, }; use super::shared::Args; @@ -25,13 +25,14 @@ pub struct Cmd { #[command(flatten)] pub container_args: Args, - /// Container to stop - pub name: String, + /// Network to stop (used in container name generation) + #[arg(required_unless_present = "container_name")] + pub network: Option, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.name.clone(); + let container_name = self.container_args.get_container_name(self.network); let docker = connect_to_docker(&self.container_args.docker_host).await?; println!("ℹ️ Stopping container: {container_name}"); docker From c2670e2271df12cfadece2fc50b82227eccce481 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:28:15 -0400 Subject: [PATCH 19/32] Rename container_name arg to name --- cmd/soroban-cli/src/commands/network/container/logs.rs | 2 +- .../src/commands/network/container/shared.rs | 10 +++++----- cmd/soroban-cli/src/commands/network/container/stop.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index c21511295..8e9b96437 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -21,7 +21,7 @@ pub struct Cmd { pub container_args: Args, /// Network container to tail (used in container name generation) - #[arg(required_unless_present = "container_name")] + #[arg(required_unless_present = "name")] pub network: Option, } diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index d2d0ccef7..3f2a544bc 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -34,8 +34,8 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Args { /// Optional argument to specify the container name - #[arg(short = 'c', long, required_unless_present = "network")] - pub container_name: Option, + #[arg(long, required_unless_present = "network")] + pub name: Option, /// 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 #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] @@ -51,7 +51,7 @@ impl Args { } pub(crate) fn get_container_name(&self, network: Option) -> String { - self.container_name.as_ref().map_or_else( + self.name.as_ref().map_or_else( || { format!( "stellar-{}", @@ -67,13 +67,13 @@ impl Args { // (and we generate the container name) or the container name directly. Which is why we need to check if the // container_name is present or not here. pub(crate) fn get_container_name_arg(&self, network: Option) -> String { - self.container_name.as_ref().map_or_else( + self.name.as_ref().map_or_else( || { network .expect("Container name and/or network are required.") .to_string() }, - |container_name| format!("--container-name {container_name}"), + |container_name| format!("--name {container_name}"), ) } } diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 596fcab41..8ddb5d58e 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -26,7 +26,7 @@ pub struct Cmd { pub container_args: Args, /// Network to stop (used in container name generation) - #[arg(required_unless_present = "container_name")] + #[arg(required_unless_present = "name")] pub network: Option, } From a9fa5b013a169acc258b67c0b4bf2b97deb170a4 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:44:35 -0400 Subject: [PATCH 20/32] Update help docs --- FULL_HELP_DOCS.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 0a277898e..3bfca9fe5 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1073,8 +1073,8 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** -* `-d`, `--docker-host ` — 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 * `--name ` — Optional argument to specify the container name +* `-d`, `--docker-host ` — 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 * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1090,14 +1090,18 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network started with `network start`. For example, if you ran `stellar network start local`, you can use `stellar network stop local` to stop it. -**Usage:** `stellar network stop [OPTIONS] ` +**Usage:** `stellar network stop [OPTIONS] [NETWORK]` ###### **Arguments:** -* `` — Container to stop +* `` — Network to stop (used in container name generation) + + Possible values: `local`, `testnet`, `futurenet`, `pubnet` + ###### **Options:** +* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1110,7 +1114,7 @@ Commands to start, stop and get logs for a quickstart container ###### **Subcommands:** -* `logs` — Get logs of a running network container +* `logs` — Get logs from a running network container * `start` — Start a container running a Stellar node, RPC, API, and friendbot (faucet) * `stop` — Stop a network container started with `network container start` @@ -1118,16 +1122,20 @@ Commands to start, stop and get logs for a quickstart container ## `stellar network container logs` -Get logs of a running network container +Get logs from a running network container -**Usage:** `stellar network container logs [OPTIONS] ` +**Usage:** `stellar network container logs [OPTIONS] [NETWORK]` ###### **Arguments:** -* `` — Container to get logs from +* `` — Network container to tail (used in container name generation) + + Possible values: `local`, `testnet`, `futurenet`, `pubnet` + ###### **Options:** +* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1153,8 +1161,8 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** -* `-d`, `--docker-host ` — 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 * `--name ` — Optional argument to specify the container name +* `-d`, `--docker-host ` — 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 * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1168,14 +1176,18 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network container started with `network container start` -**Usage:** `stellar network container stop [OPTIONS] ` +**Usage:** `stellar network container stop [OPTIONS] [NETWORK]` ###### **Arguments:** -* `` — Container to stop +* `` — Network to stop (used in container name generation) + + Possible values: `local`, `testnet`, `futurenet`, `pubnet` + ###### **Options:** +* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 From aac2440894a59f4eb7bd7929b9256e27ccf8089f Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:00:34 -0400 Subject: [PATCH 21/32] Clippy --- cmd/soroban-cli/src/commands/network/container/shared.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 3f2a544bc..c45a43be6 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -58,7 +58,7 @@ impl Args { network.expect("Container name and/or network are required.") ) }, - |container_name| container_name.to_string(), + std::string::ToString::to_string, ) } From 3ed3586d1ca79898592f2239d2179d7aa9b38e71 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:17:08 -0400 Subject: [PATCH 22/32] Move connect_to_docker to Arg impl --- .../src/commands/network/container/logs.rs | 6 +- .../src/commands/network/container/shared.rs | 116 +++++++++--------- .../src/commands/network/container/start.rs | 6 +- .../src/commands/network/container/stop.rs | 6 +- 4 files changed, 64 insertions(+), 70 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index 8e9b96437..c4354f653 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,8 +1,6 @@ use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, -}; +use crate::commands::network::container::shared::{Error as ConnectionError, Network}; use super::shared::Args; @@ -28,7 +26,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { let container_name = self.container_args.get_container_name(self.network); - let docker = connect_to_docker(&self.container_args.docker_host).await?; + let docker = self.container_args.connect_to_docker().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 c45a43be6..e81fef42b 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -76,6 +76,64 @@ impl Args { |container_name| format!("--name {container_name}"), ) } + + pub(crate) async fn connect_to_docker(&self) -> 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 + let host = self.docker_host.as_ref().map_or_else( + || DEFAULT_DOCKER_HOST.to_string(), + std::string::ToString::to_string, + ); + + // this is based on the `connect_with_defaults` method which has not yet been released in the bollard crate + // https://github.com/fussybeaver/bollard/blob/0972b1aac0ad5c08798e100319ddd0d2ee010365/src/docker.rs#L660 + let connection = match host.clone() { + // if tcp or http, use connect_with_http_defaults + // if unix and host starts with "unix://" use connect_with_unix + // if windows and host starts with "npipe://", use connect_with_named_pipe + // else default to connect_with_unix + h if h.starts_with("tcp://") || h.starts_with("http://") => { + Docker::connect_with_http_defaults() + } + #[cfg(unix)] + h if h.starts_with("unix://") => { + Docker::connect_with_unix(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) + } + #[cfg(windows)] + h if h.starts_with("npipe://") => { + Docker::connect_with_named_pipe(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) + } + _ => { + return Err(Error::UnsupportedURISchemeError { + uri: host.to_string(), + }); + } + }?; + + match check_docker_connection(&connection).await { + Ok(()) => Ok(connection), + // If we aren't able to connect with the defaults, or with the provided docker_host + // try to connect with the default docker desktop socket since that is a common use case for devs + #[allow(unused_variables)] + Err(e) => { + // if on unix, try to connect to the default docker desktop socket + #[cfg(unix)] + { + let docker_desktop_connection = try_docker_desktop_socket(&host)?; + match check_docker_connection(&docker_desktop_connection).await { + Ok(()) => Ok(docker_desktop_connection), + Err(err) => Err(err)?, + } + } + + #[cfg(windows)] + { + Err(e)? + } + } + } + } } #[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] @@ -99,64 +157,6 @@ impl fmt::Display for Network { } } -pub async fn connect_to_docker(docker_host: &Option) -> 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 - - let host = docker_host - .clone() - .unwrap_or(DEFAULT_DOCKER_HOST.to_string()); - - // this is based on the `connect_with_defaults` method which has not yet been released in the bollard crate - // https://github.com/fussybeaver/bollard/blob/0972b1aac0ad5c08798e100319ddd0d2ee010365/src/docker.rs#L660 - let connection = match host.clone() { - // if tcp or http, use connect_with_http_defaults - // if unix and host starts with "unix://" use connect_with_unix - // if windows and host starts with "npipe://", use connect_with_named_pipe - // else default to connect_with_unix - h if h.starts_with("tcp://") || h.starts_with("http://") => { - Docker::connect_with_http_defaults() - } - #[cfg(unix)] - h if h.starts_with("unix://") => { - Docker::connect_with_unix(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) - } - #[cfg(windows)] - h if h.starts_with("npipe://") => { - Docker::connect_with_named_pipe(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) - } - _ => { - return Err(Error::UnsupportedURISchemeError { - uri: host.to_string(), - }); - } - }?; - - match check_docker_connection(&connection).await { - Ok(()) => Ok(connection), - // If we aren't able to connect with the defaults, or with the provided docker_host - // try to connect with the default docker desktop socket since that is a common use case for devs - #[allow(unused_variables)] - Err(e) => { - // if on unix, try to connect to the default docker desktop socket - #[cfg(unix)] - { - let docker_desktop_connection = try_docker_desktop_socket(&host)?; - match check_docker_connection(&docker_desktop_connection).await { - Ok(()) => Ok(docker_desktop_connection), - Err(err) => Err(err)?, - } - } - - #[cfg(windows)] - { - Err(e)? - } - } - } -} - #[cfg(unix)] fn try_docker_desktop_socket(host: &str) -> Result { let default_docker_desktop_host = diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index f9b5efdf0..f8faa46f1 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -7,9 +7,7 @@ use bollard::{ }; use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, -}; +use crate::commands::network::container::shared::{Error as ConnectionError, Network}; use super::shared::Args; @@ -58,7 +56,7 @@ impl Cmd { } async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { - let docker = connect_to_docker(&cmd.container_args.docker_host).await?; + let docker = cmd.container_args.connect_to_docker().await?; let image = get_image_name(cmd); docker diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 8ddb5d58e..199c5d40c 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,6 +1,4 @@ -use crate::commands::network::container::shared::{ - connect_to_docker, Error as BollardConnectionError, Network, -}; +use crate::commands::network::container::shared::{Error as BollardConnectionError, Network}; use super::shared::Args; @@ -33,7 +31,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { let container_name = self.container_args.get_container_name(self.network); - let docker = connect_to_docker(&self.container_args.docker_host).await?; + let docker = self.container_args.connect_to_docker().await?; println!("ℹ️ Stopping container: {container_name}"); docker .stop_container(&container_name, None) From fcb28dc73d547d060e518b2628ba21790c010b13 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:40:16 -0400 Subject: [PATCH 23/32] Refactor start command: move helper fns to Cmd impl --- .../src/commands/network/container/start.rs | 250 +++++++++--------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index f8faa46f1..82653c4ef 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -51,146 +51,146 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { println!("ℹ️ Starting {} network", &self.network); - run_docker_command(self).await + self.run_docker_command().await } -} - -async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { - let docker = cmd.container_args.connect_to_docker().await?; - let image = get_image_name(cmd); - docker - .create_image( - Some(CreateImageOptions { - from_image: image.clone(), + async fn run_docker_command(&self) -> Result<(), Error> { + let docker = self.container_args.connect_to_docker().await?; + + let image = self.get_image_name(); + docker + .create_image( + Some(CreateImageOptions { + from_image: image.clone(), + ..Default::default() + }), + None, + None, + ) + .try_collect::>() + .await?; + + let config = Config { + image: Some(image), + cmd: Some(self.get_container_args()), + attach_stdout: Some(true), + attach_stderr: Some(true), + host_config: Some(HostConfig { + auto_remove: Some(true), + port_bindings: Some(self.get_port_mapping()), ..Default::default() }), - None, - None, - ) - .try_collect::>() - .await?; - - let container_args = get_container_args(cmd); - let port_mapping = get_port_mapping(cmd); - - let config = Config { - image: Some(image), - cmd: Some(container_args), - attach_stdout: Some(true), - attach_stderr: Some(true), - host_config: Some(HostConfig { - auto_remove: Some(true), - port_bindings: Some(port_mapping), ..Default::default() - }), - ..Default::default() - }; - - let container_name = cmd.container_args.get_container_name(Some(cmd.network)); - let create_container_response = docker - .create_container( - Some(CreateContainerOptions { - name: container_name.clone(), - ..Default::default() - }), - config, - ) - .await?; - - docker - .start_container( - &create_container_response.id, - None::>, - ) - .await?; - println!("✅ Container started: {container_name}"); - print_log_message(cmd); - print_stop_message(cmd); - Ok(()) -} - -fn print_log_message(cmd: &Cmd) { - let log_message = format!( - "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", - arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), - additional_flags = cmd.container_args.get_additional_flags(), - ); - println!("{log_message}"); -} - -fn print_stop_message(cmd: &Cmd) { - let stop_message = format!( - "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", - arg = cmd.container_args.get_container_name_arg(Some(cmd.network)), - additional_flags = cmd.container_args.get_additional_flags(), - ); - println!("{stop_message}"); -} + }; + + let container_name = self.container_args.get_container_name(Some(self.network)); + let create_container_response = docker + .create_container( + Some(CreateContainerOptions { + name: container_name.clone(), + ..Default::default() + }), + config, + ) + .await?; + + docker + .start_container( + &create_container_response.id, + None::>, + ) + .await?; + println!("✅ Container started: {container_name}"); + self.print_log_message(); + self.print_stop_message(); + Ok(()) + } -fn get_container_args(cmd: &Cmd) -> Vec { - [ - format!("--{}", cmd.network), - "--enable rpc,horizon".to_string(), - get_protocol_version_arg(cmd), - get_limits_arg(cmd), - ] - .iter() - .filter(|&s| !s.is_empty()) - .cloned() - .collect() -} + fn get_image_name(&self) -> String { + // this can be overriden with the `-t` flag + let mut image_tag = match &self.network { + Network::Pubnet => "latest", + Network::Futurenet => "future", + _ => "testing", // default to testing for local and testnet + }; + + if let Some(image_override) = &self.image_tag_override { + println!( + "Overriding docker image tag to use '{image_override}' instead of '{image_tag}'" + ); + image_tag = image_override; + } + + format!("{DOCKER_IMAGE}:{image_tag}") + } -fn get_image_name(cmd: &Cmd) -> String { - // this can be overriden with the `-t` flag - let mut image_tag = match cmd.network { - Network::Pubnet => "latest", - Network::Futurenet => "future", - _ => "testing", // default to testing for local and testnet - }; - - if let Some(image_override) = &cmd.image_tag_override { - println!("Overriding docker image tag to use '{image_override}' instead of '{image_tag}'"); - image_tag = image_override; + fn get_container_args(&self) -> Vec { + [ + format!("--{}", self.network), + "--enable rpc,horizon".to_string(), + self.get_protocol_version_arg(), + self.get_limits_arg(), + ] + .iter() + .filter(|&s| !s.is_empty()) + .cloned() + .collect() } - format!("{DOCKER_IMAGE}:{image_tag}") -} + // The port mapping in the bollard crate is formatted differently than the docker CLI. In the docker CLI, we usually specify exposed ports as `-p HOST_PORT:CONTAINER_PORT`. But with the bollard crate, it is expecting the port mapping to be a map of the container port (with the protocol) to the host port. + fn get_port_mapping(&self) -> HashMap>> { + let mut port_mapping_hash = HashMap::new(); + for port_mapping in &self.ports_mapping { + let ports_vec: Vec<&str> = port_mapping.split(':').collect(); + let from_port = ports_vec[0]; + let to_port = ports_vec[1]; + + port_mapping_hash.insert( + format!("{to_port}/tcp"), + Some(vec![PortBinding { + host_ip: None, + host_port: Some(from_port.to_string()), + }]), + ); + } + + port_mapping_hash + } -// The port mapping in the bollard crate is formatted differently than the docker CLI. In the docker CLI, we usually specify exposed ports as `-p HOST_PORT:CONTAINER_PORT`. But with the bollard crate, it is expecting the port mapping to be a map of the container port (with the protocol) to the host port. -fn get_port_mapping(cmd: &Cmd) -> HashMap>> { - let mut port_mapping_hash = HashMap::new(); - for port_mapping in &cmd.ports_mapping { - let ports_vec: Vec<&str> = port_mapping.split(':').collect(); - let from_port = ports_vec[0]; - let to_port = ports_vec[1]; - - port_mapping_hash.insert( - format!("{to_port}/tcp"), - Some(vec![PortBinding { - host_ip: None, - host_port: Some(from_port.to_string()), - }]), + fn print_log_message(&self) { + let log_message = format!( + "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", + arg = self.container_args.get_container_name_arg(Some(self.network)), + additional_flags = self.container_args.get_additional_flags(), ); + println!("{log_message}"); } - port_mapping_hash -} + fn print_stop_message(&self) { + let stop_message = + format!( + "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", + arg = self.container_args.get_container_name_arg(Some(self.network)), + additional_flags = self.container_args.get_additional_flags(), + ); + println!("{stop_message}"); + } -fn get_protocol_version_arg(cmd: &Cmd) -> String { - if cmd.network == Network::Local && cmd.protocol_version.is_some() { - let version = cmd.protocol_version.as_ref().unwrap(); - format!("--protocol-version {version}") - } else { - String::new() + fn get_protocol_version_arg(&self) -> String { + if self.network == Network::Local && self.protocol_version.is_some() { + let version = self.protocol_version.as_ref().unwrap(); + format!("--protocol-version {version}") + } else { + String::new() + } } -} -fn get_limits_arg(cmd: &Cmd) -> String { - if cmd.network == Network::Local && cmd.limits.is_some() { - let limits = cmd.limits.as_ref().unwrap(); - format!("--limits {limits}") - } else { - String::new() + fn get_limits_arg(&self) -> String { + if self.network == Network::Local && self.limits.is_some() { + let limits = self.limits.as_ref().unwrap(); + format!("--limits {limits}") + } else { + String::new() + } } } From e997527f5320b7b66c3cb975ef130e54f8b706c4 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 18:08:32 -0400 Subject: [PATCH 24/32] Default container name to network name instead of prepending it with stellar. This will simplify logs and stop commands. --- .../src/commands/network/container/shared.rs | 18 +----------------- .../src/commands/network/container/start.rs | 8 ++++---- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index e81fef42b..f68e0453f 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -51,29 +51,13 @@ impl Args { } pub(crate) fn get_container_name(&self, network: Option) -> String { - self.name.as_ref().map_or_else( - || { - format!( - "stellar-{}", - network.expect("Container name and/or network are required.") - ) - }, - std::string::ToString::to_string, - ) - } - - // This method is used in start.rs to create a message for the user to let them know how to stop the container they - // just started, and how to view its logs. For both `stop` and `logs` the user is able to pass in either the network - // (and we generate the container name) or the container name directly. Which is why we need to check if the - // container_name is present or not here. - pub(crate) fn get_container_name_arg(&self, network: Option) -> String { self.name.as_ref().map_or_else( || { network .expect("Container name and/or network are required.") .to_string() }, - |container_name| format!("--name {container_name}"), + std::string::ToString::to_string, ) } diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 82653c4ef..329db8fe1 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -159,8 +159,8 @@ impl Cmd { fn print_log_message(&self) { let log_message = format!( - "ℹ️ To see the logs for this container run: stellar network container logs {arg} {additional_flags}", - arg = self.container_args.get_container_name_arg(Some(self.network)), + "ℹ️ To see the logs for this container run: stellar network container logs {container_name} {additional_flags}", + container_name = self.container_args.get_container_name(Some(self.network)), additional_flags = self.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -169,8 +169,8 @@ impl Cmd { fn print_stop_message(&self) { let stop_message = format!( - "ℹ️ To stop this container run: stellar network container stop {arg} {additional_flags}", - arg = self.container_args.get_container_name_arg(Some(self.network)), + "ℹ️ To stop this container run: stellar network container stop {container_name} {additional_flags}", + container_name = self.container_args.get_container_name(Some(self.network)), additional_flags = self.container_args.get_additional_flags(), ); println!("{stop_message}"); From aadfc6348c0f00028fc491d90c2375640d15483e Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 18:38:39 -0400 Subject: [PATCH 25/32] Update stop and logs commands to accept the container name instead of the network. --- .../src/commands/network/container/logs.rs | 9 ++++----- .../src/commands/network/container/shared.rs | 15 --------------- .../src/commands/network/container/start.rs | 17 ++++++++++++++--- .../src/commands/network/container/stop.rs | 9 ++++----- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index c4354f653..c7a5a13cc 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,6 +1,6 @@ use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{Error as ConnectionError, Network}; +use crate::commands::network::container::shared::Error as ConnectionError; use super::shared::Args; @@ -18,14 +18,13 @@ pub struct Cmd { #[command(flatten)] pub container_args: Args, - /// Network container to tail (used in container name generation) - #[arg(required_unless_present = "name")] - pub network: Option, + /// Container to get logs from + pub name: String, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.container_args.get_container_name(self.network); + let container_name = self.name.clone(); let docker = self.container_args.connect_to_docker().await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index f68e0453f..5540f572c 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -33,10 +33,6 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Args { - /// Optional argument to specify the container name - #[arg(long, required_unless_present = "network")] - pub name: Option, - /// 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 #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] pub docker_host: Option, @@ -50,17 +46,6 @@ impl Args { .unwrap_or_default() } - pub(crate) fn get_container_name(&self, network: Option) -> String { - self.name.as_ref().map_or_else( - || { - network - .expect("Container name and/or network are required.") - .to_string() - }, - std::string::ToString::to_string, - ) - } - pub(crate) async fn connect_to_docker(&self) -> Result { // if no docker_host is provided, use the default docker host: // "unix:///var/run/docker.sock" on unix machines diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 329db8fe1..dd6223cfe 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -31,6 +31,10 @@ pub struct Cmd { /// Network to start pub network: Network, + /// Optional argument to specify the container name + #[arg(long)] + pub name: Option, + /// Optional argument to specify the limits for the local network only #[arg(short = 'l', long)] pub limits: Option, @@ -83,7 +87,7 @@ impl Cmd { ..Default::default() }; - let container_name = self.container_args.get_container_name(Some(self.network)); + let container_name = self.get_container_name(); let create_container_response = docker .create_container( Some(CreateContainerOptions { @@ -157,10 +161,17 @@ impl Cmd { port_mapping_hash } + fn get_container_name(&self) -> String { + self.name.as_ref().map_or_else( + || self.network.to_string(), + std::string::ToString::to_string, + ) + } + fn print_log_message(&self) { let log_message = format!( "ℹ️ To see the logs for this container run: stellar network container logs {container_name} {additional_flags}", - container_name = self.container_args.get_container_name(Some(self.network)), + container_name = self.get_container_name(), additional_flags = self.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -170,7 +181,7 @@ impl Cmd { let stop_message = format!( "ℹ️ To stop this container run: stellar network container stop {container_name} {additional_flags}", - container_name = self.container_args.get_container_name(Some(self.network)), + container_name = self.get_container_name(), additional_flags = self.container_args.get_additional_flags(), ); println!("{stop_message}"); diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 199c5d40c..85a670098 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,4 +1,4 @@ -use crate::commands::network::container::shared::{Error as BollardConnectionError, Network}; +use crate::commands::network::container::shared::Error as BollardConnectionError; use super::shared::Args; @@ -23,14 +23,13 @@ pub struct Cmd { #[command(flatten)] pub container_args: Args, - /// Network to stop (used in container name generation) - #[arg(required_unless_present = "name")] - pub network: Option, + /// Container to stop + pub name: String, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.container_args.get_container_name(self.network); + let container_name = self.name.clone(); let docker = self.container_args.connect_to_docker().await?; println!("ℹ️ Stopping container: {container_name}"); docker From e96b8e10429cbac5baba8432eea951e83c7b1735 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Tue, 16 Jul 2024 18:48:18 -0400 Subject: [PATCH 26/32] Update docs --- FULL_HELP_DOCS.md | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 37152ae2d..64fae1b5e 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1073,8 +1073,8 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** -* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 +* `--name ` — Optional argument to specify the container name * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1090,18 +1090,14 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network started with `network start`. For example, if you ran `stellar network start local`, you can use `stellar network stop local` to stop it. -**Usage:** `stellar network stop [OPTIONS] [NETWORK]` +**Usage:** `stellar network stop [OPTIONS] ` ###### **Arguments:** -* `` — Network to stop (used in container name generation) - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to stop ###### **Options:** -* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1124,18 +1120,14 @@ Commands to start, stop and get logs for a quickstart container Get logs from a running network container -**Usage:** `stellar network container logs [OPTIONS] [NETWORK]` +**Usage:** `stellar network container logs [OPTIONS] ` ###### **Arguments:** -* `` — Network container to tail (used in container name generation) - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to get logs from ###### **Options:** -* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 @@ -1161,8 +1153,8 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** -* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 +* `--name ` — Optional argument to specify the container name * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1176,18 +1168,14 @@ By default, when starting a testnet container, without any optional arguments, i Stop a network container started with `network container start` -**Usage:** `stellar network container stop [OPTIONS] [NETWORK]` +**Usage:** `stellar network container stop [OPTIONS] ` ###### **Arguments:** -* `` — Network to stop (used in container name generation) - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to stop ###### **Options:** -* `--name ` — Optional argument to specify the container name * `-d`, `--docker-host ` — 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 From 0c955628079da34baeb509b88b7430d21163669c Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:11:15 -0400 Subject: [PATCH 27/32] Create a Name type to handle internal vs external name conventions --- .../src/commands/network/container/shared.rs | 29 +++++++++++++++++++ .../src/commands/network/container/start.rs | 21 +++++++------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 5540f572c..c197e721d 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -126,6 +126,35 @@ impl fmt::Display for Network { } } +pub struct Name(Option, Option); +impl Name { + pub fn new(name: Option, network: Option) -> Self { + Self(name, network) + } + + pub fn get_internal_container_name(&self) -> String { + self.0.as_ref().map_or_else( + || { + self.1 + .expect("Container name and/or network are required.") + .to_string() + }, + std::string::ToString::to_string, + ) + } + + pub fn get_external_container_name(&self) -> String { + self.0.as_ref().map_or_else( + || { + self.1 + .expect("Container name and/or network are required.") + .to_string() + }, + std::string::ToString::to_string, + ) + } +} + #[cfg(unix)] fn try_docker_desktop_socket(host: &str) -> Result { let default_docker_desktop_host = diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index dd6223cfe..7fb4f9450 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -9,7 +9,7 @@ use futures_util::TryStreamExt; use crate::commands::network::container::shared::{Error as ConnectionError, Network}; -use super::shared::Args; +use super::shared::{Args, Name}; const DEFAULT_PORT_MAPPING: &str = "8000:8000"; const DOCKER_IMAGE: &str = "docker.io/stellar/quickstart"; @@ -87,11 +87,10 @@ impl Cmd { ..Default::default() }; - let container_name = self.get_container_name(); let create_container_response = docker .create_container( Some(CreateContainerOptions { - name: container_name.clone(), + name: self.container_name().get_internal_container_name(), ..Default::default() }), config, @@ -104,7 +103,10 @@ impl Cmd { None::>, ) .await?; - println!("✅ Container started: {container_name}"); + println!( + "✅ Container started: {}", + self.container_name().get_external_container_name() + ); self.print_log_message(); self.print_stop_message(); Ok(()) @@ -161,17 +163,14 @@ impl Cmd { port_mapping_hash } - fn get_container_name(&self) -> String { - self.name.as_ref().map_or_else( - || self.network.to_string(), - std::string::ToString::to_string, - ) + fn container_name(&self) -> Name { + Name::new(self.name.clone(), Some(self.network)) } fn print_log_message(&self) { let log_message = format!( "ℹ️ To see the logs for this container run: stellar network container logs {container_name} {additional_flags}", - container_name = self.get_container_name(), + container_name = self.container_name().get_external_container_name(), additional_flags = self.container_args.get_additional_flags(), ); println!("{log_message}"); @@ -181,7 +180,7 @@ impl Cmd { let stop_message = format!( "ℹ️ To stop this container run: stellar network container stop {container_name} {additional_flags}", - container_name = self.get_container_name(), + container_name = self.container_name().get_external_container_name(), additional_flags = self.container_args.get_additional_flags(), ); println!("{stop_message}"); From 235f521fb994ae21f657cf93ad9e3eb949b84494 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:19:53 -0400 Subject: [PATCH 28/32] Prefix container names with 'stellar-' --- .../src/commands/network/container/logs.rs | 4 ++-- .../src/commands/network/container/shared.rs | 11 +++++++---- .../src/commands/network/container/stop.rs | 18 ++++++++++++------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index c7a5a13cc..ceafb2a8b 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -2,7 +2,7 @@ use futures_util::TryStreamExt; use crate::commands::network::container::shared::Error as ConnectionError; -use super::shared::Args; +use super::shared::{Args, Name}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -24,7 +24,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.name.clone(); + let container_name = Name::new(Some(self.name.clone()), None).get_internal_container_name(); let docker = self.container_args.connect_to_docker().await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index c197e721d..f0fe72e12 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -135,11 +135,14 @@ impl Name { pub fn get_internal_container_name(&self) -> String { self.0.as_ref().map_or_else( || { - self.1 - .expect("Container name and/or network are required.") - .to_string() + format!( + "stellar-{}", + self.1 + .expect("Container name and/or network are required.") + .to_string() + ) }, - std::string::ToString::to_string, + |name| format!("stellar-{}", name.to_string()), ) } diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 85a670098..10be48ce4 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,6 +1,6 @@ use crate::commands::network::container::shared::Error as BollardConnectionError; -use super::shared::Args; +use super::shared::{Args, Name}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -29,24 +29,30 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = self.name.clone(); + let container_name = Name::new(Some(self.name.clone()), None); let docker = self.container_args.connect_to_docker().await?; - println!("ℹ️ Stopping container: {container_name}"); + println!( + "ℹ️ Stopping container: {}", + container_name.get_external_container_name() + ); docker - .stop_container(&container_name, None) + .stop_container(&container_name.get_internal_container_name(), None) .await .map_err(|e| { let msg = e.to_string(); if msg.contains("No such container") { Error::ContainerNotFound { - container_name: container_name.clone(), + container_name: container_name.get_external_container_name(), source: e, } } else { Error::ContainerStopFailed(e) } })?; - println!("✅ Container stopped: {container_name}"); + println!( + "✅ Container stopped: {}", + container_name.get_external_container_name() + ); Ok(()) } } From 03d29aca10ed876a1d45e5c298637b10ba2e4e95 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:26:22 -0400 Subject: [PATCH 29/32] Add tests for Name struct --- .../src/commands/network/container/shared.rs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index f0fe72e12..55acdd927 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -196,3 +196,61 @@ async fn check_docker_connection(docker: &Docker) -> Result<(), bollard::errors: } } } + +#[cfg(test)] +mod tests { + use super::*; + + const NETWORK: Network = Network::Local; + const CONTAINER_NAME: &str = "test-name"; + + #[test] + fn test_get_internal_container_name_with_both_args() { + let name = Name::new(Some(CONTAINER_NAME.to_string()), Some(NETWORK)); + assert_eq!(name.get_internal_container_name(), "stellar-test-name"); + } + + #[test] + fn test_get_internal_container_name_with_network() { + let name = Name::new(None, Some(NETWORK)); + assert_eq!(name.get_internal_container_name(), "stellar-local"); + } + + #[test] + fn test_get_internal_container_name_with_name() { + // in practice, this would fail clap validation and we would never get here, but testing anyway + let name = Name::new(Some(CONTAINER_NAME.to_string()), None); + assert_eq!(name.get_internal_container_name(), "stellar-test-name"); + } + + #[test] + #[should_panic] + fn test_get_internal_container_name_with_neither_args() { + Name::new(None, None).get_internal_container_name(); + } + + #[test] + fn test_get_external_container_name_with_both_args() { + let name = Name::new(Some(CONTAINER_NAME.to_string()), Some(NETWORK)); + assert_eq!(name.get_external_container_name(), "test-name"); + } + + #[test] + fn test_get_external_container_name_with_network() { + let name = Name::new(None, Some(NETWORK)); + assert_eq!(name.get_external_container_name(), "local"); + } + + #[test] + fn test_get_external_container_name_with_name() { + // in practice, this would fail clap validation and we would never get here, but testing anyway + let name = Name::new(Some(CONTAINER_NAME.to_string()), None); + assert_eq!(name.get_external_container_name(), "test-name"); + } + + #[test] + #[should_panic] + fn test_get_external_container_name_with_neither_args() { + Name::new(None, None).get_external_container_name(); + } +} From 392e1f6de4e9b2542e81d7936a2f1a8b8a0a092a Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:31:14 -0400 Subject: [PATCH 30/32] Refactor Name fns --- .../src/commands/network/container/shared.rs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 55acdd927..04ec9a807 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -133,28 +133,19 @@ impl Name { } pub fn get_internal_container_name(&self) -> String { - self.0.as_ref().map_or_else( - || { - format!( - "stellar-{}", - self.1 - .expect("Container name and/or network are required.") - .to_string() - ) - }, - |name| format!("stellar-{}", name.to_string()), - ) + match (&self.0, &self.1) { + (Some(name), _) => format!("stellar-{}", name), + (None, Some(network)) => format!("stellar-{}", network), + (None, None) => panic!("Container name and/or network are required."), + } } pub fn get_external_container_name(&self) -> String { - self.0.as_ref().map_or_else( - || { - self.1 - .expect("Container name and/or network are required.") - .to_string() - }, - std::string::ToString::to_string, - ) + match (&self.0, &self.1) { + (Some(name), _) => name.to_string(), + (None, Some(network)) => network.to_string(), + (None, None) => panic!("Container name and/or network are required."), + } } } From ec3d39fe3bf30013d123bc2043f041adc994f90b Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:43:45 -0400 Subject: [PATCH 31/32] Update Name::new to just take in one arg Co-authored-by: Willem Wyndham --- .../src/commands/network/container/logs.rs | 2 +- .../src/commands/network/container/shared.rs | 78 ++----------------- .../src/commands/network/container/start.rs | 2 +- .../src/commands/network/container/stop.rs | 2 +- 4 files changed, 9 insertions(+), 75 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index ceafb2a8b..6d2908edc 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -24,7 +24,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = Name::new(Some(self.name.clone()), None).get_internal_container_name(); + let container_name = Name::new(self.name.clone()).get_internal_container_name(); let docker = self.container_args.connect_to_docker().await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 04ec9a807..5f4ac1166 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -126,26 +126,18 @@ impl fmt::Display for Network { } } -pub struct Name(Option, Option); +pub struct Name(String); impl Name { - pub fn new(name: Option, network: Option) -> Self { - Self(name, network) + pub fn new(name: String) -> Self { + Self(name) } pub fn get_internal_container_name(&self) -> String { - match (&self.0, &self.1) { - (Some(name), _) => format!("stellar-{}", name), - (None, Some(network)) => format!("stellar-{}", network), - (None, None) => panic!("Container name and/or network are required."), - } + format!("stellar-{}", self.0) } pub fn get_external_container_name(&self) -> String { - match (&self.0, &self.1) { - (Some(name), _) => name.to_string(), - (None, Some(network)) => network.to_string(), - (None, None) => panic!("Container name and/or network are required."), - } + self.0.to_string() } } @@ -186,62 +178,4 @@ async fn check_docker_connection(docker: &Docker) -> Result<(), bollard::errors: Err(err) } } -} - -#[cfg(test)] -mod tests { - use super::*; - - const NETWORK: Network = Network::Local; - const CONTAINER_NAME: &str = "test-name"; - - #[test] - fn test_get_internal_container_name_with_both_args() { - let name = Name::new(Some(CONTAINER_NAME.to_string()), Some(NETWORK)); - assert_eq!(name.get_internal_container_name(), "stellar-test-name"); - } - - #[test] - fn test_get_internal_container_name_with_network() { - let name = Name::new(None, Some(NETWORK)); - assert_eq!(name.get_internal_container_name(), "stellar-local"); - } - - #[test] - fn test_get_internal_container_name_with_name() { - // in practice, this would fail clap validation and we would never get here, but testing anyway - let name = Name::new(Some(CONTAINER_NAME.to_string()), None); - assert_eq!(name.get_internal_container_name(), "stellar-test-name"); - } - - #[test] - #[should_panic] - fn test_get_internal_container_name_with_neither_args() { - Name::new(None, None).get_internal_container_name(); - } - - #[test] - fn test_get_external_container_name_with_both_args() { - let name = Name::new(Some(CONTAINER_NAME.to_string()), Some(NETWORK)); - assert_eq!(name.get_external_container_name(), "test-name"); - } - - #[test] - fn test_get_external_container_name_with_network() { - let name = Name::new(None, Some(NETWORK)); - assert_eq!(name.get_external_container_name(), "local"); - } - - #[test] - fn test_get_external_container_name_with_name() { - // in practice, this would fail clap validation and we would never get here, but testing anyway - let name = Name::new(Some(CONTAINER_NAME.to_string()), None); - assert_eq!(name.get_external_container_name(), "test-name"); - } - - #[test] - #[should_panic] - fn test_get_external_container_name_with_neither_args() { - Name::new(None, None).get_external_container_name(); - } -} +} \ No newline at end of file diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 7fb4f9450..35bf166c1 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -164,7 +164,7 @@ impl Cmd { } fn container_name(&self) -> Name { - Name::new(self.name.clone(), Some(self.network)) + Name::new(self.name.clone().unwrap_or(self.network.to_string())) } fn print_log_message(&self) { diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index 10be48ce4..c47dda32d 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -29,7 +29,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = Name::new(Some(self.name.clone()), None); + let container_name = Name::new(self.name.clone()); let docker = self.container_args.connect_to_docker().await?; println!( "ℹ️ Stopping container: {}", From 996dea44071acc13c46fe6dd9ae1ad0fd7a1f5c9 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:30:02 -0400 Subject: [PATCH 32/32] Refactor Name --- cmd/soroban-cli/src/commands/network/container/logs.rs | 2 +- cmd/soroban-cli/src/commands/network/container/shared.rs | 8 ++------ cmd/soroban-cli/src/commands/network/container/start.rs | 2 +- cmd/soroban-cli/src/commands/network/container/stop.rs | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index 6d2908edc..99b36af9b 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -24,7 +24,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = Name::new(self.name.clone()).get_internal_container_name(); + let container_name = Name(self.name.clone()).get_internal_container_name(); let docker = self.container_args.connect_to_docker().await?; let logs_stream = &mut docker.logs( &container_name, diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 5f4ac1166..f819f3ed3 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -126,12 +126,8 @@ impl fmt::Display for Network { } } -pub struct Name(String); +pub struct Name(pub String); impl Name { - pub fn new(name: String) -> Self { - Self(name) - } - pub fn get_internal_container_name(&self) -> String { format!("stellar-{}", self.0) } @@ -178,4 +174,4 @@ async fn check_docker_connection(docker: &Docker) -> Result<(), bollard::errors: Err(err) } } -} \ No newline at end of file +} diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index 35bf166c1..46348c297 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -164,7 +164,7 @@ impl Cmd { } fn container_name(&self) -> Name { - Name::new(self.name.clone().unwrap_or(self.network.to_string())) + Name(self.name.clone().unwrap_or(self.network.to_string())) } fn print_log_message(&self) { diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index c47dda32d..733c86436 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -29,7 +29,7 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = Name::new(self.name.clone()); + let container_name = Name(self.name.clone()); let docker = self.container_args.connect_to_docker().await?; println!( "ℹ️ Stopping container: {}",