Skip to content

Commit

Permalink
Check if container belongs to a network when using exposeHostPorts (#…
Browse files Browse the repository at this point in the history
…8298)

Fixes #7335

---------

Co-authored-by: Eddú Meléndez Gonzales <eddu.melendez@gmail.com>
  • Loading branch information
TomDeBacker and eddumelendez authored Nov 7, 2024
1 parent 78ba315 commit be7251b
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,14 @@ private void connectToPortForwardingNetwork(String networkMode) {
.map(ContainerNetwork::getNetworkID)
.ifPresent(networkId -> {
if (!Arrays.asList(networkId, "none", "host").contains(networkMode)) {
dockerClient.connectToNetworkCmd().withContainerId(containerId).withNetworkId(networkId).exec();
com.github.dockerjava.api.model.Network network =
this.dockerClient.inspectNetworkCmd().withNetworkId(networkId).exec();
if (!network.getContainers().containsKey(this.containerId)) {
this.dockerClient.connectToNetworkCmd()
.withContainerId(this.containerId)
.withNetworkId(networkId)
.exec();
}
}
});
}
Expand Down Expand Up @@ -827,7 +834,7 @@ private void applyConfiguration(CreateContainerCmd createCommand) {
withExtraHost(INTERNAL_HOST_HOSTNAME, it.getIpAddress());
});

String[] extraHostsArray = extraHosts.stream().toArray(String[]::new);
String[] extraHostsArray = extraHosts.stream().distinct().toArray(String[]::new);
createCommand.withExtraHosts(extraHostsArray);

if (workingDirectory != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,21 @@
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.TestImages;
import org.testcontainers.Testcontainers;
import org.testcontainers.utility.TestcontainersConfiguration;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;

public class ExposedHostTest {

Expand All @@ -33,7 +41,6 @@ public static void setUpClass() throws Exception {
}
}
);

server.start();
}

Expand Down Expand Up @@ -82,6 +89,61 @@ public void testExposedHostPortOnFixedInternalPorts() {
assertResponse(new GenericContainer<>(tinyContainerDef()), 81);
}

@Test
public void testExposedHostWithReusableContainerAndFixedNetworkName() throws IOException, InterruptedException {
assumeThat(TestcontainersConfiguration.getInstance().environmentSupportsReuse()).isTrue();
Network network = createReusableNetwork(UUID.randomUUID());
Testcontainers.exposeHostPorts(server.getAddress().getPort());

GenericContainer<?> container = new GenericContainer<>(tinyContainerDef()).withReuse(true).withNetwork(network);
container.start();

assertHttpResponseFromHost(container, server.getAddress().getPort());

PortForwardingContainer.INSTANCE.reset();
Testcontainers.exposeHostPorts(server.getAddress().getPort());

GenericContainer<?> reusedContainer = new GenericContainer<>(tinyContainerDef())
.withReuse(true)
.withNetwork(network);
reusedContainer.start();

assertThat(reusedContainer.getContainerId()).isEqualTo(container.getContainerId());
assertHttpResponseFromHost(reusedContainer, server.getAddress().getPort());

container.stop();
reusedContainer.stop();
DockerClientFactory.lazyClient().removeNetworkCmd(network.getId()).exec();
}

@Test
public void testExposedHostOnFixedInternalPortsWithReusableContainerAndFixedNetworkName()
throws IOException, InterruptedException {
assumeThat(TestcontainersConfiguration.getInstance().environmentSupportsReuse()).isTrue();
Network network = createReusableNetwork(UUID.randomUUID());
Testcontainers.exposeHostPorts(ImmutableMap.of(server.getAddress().getPort(), 1234));

GenericContainer<?> container = new GenericContainer<>(tinyContainerDef()).withReuse(true).withNetwork(network);
container.start();

assertHttpResponseFromHost(container, 1234);

PortForwardingContainer.INSTANCE.reset();
Testcontainers.exposeHostPorts(ImmutableMap.of(server.getAddress().getPort(), 1234));

GenericContainer<?> reusedContainer = new GenericContainer<>(tinyContainerDef())
.withReuse(true)
.withNetwork(network);
reusedContainer.start();

assertThat(reusedContainer.getContainerId()).isEqualTo(container.getContainerId());
assertHttpResponseFromHost(reusedContainer, 1234);

container.stop();
reusedContainer.stop();
DockerClientFactory.lazyClient().removeNetworkCmd(network.getId()).exec();
}

@SneakyThrows
protected void assertResponse(GenericContainer<?> container, int port) {
try {
Expand All @@ -108,4 +170,40 @@ private static class TinyContainerDef extends ContainerDef {
setCommand("top");
}
}

private void assertHttpResponseFromHost(GenericContainer<?> container, int port)
throws IOException, InterruptedException {
String httpResponseFromHost = container
.execInContainer("wget", "-O", "-", "http://host.testcontainers.internal:" + port)
.getStdout();
assertThat(httpResponseFromHost).isEqualTo("Hello World!");
}

private static Network createReusableNetwork(UUID name) {
String networkName = name.toString();
Network network = new Network() {
@Override
public String getId() {
return networkName;
}

@Override
public void close() {}

@Override
public Statement apply(Statement base, Description description) {
return null;
}
};

List<com.github.dockerjava.api.model.Network> networks = DockerClientFactory
.lazyClient()
.listNetworksCmd()
.withNameFilter(networkName)
.exec();
if (networks.isEmpty()) {
Network.builder().createNetworkCmdModifier(cmd -> cmd.withName(networkName)).build().getId();
}
return network;
}
}

0 comments on commit be7251b

Please sign in to comment.