Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions testcontainers/src/core/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,16 @@ impl Client {
.map_err(ClientError::RemoveContainer)
}

pub(crate) async fn stop(&self, id: &str) -> Result<(), ClientError> {
pub(crate) async fn stop(
&self,
id: &str,
timeout_seconds: Option<i64>,
) -> Result<(), ClientError> {
self.bollard
.stop_container(id, None)
.stop_container(
id,
timeout_seconds.map(|t| bollard::container::StopContainerOptions { t }),
)
.await
.map_err(ClientError::StopContainer)
}
Expand Down Expand Up @@ -497,10 +504,10 @@ where
message,
} => io::Error::new(
io::ErrorKind::UnexpectedEof,
format!("Docker container has been dropped: {}", message),
format!("Docker container has been dropped: {message}"),
),
bollard::errors::Error::IOError { err } => err,
err => io::Error::new(io::ErrorKind::Other, err),
err => io::Error::other(err),
})
.boxed();
LogStream::new(stream)
Expand Down
24 changes: 20 additions & 4 deletions testcontainers/src/core/containers/async_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ where
let network_settings = self.docker_client.inspect_network(&network_mode).await?;

network_settings.driver.ok_or_else(|| {
TestcontainersError::other(format!("network {} is not in bridge mode", network_mode))
TestcontainersError::other(format!("network {network_mode} is not in bridge mode"))
})?;

let container_network_settings = container_settings
Expand Down Expand Up @@ -280,11 +280,27 @@ where
Ok(())
}

/// Stops the container (not the same with `pause`).
/// Stops the container (not the same with `pause`) using the default 10 second timeout
pub async fn stop(&self) -> Result<()> {
log::debug!("Stopping docker container {}", self.id);
self.stop_with_timeout(None).await?;
Ok(())
}

/// Stops the container with timeout before issuing SIGKILL (not the same with `pause`).
///
/// Set Some(-1) to wait indefinitely, None to use system configured default and Some(0)
/// to forcibly stop the container immediately - otherwise the runtime will issue SIGINT
/// and then wait timeout_seconds seconds for the process to stop before issuing SIGKILL.
pub async fn stop_with_timeout(&self, timeout_seconds: Option<i64>) -> Result<()> {
log::debug!(
"Stopping docker container {} with {} second timeout",
self.id,
timeout_seconds
.map(|t| t.to_string())
.unwrap_or("'system default'".into())
);

self.docker_client.stop(&self.id).await?;
self.docker_client.stop(&self.id, timeout_seconds).await?;
Ok(())
}

Expand Down
12 changes: 11 additions & 1 deletion testcontainers/src/core/containers/sync_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,21 @@ where
})
}

/// Stops the container (not the same with `pause`).
/// Stops the container (not the same with `pause`) using the default 10 second timeout.
pub fn stop(&self) -> Result<()> {
self.rt().block_on(self.async_impl().stop())
}

/// Stops the container with timeout before issuing SIGKILL (not the same with `pause`).
///
/// Set Some(-1) to wait indefinitely, None to use system configured default and Some(0)
/// to forcibly stop the container immediately - otherwise the runtime will issue SIGINT
/// and then wait timeout_seconds seconds for the process to stop before issuing SIGKILL.
pub fn stop_with_timeout(&self, timeout_seconds: Option<i64>) -> Result<()> {
self.rt()
.block_on(self.async_impl().stop_with_timeout(timeout_seconds))
}

/// Starts the container.
pub fn start(&self) -> Result<()> {
self.rt().block_on(self.async_impl().start())
Expand Down
2 changes: 1 addition & 1 deletion testcontainers/src/core/logs/consumer/logging_consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl LoggingConsumer {
let message = message.trim_end_matches(['\n', '\r']);

if let Some(prefix) = &self.prefix {
Cow::Owned(format!("{} {}", prefix, message))
Cow::Owned(format!("{prefix} {message}"))
} else {
Cow::Borrowed(message)
}
Expand Down
8 changes: 2 additions & 6 deletions testcontainers/src/core/logs/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,8 @@ impl LogStream {
}
Err(err) => {
let err = Arc::new(err);
handle_error!(
stdout_tx.send(Err(io::Error::new(io::ErrorKind::Other, err.clone())))
);
handle_error!(
stderr_tx.send(Err(io::Error::new(io::ErrorKind::Other, err)))
);
handle_error!(stdout_tx.send(Err(io::Error::other(err.clone()))));
handle_error!(stderr_tx.send(Err(io::Error::other(err))));
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions testcontainers/src/core/wait/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub enum WaitFor {
/// Wait for a certain HTTP response.
#[cfg(feature = "http_wait")]
#[cfg_attr(docsrs, doc(cfg(feature = "http_wait")))]
Http(HttpWaitStrategy),
Http(Box<HttpWaitStrategy>),
/// Wait for the container to exit.
Exit(ExitWaitStrategy),
}
Expand Down Expand Up @@ -74,7 +74,7 @@ impl WaitFor {
#[cfg(feature = "http_wait")]
#[cfg_attr(docsrs, doc(cfg(feature = "http_wait")))]
pub fn http(http_strategy: HttpWaitStrategy) -> WaitFor {
WaitFor::Http(http_strategy)
WaitFor::Http(Box::new(http_strategy))
}

/// Wait for the container to exit.
Expand Down Expand Up @@ -121,7 +121,7 @@ impl WaitFor {
#[cfg_attr(docsrs, doc(cfg(feature = "http_wait")))]
impl From<HttpWaitStrategy> for WaitFor {
fn from(value: HttpWaitStrategy) -> Self {
Self::Http(value)
Self::Http(Box::new(value))
}
}

Expand Down
3 changes: 1 addition & 2 deletions testcontainers/src/runners/async_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,7 @@ where
res => res,
}?;

let copy_to_sources: Vec<&CopyToContainer> =
container_req.copy_to_sources().map(Into::into).collect();
let copy_to_sources: Vec<&CopyToContainer> = container_req.copy_to_sources().collect();

for copy_to_source in copy_to_sources {
client
Expand Down
2 changes: 1 addition & 1 deletion testcontainers/src/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static WATCHDOG: Lazy<Mutex<Watchdog>> = Lazy::new(|| {
.unwrap_or_default()
{
signal_docker
.stop(&container_id)
.stop(&container_id, None)
.await
.expect("failed to stop container");
signal_docker
Expand Down
Loading