// Testcontainers for MoonBit
// Type definitions for container management
///|
/// Wait strategy for container readiness
pub(all) enum WaitStrategy {
TcpPort(Int) // Wait for TCP port to be open
Seconds(Int) // Wait for a fixed number of seconds
HttpGet(String, Int) // Wait for HTTP endpoint (path, expected_status_code)
LogMessage(String) // Wait for a specific message in container logs
} derive(Show, Eq)
///|
/// Error type for testcontainers operations
pub(all) enum TestContainerError {
DockerCommandFailed(String)
ContainerNotFound(String)
PortMappingFailed(String)
InvalidConfiguration(String)
WaitStrategyTimeout(String)
} derive(Show, Eq)
///|
/// Volume mount configuration
pub struct VolumeMount {
host_path : String // Host filesystem path
container_path : String // Container filesystem path
read_only : Bool // Mount as read-only (default: false)
}
///|
/// Log options for container logs
pub struct LogOptions {
follow : Bool // -f: follow log output (stream mode)
timestamps : Bool // -t: show timestamps
tail : Int? // --tail N: show last N lines
since : String? // --since: show logs since timestamp
until : String? // --until: show logs until timestamp
}
///|
/// Create default LogOptions
pub fn LogOptions::default() -> LogOptions {
{ follow: false, timestamps: false, tail: None, since: None, until: None }
}
///|
/// Set follow option
pub fn LogOptions::with_follow(self : LogOptions, follow : Bool) -> LogOptions {
{ ..self, follow, }
}
///|
/// Set timestamps option
pub fn LogOptions::with_timestamps(
self : LogOptions,
timestamps : Bool,
) -> LogOptions {
{ ..self, timestamps, }
}
///|
/// Set tail option
pub fn LogOptions::with_tail(self : LogOptions, lines : Int) -> LogOptions {
{ ..self, tail: Some(lines) }
}
///|
/// Set since option
pub fn LogOptions::with_since(
self : LogOptions,
timestamp : String,
) -> LogOptions {
{ ..self, since: Some(timestamp) }
}
///|
/// Set until option
pub fn LogOptions::with_until(
self : LogOptions,
timestamp : String,
) -> LogOptions {
{ ..self, until: Some(timestamp) }
}
///|
/// Container image configuration
pub struct ContainerImage {
name : String
tag : String
exposed_ports : Array[Int]
env_vars : Array[(String, String)]
cmd : Array[String]
wait_strategy : WaitStrategy?
wait_timeout : Int // seconds, default 60
volumes : Array[VolumeMount] // volume mounts
}
///|
/// Running container instance
pub struct Container {
id : String
image : ContainerImage
port_mappings : Array[(Int, Int)] // (container_port, host_port)
}
///|
/// Create a new container image configuration
pub fn ContainerImage::new(name : String, tag : String) -> ContainerImage {
{
name,
tag,
exposed_ports: [],
env_vars: [],
cmd: [],
wait_strategy: None,
wait_timeout: 60,
volumes: [],
}
}
///|
/// Add an exposed port to the container configuration
pub fn ContainerImage::with_exposed_port(
self : ContainerImage,
port : Int,
) -> ContainerImage {
let ports = self.exposed_ports.copy()
ports.push(port)
{ ..self, exposed_ports: ports }
}
///|
/// Add an environment variable to the container configuration
pub fn ContainerImage::with_env_var(
self : ContainerImage,
key : String,
value : String,
) -> ContainerImage {
let vars = self.env_vars.copy()
vars.push((key, value))
{ ..self, env_vars: vars }
}
///|
/// Set the command to run in the container
pub fn ContainerImage::with_cmd(
self : ContainerImage,
cmd : Array[String],
) -> ContainerImage {
{ ..self, cmd, }
}
///|
/// Set the wait strategy for container readiness
pub fn ContainerImage::with_wait_for(
self : ContainerImage,
strategy : WaitStrategy,
) -> ContainerImage {
{ ..self, wait_strategy: Some(strategy) }
}
///|
/// Set the wait timeout in seconds (default: 60)
pub fn ContainerImage::with_wait_timeout(
self : ContainerImage,
timeout : Int,
) -> ContainerImage {
{ ..self, wait_timeout: timeout }
}
///|
/// Add a volume mount to the container configuration
pub fn ContainerImage::with_volume(
self : ContainerImage,
host_path : String,
container_path : String,
) -> ContainerImage {
let volumes = self.volumes.copy()
volumes.push({ host_path, container_path, read_only: false })
{ ..self, volumes, }
}
///|
/// Add a read-only volume mount to the container configuration
pub fn ContainerImage::with_volume_ro(
self : ContainerImage,
host_path : String,
container_path : String,
) -> ContainerImage {
let volumes = self.volumes.copy()
volumes.push({ host_path, container_path, read_only: true })
{ ..self, volumes, }
}