Skip to content

Commit 966221c

Browse files
authored
refactor!: return PortNotExposed error from ContainerState::host_port_* (#644)
That's much easier for users to use `?` in `exec_after_start` instead of mapping manually to appropriate error.
1 parent 54e80e4 commit 966221c

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

testcontainers/src/core/containers/async_container.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,8 @@ where
234234
/// Starts the container.
235235
pub async fn start(&self) -> Result<()> {
236236
self.docker_client.start(&self.id).await?;
237-
for cmd in self
238-
.image
239-
.exec_after_start(ContainerState::new(self.ports().await?))?
240-
{
237+
let state = ContainerState::new(self.id(), self.ports().await?);
238+
for cmd in self.image.exec_after_start(state)? {
241239
self.exec(cmd).await?;
242240
}
243241
Ok(())

testcontainers/src/core/image.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,20 +112,40 @@ where
112112

113113
#[derive(Debug)]
114114
pub struct ContainerState {
115+
id: String,
115116
ports: Ports,
116117
}
117118

118119
impl ContainerState {
119-
pub fn new(ports: Ports) -> Self {
120-
Self { ports }
120+
pub fn new(id: impl Into<String>, ports: Ports) -> Self {
121+
Self {
122+
id: id.into(),
123+
ports,
124+
}
121125
}
122126

123-
pub fn host_port_ipv4(&self, internal_port: u16) -> Option<u16> {
124-
self.ports.map_to_host_port_ipv4(internal_port)
127+
/// Returns the host port for the given internal port (`IPv4`).
128+
///
129+
/// Results in an error ([`TestcontainersError::PortNotExposed`]) if the port is not exposed.
130+
pub fn host_port_ipv4(&self, internal_port: u16) -> Result<u16, TestcontainersError> {
131+
self.ports
132+
.map_to_host_port_ipv4(internal_port)
133+
.ok_or_else(|| TestcontainersError::PortNotExposed {
134+
id: self.id.clone(),
135+
port: internal_port,
136+
})
125137
}
126138

127-
pub fn host_port_ipv6(&self, internal_port: u16) -> Option<u16> {
128-
self.ports.map_to_host_port_ipv6(internal_port)
139+
/// Returns the host port for the given internal port (`IPv6`).
140+
///
141+
/// Results in an error ([`TestcontainersError::PortNotExposed`]) if the port is not exposed.
142+
pub fn host_port_ipv6(&self, internal_port: u16) -> Result<u16, TestcontainersError> {
143+
self.ports
144+
.map_to_host_port_ipv6(internal_port)
145+
.ok_or_else(|| TestcontainersError::PortNotExposed {
146+
id: self.id.clone(),
147+
port: internal_port,
148+
})
129149
}
130150
}
131151

testcontainers/src/runners/async_runner.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,8 @@ where
218218
let container =
219219
ContainerAsync::new(container_id, client.clone(), runnable_image, network).await?;
220220

221-
for cmd in container
222-
.image()
223-
.exec_after_start(ContainerState::new(container.ports().await?))?
224-
{
221+
let state = ContainerState::new(container.id(), container.ports().await?);
222+
for cmd in container.image().exec_after_start(state)? {
225223
container.exec(cmd).await?;
226224
}
227225

0 commit comments

Comments
 (0)