Skip to content

Commit

Permalink
QUARKUS-1490: Use BuildItem to enable use of TestContainers shared ne…
Browse files Browse the repository at this point in the history
…twork
  • Loading branch information
Michael Anstis committed Dec 2, 2021
1 parent e98ec8a commit eda7d72
Show file tree
Hide file tree
Showing 19 changed files with 155 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.deployment.builditem;

import io.quarkus.builder.item.BuildItem;
import io.quarkus.builder.item.MultiBuildItem;

/**
* A marker build item that, if any instances are provided during the build, the containers started by DevServices
* will be exposed to the Docker host. This is mainly used by {@see DevServicesKafkaProcessor} where the
* container may need to be exposed to Dockers host and accessible from Dockers internal network.
*
* If a {@link DevServicesSharedNetworkBuildItem} is not produced the default behaviour is to expose services only
* to the Docker host and this {@link BuildItem} is not required. This {@link BuildItem} should therefore
* only be used in conjunction with {@link DevServicesSharedNetworkBuildItem} when expose to both the
* Docker host and the Docker network is required.
*/
public final class DevServicesExposeOnDockerHostBuildItem extends MultiBuildItem {

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@

import io.quarkus.builder.BuildChainBuilder;
import io.quarkus.builder.BuildStepBuilder;
import io.quarkus.builder.item.SimpleBuildItem;
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
* A marker build item that, if any instances are provided during the build, the containers started by DevServices
* will use a shared network.
* 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 {

/**
* 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

0 comments on commit eda7d72

Please sign in to comment.