Skip to content

Commit be7251b

Browse files
Check if container belongs to a network when using exposeHostPorts (#8298)
Fixes #7335 --------- Co-authored-by: Eddú Meléndez Gonzales <[email protected]>
1 parent 78ba315 commit be7251b

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

core/src/main/java/org/testcontainers/containers/GenericContainer.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,14 @@ private void connectToPortForwardingNetwork(String networkMode) {
623623
.map(ContainerNetwork::getNetworkID)
624624
.ifPresent(networkId -> {
625625
if (!Arrays.asList(networkId, "none", "host").contains(networkMode)) {
626-
dockerClient.connectToNetworkCmd().withContainerId(containerId).withNetworkId(networkId).exec();
626+
com.github.dockerjava.api.model.Network network =
627+
this.dockerClient.inspectNetworkCmd().withNetworkId(networkId).exec();
628+
if (!network.getContainers().containsKey(this.containerId)) {
629+
this.dockerClient.connectToNetworkCmd()
630+
.withContainerId(this.containerId)
631+
.withNetworkId(networkId)
632+
.exec();
633+
}
627634
}
628635
});
629636
}
@@ -827,7 +834,7 @@ private void applyConfiguration(CreateContainerCmd createCommand) {
827834
withExtraHost(INTERNAL_HOST_HOSTNAME, it.getIpAddress());
828835
});
829836

830-
String[] extraHostsArray = extraHosts.stream().toArray(String[]::new);
837+
String[] extraHostsArray = extraHosts.stream().distinct().toArray(String[]::new);
831838
createCommand.withExtraHosts(extraHostsArray);
832839

833840
if (workingDirectory != null) {

core/src/test/java/org/testcontainers/containers/ExposedHostTest.java

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@
77
import org.junit.AfterClass;
88
import org.junit.BeforeClass;
99
import org.junit.Test;
10+
import org.junit.runner.Description;
11+
import org.junit.runners.model.Statement;
12+
import org.testcontainers.DockerClientFactory;
1013
import org.testcontainers.TestImages;
1114
import org.testcontainers.Testcontainers;
15+
import org.testcontainers.utility.TestcontainersConfiguration;
1216

17+
import java.io.IOException;
1318
import java.io.OutputStream;
1419
import java.net.InetSocketAddress;
20+
import java.util.List;
21+
import java.util.UUID;
1522

1623
import static org.assertj.core.api.Assertions.assertThat;
24+
import static org.assertj.core.api.Assumptions.assumeThat;
1725

1826
public class ExposedHostTest {
1927

@@ -33,7 +41,6 @@ public static void setUpClass() throws Exception {
3341
}
3442
}
3543
);
36-
3744
server.start();
3845
}
3946

@@ -82,6 +89,61 @@ public void testExposedHostPortOnFixedInternalPorts() {
8289
assertResponse(new GenericContainer<>(tinyContainerDef()), 81);
8390
}
8491

92+
@Test
93+
public void testExposedHostWithReusableContainerAndFixedNetworkName() throws IOException, InterruptedException {
94+
assumeThat(TestcontainersConfiguration.getInstance().environmentSupportsReuse()).isTrue();
95+
Network network = createReusableNetwork(UUID.randomUUID());
96+
Testcontainers.exposeHostPorts(server.getAddress().getPort());
97+
98+
GenericContainer<?> container = new GenericContainer<>(tinyContainerDef()).withReuse(true).withNetwork(network);
99+
container.start();
100+
101+
assertHttpResponseFromHost(container, server.getAddress().getPort());
102+
103+
PortForwardingContainer.INSTANCE.reset();
104+
Testcontainers.exposeHostPorts(server.getAddress().getPort());
105+
106+
GenericContainer<?> reusedContainer = new GenericContainer<>(tinyContainerDef())
107+
.withReuse(true)
108+
.withNetwork(network);
109+
reusedContainer.start();
110+
111+
assertThat(reusedContainer.getContainerId()).isEqualTo(container.getContainerId());
112+
assertHttpResponseFromHost(reusedContainer, server.getAddress().getPort());
113+
114+
container.stop();
115+
reusedContainer.stop();
116+
DockerClientFactory.lazyClient().removeNetworkCmd(network.getId()).exec();
117+
}
118+
119+
@Test
120+
public void testExposedHostOnFixedInternalPortsWithReusableContainerAndFixedNetworkName()
121+
throws IOException, InterruptedException {
122+
assumeThat(TestcontainersConfiguration.getInstance().environmentSupportsReuse()).isTrue();
123+
Network network = createReusableNetwork(UUID.randomUUID());
124+
Testcontainers.exposeHostPorts(ImmutableMap.of(server.getAddress().getPort(), 1234));
125+
126+
GenericContainer<?> container = new GenericContainer<>(tinyContainerDef()).withReuse(true).withNetwork(network);
127+
container.start();
128+
129+
assertHttpResponseFromHost(container, 1234);
130+
131+
PortForwardingContainer.INSTANCE.reset();
132+
Testcontainers.exposeHostPorts(ImmutableMap.of(server.getAddress().getPort(), 1234));
133+
134+
GenericContainer<?> reusedContainer = new GenericContainer<>(tinyContainerDef())
135+
.withReuse(true)
136+
.withNetwork(network);
137+
reusedContainer.start();
138+
139+
assertThat(reusedContainer.getContainerId()).isEqualTo(container.getContainerId());
140+
assertHttpResponseFromHost(reusedContainer, 1234);
141+
142+
container.stop();
143+
reusedContainer.stop();
144+
DockerClientFactory.lazyClient().removeNetworkCmd(network.getId()).exec();
145+
}
146+
85147
@SneakyThrows
86148
protected void assertResponse(GenericContainer<?> container, int port) {
87149
try {
@@ -108,4 +170,40 @@ private static class TinyContainerDef extends ContainerDef {
108170
setCommand("top");
109171
}
110172
}
173+
174+
private void assertHttpResponseFromHost(GenericContainer<?> container, int port)
175+
throws IOException, InterruptedException {
176+
String httpResponseFromHost = container
177+
.execInContainer("wget", "-O", "-", "http://host.testcontainers.internal:" + port)
178+
.getStdout();
179+
assertThat(httpResponseFromHost).isEqualTo("Hello World!");
180+
}
181+
182+
private static Network createReusableNetwork(UUID name) {
183+
String networkName = name.toString();
184+
Network network = new Network() {
185+
@Override
186+
public String getId() {
187+
return networkName;
188+
}
189+
190+
@Override
191+
public void close() {}
192+
193+
@Override
194+
public Statement apply(Statement base, Description description) {
195+
return null;
196+
}
197+
};
198+
199+
List<com.github.dockerjava.api.model.Network> networks = DockerClientFactory
200+
.lazyClient()
201+
.listNetworksCmd()
202+
.withNameFilter(networkName)
203+
.exec();
204+
if (networks.isEmpty()) {
205+
Network.builder().createNetworkCmdModifier(cmd -> cmd.withName(networkName)).build().getId();
206+
}
207+
return network;
208+
}
111209
}

0 commit comments

Comments
 (0)