Skip to content

Commit

Permalink
Merge pull request #21863 from manstis/QUARKUS-1490
Browse files Browse the repository at this point in the history
QUARKUS-1490: Use BuildItem to enable use of TestContainers shared network
  • Loading branch information
geoand authored Dec 3, 2021
2 parents 7aa7ca5 + ed96a82 commit 1fe8ec0
Show file tree
Hide file tree
Showing 18 changed files with 162 additions and 161 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,41 @@

import io.quarkus.builder.BuildChainBuilder;
import io.quarkus.builder.BuildStepBuilder;
import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.builder.item.BuildItem;
import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.deployment.pkg.builditem.ProcessInheritIODisabled;

/**
* A marker build item that if present during the build, then the containers started by DevServices
* will use a shared network.
* A marker build item that, if any instances are provided during the build, the containers started by DevServices
* will use a shared network and be accessible across the Docker network. The default is that containers started by
* DevServices will only be accessible from the Docker host.
* This is mainly useful in integration tests where the application container needs to be able
* to communicate with the services containers
*/
public final class DevServicesSharedNetworkBuildItem extends SimpleBuildItem {
public final class DevServicesSharedNetworkBuildItem extends MultiBuildItem {

private boolean exposeOnDockerHost;

/**
* Construct the {@link BuildItem} exposing services only on the shared network.
*/
public DevServicesSharedNetworkBuildItem() {
this(false);
}

/**
* Construct the {@link BuildItem} exposing services on both the shared network and Docker host.
* This is mainly used by {@see DevServicesKafkaProcessor}.
*
* @param exposeOnDockerHost
*/
public DevServicesSharedNetworkBuildItem(boolean exposeOnDockerHost) {
this.exposeOnDockerHost = exposeOnDockerHost;
}

public boolean isExposedOnDockerHost() {
return exposeOnDockerHost;
}

/**
* Generates a {@link List<Consumer<BuildChainBuilder>> build chain builder} which creates a build step
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package io.quarkus.apicurio.registry.avro;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.Base58;
import org.testcontainers.utility.DockerImageName;

import io.quarkus.deployment.IsDockerWorking;
Expand All @@ -25,6 +23,7 @@
import io.quarkus.deployment.console.StartupLogCompressor;
import io.quarkus.deployment.dev.devservices.GlobalDevServicesConfig;
import io.quarkus.deployment.logging.LoggingSetupBuildItem;
import io.quarkus.devservices.common.ConfigureUtil;
import io.quarkus.devservices.common.ContainerLocator;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ConfigUtils;
Expand Down Expand Up @@ -60,7 +59,7 @@ public class DevServicesApicurioRegistryProcessor {
@BuildStep(onlyIfNot = IsNormal.class, onlyIf = GlobalDevServicesConfig.Enabled.class)
public void startApicurioRegistryDevService(LaunchModeBuildItem launchMode,
ApicurioRegistryDevServicesBuildTimeConfig apicurioRegistryDevServices,
Optional<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem,
List<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem,
BuildProducer<DevServicesConfigResultBuildItem> devServicesConfiguration,
Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
CuratedApplicationShutdownBuildItem closeBuildItem,
Expand All @@ -82,7 +81,7 @@ public void startApicurioRegistryDevService(LaunchModeBuildItem launchMode,
consoleInstalledBuildItem, loggingSetupBuildItem);
try {
apicurioRegistry = startApicurioRegistry(configuration, launchMode,
devServicesSharedNetworkBuildItem.isPresent(), devServicesConfig.timeout);
!devServicesSharedNetworkBuildItem.isEmpty(), devServicesConfig.timeout);
if (apicurioRegistry == null) {
compressor.close();
return;
Expand Down Expand Up @@ -254,23 +253,17 @@ public int hashCode() {
}

private static final class ApicurioRegistryContainer extends GenericContainer<ApicurioRegistryContainer> {
private final int port;
private final int fixedExposedPort;
private final boolean useSharedNetwork;

private String hostName = null;

private ApicurioRegistryContainer(DockerImageName dockerImageName, int fixedExposedPort, String serviceName,
boolean useSharedNetwork) {
super(dockerImageName);
this.port = fixedExposedPort;
this.fixedExposedPort = fixedExposedPort;
this.useSharedNetwork = useSharedNetwork;
withNetwork(Network.SHARED);
if (useSharedNetwork) {
hostName = "kafka-" + Base58.randomString(5);
setNetworkAliases(Collections.singletonList(hostName));
} else {
withExposedPorts(APICURIO_REGISTRY_PORT);
}

if (serviceName != null) { // Only adds the label in dev mode.
withLabel(DEV_SERVICE_LABEL, serviceName);
}
Expand All @@ -283,8 +276,16 @@ private ApicurioRegistryContainer(DockerImageName dockerImageName, int fixedExpo
@Override
protected void configure() {
super.configure();
if (port > 0 && !useSharedNetwork) {
addFixedExposedPort(port, APICURIO_REGISTRY_PORT);

if (useSharedNetwork) {
hostName = ConfigureUtil.configureSharedNetwork(this, "kafka");
return;
}

if (fixedExposedPort > 0) {
addFixedExposedPort(fixedExposedPort, APICURIO_REGISTRY_PORT);
} else {
addExposedPorts(APICURIO_REGISTRY_PORT);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ public interface DevServicesDatasourceProvider {
RunningDevServicesDatasource startDatabase(Optional<String> username, Optional<String> password,
Optional<String> datasourceName,
Optional<String> imageName, Map<String, String> additionalProperties,
OptionalInt port, LaunchMode launchMode, Optional<Duration> startupTimeout,
boolean useTestContainersSharedNetwork);
OptionalInt port, LaunchMode launchMode, Optional<Duration> startupTimeout);

default boolean isDockerRequired() {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,7 @@ private DevServicesDatasourceResultBuildItem.DbResult startDevDb(String dbName,
ConfigProvider.getConfig().getOptionalValue(prefix + "password", String.class),
Optional.ofNullable(dbName), dataSourceBuildTimeConfig.devservices.imageName,
dataSourceBuildTimeConfig.devservices.properties,
dataSourceBuildTimeConfig.devservices.port, launchMode, globalDevServicesConfig.timeout,
dataSourceBuildTimeConfig.devservices.useTestContainersSharedNetwork);
dataSourceBuildTimeConfig.devservices.port, launchMode, globalDevServicesConfig.timeout);
closeableList.add(datasource.getCloseTask());

propertiesMap.put(prefix + "db-kind", dataSourceBuildTimeConfig.dbKind.orElse(null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,4 @@ public class DevServicesBuildTimeConfig {
@ConfigItem
public OptionalInt port;

/**
* Whether this particular data source's container should join TestContainers Shared Network.
* <p>
* By default, the data source container will join Docker's default network.
*/
@ConfigItem(defaultValue = "false")
public boolean useTestContainersSharedNetwork;

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import java.io.Closeable;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;

import org.jboss.logging.Logger;
import org.testcontainers.containers.Db2Container;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;

import io.quarkus.datasource.common.runtime.DatabaseKind;
Expand All @@ -31,15 +31,14 @@ public class DB2DevServicesProcessor {

@BuildStep
DevServicesDatasourceProviderBuildItem setupDB2(
Optional<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem) {
List<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem) {
return new DevServicesDatasourceProviderBuildItem(DatabaseKind.DB2, new DevServicesDatasourceProvider() {
@Override
public RunningDevServicesDatasource startDatabase(Optional<String> username, Optional<String> password,
Optional<String> datasourceName, Optional<String> imageName, Map<String, String> additionalProperties,
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout,
boolean useTestContainersSharedNetwork) {
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout) {
QuarkusDb2Container container = new QuarkusDb2Container(imageName, fixedExposedPort,
devServicesSharedNetworkBuildItem.isPresent(), useTestContainersSharedNetwork);
!devServicesSharedNetworkBuildItem.isEmpty());
startupTimeout.ifPresent(container::withStartupTimeout);
container.withPassword(password.orElse("quarkus"))
.withUsername(username.orElse("quarkus"))
Expand Down Expand Up @@ -69,15 +68,11 @@ private static class QuarkusDb2Container extends Db2Container {

private String hostName = null;

public QuarkusDb2Container(Optional<String> imageName, OptionalInt fixedExposedPort, boolean useSharedNetwork,
boolean useTestContainersSharedNetwork) {
public QuarkusDb2Container(Optional<String> imageName, OptionalInt fixedExposedPort, boolean useSharedNetwork) {
super(DockerImageName.parse(imageName.orElse("ibmcom/db2:" + DB2DevServicesProcessor.TAG))
.asCompatibleSubstituteFor(DockerImageName.parse("ibmcom/db2")));
this.fixedExposedPort = fixedExposedPort;
this.useSharedNetwork = useSharedNetwork;
if (useTestContainersSharedNetwork) {
withNetwork(Network.SHARED);
}
}

@Override
Expand All @@ -91,6 +86,8 @@ protected void configure() {

if (fixedExposedPort.isPresent()) {
addFixedExposedPort(fixedExposedPort.getAsInt(), DB2_PORT);
} else {
addExposedPorts(DB2_PORT);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ DevServicesDatasourceProviderBuildItem setupDerby() {
@Override
public RunningDevServicesDatasource startDatabase(Optional<String> username, Optional<String> password,
Optional<String> datasourceName, Optional<String> imageName, Map<String, String> additionalProperties,
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout,
boolean useTestContainersSharedNetwork) {
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout) {
try {
int port = fixedExposedPort.isPresent() ? fixedExposedPort.getAsInt()
: 1527 + (launchMode == LaunchMode.TEST ? 0 : 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ DevServicesDatasourceProviderBuildItem setupH2() {
@Override
public RunningDevServicesDatasource startDatabase(Optional<String> username, Optional<String> password,
Optional<String> datasourceName, Optional<String> imageName, Map<String, String> additionalProperties,
OptionalInt port, LaunchMode launchMode, Optional<Duration> startupTimeout,
boolean useTestContainersSharedNetwork) {
OptionalInt port, LaunchMode launchMode, Optional<Duration> startupTimeout) {
try {
final Server tcpServer = Server.createTcpServer("-tcpPort",
port.isPresent() ? String.valueOf(port.getAsInt()) : "0");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import java.io.Closeable;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;

import org.jboss.logging.Logger;
import org.testcontainers.containers.MariaDBContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;

import io.quarkus.datasource.common.runtime.DatabaseKind;
Expand All @@ -29,15 +29,14 @@ public class MariaDBDevServicesProcessor {

@BuildStep
DevServicesDatasourceProviderBuildItem setupMariaDB(
Optional<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem) {
List<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem) {
return new DevServicesDatasourceProviderBuildItem(DatabaseKind.MARIADB, new DevServicesDatasourceProvider() {
@Override
public RunningDevServicesDatasource startDatabase(Optional<String> username, Optional<String> password,
Optional<String> datasourceName, Optional<String> imageName, Map<String, String> additionalProperties,
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout,
boolean useTestContainersSharedNetwork) {
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout) {
QuarkusMariaDBContainer container = new QuarkusMariaDBContainer(imageName, fixedExposedPort,
devServicesSharedNetworkBuildItem.isPresent(), useTestContainersSharedNetwork);
!devServicesSharedNetworkBuildItem.isEmpty());
startupTimeout.ifPresent(container::withStartupTimeout);
container.withPassword(password.orElse("quarkus"))
.withUsername(username.orElse("quarkus"))
Expand Down Expand Up @@ -67,15 +66,11 @@ private static class QuarkusMariaDBContainer extends MariaDBContainer {

private String hostName = null;

public QuarkusMariaDBContainer(Optional<String> imageName, OptionalInt fixedExposedPort, boolean useSharedNetwork,
boolean useTestContainersSharedNetwork) {
public QuarkusMariaDBContainer(Optional<String> imageName, OptionalInt fixedExposedPort, boolean useSharedNetwork) {
super(DockerImageName.parse(imageName.orElse(MariaDBContainer.IMAGE + ":" + MariaDBDevServicesProcessor.TAG))
.asCompatibleSubstituteFor(DockerImageName.parse(MariaDBContainer.IMAGE)));
this.fixedExposedPort = fixedExposedPort;
this.useSharedNetwork = useSharedNetwork;
if (useTestContainersSharedNetwork) {
withNetwork(Network.SHARED);
}
}

@Override
Expand All @@ -89,6 +84,8 @@ protected void configure() {

if (fixedExposedPort.isPresent()) {
addFixedExposedPort(fixedExposedPort.getAsInt(), PORT);
} else {
addExposedPort(PORT);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import java.io.Closeable;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;

import org.jboss.logging.Logger;
import org.testcontainers.containers.MSSQLServerContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;

import io.quarkus.datasource.common.runtime.DatabaseKind;
Expand All @@ -31,15 +31,14 @@ public class MSSQLDevServicesProcessor {

@BuildStep
DevServicesDatasourceProviderBuildItem setupMSSQL(
Optional<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem) {
List<DevServicesSharedNetworkBuildItem> devServicesSharedNetworkBuildItem) {
return new DevServicesDatasourceProviderBuildItem(DatabaseKind.MSSQL, new DevServicesDatasourceProvider() {
@Override
public RunningDevServicesDatasource startDatabase(Optional<String> username, Optional<String> password,
Optional<String> datasourceName, Optional<String> imageName, Map<String, String> additionalProperties,
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout,
boolean useTestContainersSharedNetwork) {
OptionalInt fixedExposedPort, LaunchMode launchMode, Optional<Duration> startupTimeout) {
QuarkusMSSQLServerContainer container = new QuarkusMSSQLServerContainer(imageName, fixedExposedPort,
devServicesSharedNetworkBuildItem.isPresent(), useTestContainersSharedNetwork);
!devServicesSharedNetworkBuildItem.isEmpty());
startupTimeout.ifPresent(container::withStartupTimeout);
container.withPassword(password.orElse("Quarkuspassword1"));
additionalProperties.forEach(container::withUrlParam);
Expand Down Expand Up @@ -67,16 +66,12 @@ private static class QuarkusMSSQLServerContainer extends MSSQLServerContainer {

private String hostName = null;

public QuarkusMSSQLServerContainer(Optional<String> imageName, OptionalInt fixedExposedPort, boolean useSharedNetwork,
boolean useTestContainersSharedNetwork) {
public QuarkusMSSQLServerContainer(Optional<String> imageName, OptionalInt fixedExposedPort, boolean useSharedNetwork) {
super(DockerImageName
.parse(imageName.orElse(MSSQLServerContainer.IMAGE + ":" + MSSQLDevServicesProcessor.TAG))
.asCompatibleSubstituteFor(MSSQLServerContainer.IMAGE));
this.fixedExposedPort = fixedExposedPort;
this.useSharedNetwork = useSharedNetwork;
if (useTestContainersSharedNetwork) {
withNetwork(Network.SHARED);
}
}

@Override
Expand All @@ -90,6 +85,8 @@ protected void configure() {

if (fixedExposedPort.isPresent()) {
addFixedExposedPort(fixedExposedPort.getAsInt(), MSSQLServerContainer.MS_SQL_SERVER_PORT);
} else {
addExposedPort(MS_SQL_SERVER_PORT);
}
}

Expand Down
Loading

0 comments on commit 1fe8ec0

Please sign in to comment.