Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support HTTP wait strategy #659

Merged
merged 2 commits into from
Jun 15, 2024
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
3 changes: 2 additions & 1 deletion testcontainers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ futures = "0.3"
log = "0.4"
memchr = "2.7.2"
parse-display = "0.9.0"
reqwest = { version = "0.12.4", features = ["default-tls", "hickory-dns", "json", "charset", "http2"], default-features = false }
serde = { version = "1", features = ["derive"] }
serde-java-properties = { version = "0.2.0", optional = true }
serde_json = "1"
Expand All @@ -48,6 +49,6 @@ properties-config = ["serde-java-properties"]
[dev-dependencies]
anyhow = "1.0.86"
pretty_env_logger = "0.5"
reqwest = { version = "0.12.3", features = ["blocking"] }
reqwest = { version = "0.12.4", features = ["blocking"] }
testimages.workspace = true
tokio = { version = "1", features = ["macros"] }
4 changes: 3 additions & 1 deletion testcontainers/src/core.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
pub use self::{
containers::*,
image::{CmdWaitFor, ContainerState, ExecCommand, Image, ImageExt, WaitFor},
image::{ContainerState, ExecCommand, Image, ImageExt},
mounts::{AccessMode, Mount, MountType},
ports::{ContainerPort, IntoContainerPort},
wait::{cmd_wait::CmdWaitFor, WaitFor},
};

mod image;
Expand All @@ -16,3 +17,4 @@ pub(crate) mod macros;
pub(crate) mod mounts;
pub(crate) mod network;
pub(crate) mod ports;
pub mod wait;
7 changes: 5 additions & 2 deletions testcontainers/src/core/containers/async_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use crate::{
client::Client,
env,
error::{ContainerMissingInfo, ExecError, Result, TestcontainersError, WaitContainerError},
image::CmdWaitFor,
macros,
network::Network,
ports::Ports,
ContainerPort, ContainerState, ExecCommand, WaitFor,
wait::WaitStrategy,
CmdWaitFor, ContainerPort, ContainerState, ExecCommand, WaitFor,
},
ContainerRequest, Image,
};
Expand Down Expand Up @@ -342,6 +342,9 @@ where
}
}
},
WaitFor::Http(http_strategy) => {
http_strategy.wait_until_ready(self).await?;
}
WaitFor::Nothing => {}
}
}
Expand Down
4 changes: 3 additions & 1 deletion testcontainers/src/core/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::error::Error;

use crate::core::logs::WaitLogError;
pub use crate::core::{client::ClientError, env::ConfigurationError, ContainerPort};
use crate::core::{logs::WaitLogError, wait::http_strategy::HttpWaitError};

pub type Result<T> = std::result::Result<T, TestcontainersError>;

Expand Down Expand Up @@ -54,6 +54,8 @@ pub enum WaitContainerError {
WaitLog(#[from] WaitLogError),
#[error("container state is unavailable")]
StateUnavailable,
#[error("container is not ready: {0}")]
HttpWait(#[from] HttpWaitError),
#[error("healthcheck is not configured for container: {0}")]
HealthCheckNotConfigured(String),
#[error("container is unhealthy")]
Expand Down
9 changes: 5 additions & 4 deletions testcontainers/src/core/image.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::{borrow::Cow, fmt::Debug};

pub use exec::{CmdWaitFor, ExecCommand};
pub use exec::ExecCommand;
pub use image_ext::ImageExt;
pub use wait_for::WaitFor;

use super::ports::{ContainerPort, Ports};
use crate::{core::mounts::Mount, TestcontainersError};
use crate::{
core::{mounts::Mount, WaitFor},
TestcontainersError,
};

mod exec;
mod image_ext;
mod wait_for;

/// Represents a docker image.
///
Expand Down
62 changes: 1 addition & 61 deletions testcontainers/src/core/image/exec.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::time::Duration;

use bytes::Bytes;

use crate::core::WaitFor;
use crate::core::{CmdWaitFor, WaitFor};

#[derive(Debug)]
pub struct ExecCommand {
Expand Down Expand Up @@ -39,59 +35,3 @@ impl Default for ExecCommand {
Self::new(Vec::<String>::new())
}
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub enum CmdWaitFor {
/// An empty condition. Useful for default cases or fallbacks.
Nothing,
/// Wait for a message on the stdout stream of the command's output.
StdOutMessage { message: Bytes },
/// Wait for a message on the stderr stream of the command's output.
StdErrMessage { message: Bytes },
/// Wait for a certain amount of time.
Duration { length: Duration },
/// Wait for the command's exit code to be equal to the provided one.
ExitCode { code: i64 },
}

impl CmdWaitFor {
pub fn message_on_stdout(message: impl AsRef<[u8]>) -> Self {
Self::StdOutMessage {
message: Bytes::from(message.as_ref().to_vec()),
}
}

pub fn message_on_stderr(message: impl AsRef<[u8]>) -> Self {
Self::StdErrMessage {
message: Bytes::from(message.as_ref().to_vec()),
}
}

pub fn exit_code(code: i64) -> Self {
Self::ExitCode { code }
}

pub fn seconds(length: u64) -> Self {
Self::Duration {
length: Duration::from_secs(length),
}
}

pub fn millis(length: u64) -> Self {
Self::Duration {
length: Duration::from_millis(length),
}
}
}

impl From<WaitFor> for CmdWaitFor {
fn from(wait_for: WaitFor) -> Self {
match wait_for {
WaitFor::Nothing => Self::Nothing,
WaitFor::StdOutMessage { message } => Self::StdOutMessage { message },
WaitFor::StdErrMessage { message } => Self::StdErrMessage { message },
WaitFor::Duration { length } => Self::Duration { length },
WaitFor::Healthcheck => Self::ExitCode { code: 0 },
}
}
}
47 changes: 47 additions & 0 deletions testcontainers/src/core/wait/cmd_wait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::time::Duration;

use bytes::Bytes;

#[derive(Debug, Eq, PartialEq, Clone)]
pub enum CmdWaitFor {
/// An empty condition. Useful for default cases or fallbacks.
Nothing,
/// Wait for a message on the stdout stream of the command's output.
StdOutMessage { message: Bytes },
/// Wait for a message on the stderr stream of the command's output.
StdErrMessage { message: Bytes },
/// Wait for a certain amount of time.
Duration { length: Duration },
/// Wait for the command's exit code to be equal to the provided one.
ExitCode { code: i64 },
}

impl CmdWaitFor {
pub fn message_on_stdout(message: impl AsRef<[u8]>) -> Self {
Self::StdOutMessage {
message: Bytes::from(message.as_ref().to_vec()),
}
}

pub fn message_on_stderr(message: impl AsRef<[u8]>) -> Self {
Self::StdErrMessage {
message: Bytes::from(message.as_ref().to_vec()),
}
}

pub fn exit_code(code: i64) -> Self {
Self::ExitCode { code }
}

pub fn seconds(length: u64) -> Self {
Self::Duration {
length: Duration::from_secs(length),
}
}

pub fn millis(length: u64) -> Self {
Self::Duration {
length: Duration::from_millis(length),
}
}
}
Loading
Loading