From 0e772ad3ccea9e0eeb49c98f72b179f86b0d7e22 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 5 Jan 2022 13:23:54 +0100 Subject: [PATCH] Provide a way to push container properties to database dev services Fixes #20654 --- docs/src/main/asciidoc/datasource.adoc | 17 ++++++++++++++++- .../spi/DevServicesDatasourceProvider.java | 4 +++- .../DevServicesDatasourceProcessor.java | 1 + .../runtime/DevServicesBuildTimeConfig.java | 9 +++++++++ .../db2/deployment/DB2DevServicesProcessor.java | 5 +++-- .../deployment/DerbyDevServicesProcessor.java | 5 +++-- .../h2/deployment/H2DevServicesProcessor.java | 5 +++-- .../deployment/MariaDBDevServicesProcessor.java | 11 +++++++++-- .../deployment/MSSQLDevServicesProcessor.java | 5 +++-- .../deployment/MySQLDevServicesProcessor.java | 12 ++++++++++-- .../deployment/OracleDevServicesProcessor.java | 5 +++-- .../PostgresqlDevServicesProcessor.java | 5 +++-- 12 files changed, 66 insertions(+), 18 deletions(-) diff --git a/docs/src/main/asciidoc/datasource.adoc b/docs/src/main/asciidoc/datasource.adoc index 43f8bd6b4f083..989a4b7b45b9f 100644 --- a/docs/src/main/asciidoc/datasource.adoc +++ b/docs/src/main/asciidoc/datasource.adoc @@ -76,7 +76,22 @@ mcr.microsoft.com/mssql/server:2017-CU12 [NOTE] ==== -All services based on containers are ran using `testcontainers`. Even though extra URL properties can be set in your `application.properties` file, specific `testcontainers` properties such as `TC_INITSCRIPT`, `TC_INITFUNCTION`, `TC_DAEMON`, `TC_TMPFS` are not supported. +All services based on containers are run using Testcontainers but Quarkus is not using the Testcontainers JDBC driver. + +Thus, even though extra JDBC URL properties can be set in your `application.properties` file, +specific properties supported by the Testcontainers JDBC driver such as `TC_INITSCRIPT`, `TC_INITFUNCTION`, `TC_DAEMON`, `TC_TMPFS` are not supported. + +Quarkus can support specific properties sent to the container itself though and, +typically, this is the case for `TC_MY_CNF` which allows to override the MariaDB/MySQL configuration file. + +Overriding the MariaDB/MySQL configuration would be done as follows: + +[source,properties] +---- +quarkus.datasource.devservices.container-properties.TC_MY_CNF=testcontainers/mysql-conf +---- + +This support is database specific and needs to be implemented in each dev service specifically. ==== === JDBC datasource diff --git a/extensions/datasource/deployment-spi/src/main/java/io/quarkus/datasource/deployment/spi/DevServicesDatasourceProvider.java b/extensions/datasource/deployment-spi/src/main/java/io/quarkus/datasource/deployment/spi/DevServicesDatasourceProvider.java index 55cf064b852f4..fe5666027f196 100644 --- a/extensions/datasource/deployment-spi/src/main/java/io/quarkus/datasource/deployment/spi/DevServicesDatasourceProvider.java +++ b/extensions/datasource/deployment-spi/src/main/java/io/quarkus/datasource/deployment/spi/DevServicesDatasourceProvider.java @@ -12,7 +12,9 @@ public interface DevServicesDatasourceProvider { RunningDevServicesDatasource startDatabase(Optional username, Optional password, Optional datasourceName, - Optional imageName, Map additionalProperties, + Optional imageName, + Map containerProperties, + Map additionalJdbcUrlProperties, OptionalInt port, LaunchMode launchMode, Optional startupTimeout); default boolean isDockerRequired() { diff --git a/extensions/datasource/deployment/src/main/java/io/quarkus/datasource/deployment/devservices/DevServicesDatasourceProcessor.java b/extensions/datasource/deployment/src/main/java/io/quarkus/datasource/deployment/devservices/DevServicesDatasourceProcessor.java index 606f4b0e36dc7..84e47aadc7622 100644 --- a/extensions/datasource/deployment/src/main/java/io/quarkus/datasource/deployment/devservices/DevServicesDatasourceProcessor.java +++ b/extensions/datasource/deployment/src/main/java/io/quarkus/datasource/deployment/devservices/DevServicesDatasourceProcessor.java @@ -266,6 +266,7 @@ private DevServicesDatasourceResultBuildItem.DbResult startDevDb(String dbName, .startDatabase(ConfigProvider.getConfig().getOptionalValue(prefix + "username", String.class), ConfigProvider.getConfig().getOptionalValue(prefix + "password", String.class), Optional.ofNullable(dbName), dataSourceBuildTimeConfig.devservices.imageName, + dataSourceBuildTimeConfig.devservices.containerProperties, dataSourceBuildTimeConfig.devservices.properties, dataSourceBuildTimeConfig.devservices.port, launchMode, globalDevServicesConfig.timeout); closeableList.add(datasource.getCloseTask()); diff --git a/extensions/datasource/runtime/src/main/java/io/quarkus/datasource/runtime/DevServicesBuildTimeConfig.java b/extensions/datasource/runtime/src/main/java/io/quarkus/datasource/runtime/DevServicesBuildTimeConfig.java index 62e422722c29c..406b0185fbd0c 100644 --- a/extensions/datasource/runtime/src/main/java/io/quarkus/datasource/runtime/DevServicesBuildTimeConfig.java +++ b/extensions/datasource/runtime/src/main/java/io/quarkus/datasource/runtime/DevServicesBuildTimeConfig.java @@ -41,6 +41,15 @@ public class DevServicesBuildTimeConfig { @ConfigItem public Optional imageName; + /** + * Generic properties that are passed for additional container configuration. + *

+ * Properties defined here are database specific and are interpreted specifically in each database dev service + * implementation. + */ + @ConfigItem + public Map containerProperties; + /** * Generic properties that are added to the database connection URL. */ diff --git a/extensions/devservices/db2/src/main/java/io/quarkus/devservices/db2/deployment/DB2DevServicesProcessor.java b/extensions/devservices/db2/src/main/java/io/quarkus/devservices/db2/deployment/DB2DevServicesProcessor.java index 8e650a49a15c3..99a45bf1c1e8e 100644 --- a/extensions/devservices/db2/src/main/java/io/quarkus/devservices/db2/deployment/DB2DevServicesProcessor.java +++ b/extensions/devservices/db2/src/main/java/io/quarkus/devservices/db2/deployment/DB2DevServicesProcessor.java @@ -35,7 +35,8 @@ DevServicesDatasourceProviderBuildItem setupDB2( return new DevServicesDatasourceProviderBuildItem(DatabaseKind.DB2, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { QuarkusDb2Container container = new QuarkusDb2Container(imageName, fixedExposedPort, !devServicesSharedNetworkBuildItem.isEmpty()); @@ -43,7 +44,7 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt container.withPassword(password.orElse("quarkus")) .withUsername(username.orElse("quarkus")) .withDatabaseName(datasourceName.orElse("default")); - additionalProperties.forEach(container::withUrlParam); + additionalJdbcUrlProperties.forEach(container::withUrlParam); container.start(); LOG.info("Dev Services for IBM Db2 started."); diff --git a/extensions/devservices/derby/src/main/java/io/quarkus/devservices/derby/deployment/DerbyDevServicesProcessor.java b/extensions/devservices/derby/src/main/java/io/quarkus/devservices/derby/deployment/DerbyDevServicesProcessor.java index 6e54a2f66072e..f76d2805a0ac9 100644 --- a/extensions/devservices/derby/src/main/java/io/quarkus/devservices/derby/deployment/DerbyDevServicesProcessor.java +++ b/extensions/devservices/derby/src/main/java/io/quarkus/devservices/derby/deployment/DerbyDevServicesProcessor.java @@ -30,7 +30,8 @@ DevServicesDatasourceProviderBuildItem setupDerby() { return new DevServicesDatasourceProviderBuildItem(DatabaseKind.DERBY, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { try { int port = fixedExposedPort.isPresent() ? fixedExposedPort.getAsInt() @@ -57,7 +58,7 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt LOG.info("Dev Services for Derby started."); StringBuilder additionalArgs = new StringBuilder(); - for (Map.Entry i : additionalProperties.entrySet()) { + for (Map.Entry i : additionalJdbcUrlProperties.entrySet()) { additionalArgs.append(";"); additionalArgs.append(i.getKey()); additionalArgs.append("="); diff --git a/extensions/devservices/h2/src/main/java/io/quarkus/devservices/h2/deployment/H2DevServicesProcessor.java b/extensions/devservices/h2/src/main/java/io/quarkus/devservices/h2/deployment/H2DevServicesProcessor.java index b5b40af18706c..a1b1be5614a94 100644 --- a/extensions/devservices/h2/src/main/java/io/quarkus/devservices/h2/deployment/H2DevServicesProcessor.java +++ b/extensions/devservices/h2/src/main/java/io/quarkus/devservices/h2/deployment/H2DevServicesProcessor.java @@ -29,7 +29,8 @@ DevServicesDatasourceProviderBuildItem setupH2() { return new DevServicesDatasourceProviderBuildItem(DatabaseKind.H2, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt port, LaunchMode launchMode, Optional startupTimeout) { try { final Server tcpServer = Server.createTcpServer("-tcpPort", @@ -37,7 +38,7 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt tcpServer.start(); StringBuilder additionalArgs = new StringBuilder(); - for (Map.Entry i : additionalProperties.entrySet()) { + for (Map.Entry i : additionalJdbcUrlProperties.entrySet()) { additionalArgs.append(";"); additionalArgs.append(i.getKey()); additionalArgs.append("="); diff --git a/extensions/devservices/mariadb/src/main/java/io/quarkus/devservices/mariadb/deployment/MariaDBDevServicesProcessor.java b/extensions/devservices/mariadb/src/main/java/io/quarkus/devservices/mariadb/deployment/MariaDBDevServicesProcessor.java index 83ba1ea1e9936..ba26d1e5d5675 100644 --- a/extensions/devservices/mariadb/src/main/java/io/quarkus/devservices/mariadb/deployment/MariaDBDevServicesProcessor.java +++ b/extensions/devservices/mariadb/src/main/java/io/quarkus/devservices/mariadb/deployment/MariaDBDevServicesProcessor.java @@ -26,6 +26,7 @@ public class MariaDBDevServicesProcessor { public static final String TAG = "10.5.9"; public static final Integer PORT = 3306; + public static final String MY_CNF_CONFIG_OVERRIDE_PARAM_NAME = "TC_MY_CNF"; @BuildStep DevServicesDatasourceProviderBuildItem setupMariaDB( @@ -33,7 +34,8 @@ DevServicesDatasourceProviderBuildItem setupMariaDB( return new DevServicesDatasourceProviderBuildItem(DatabaseKind.MARIADB, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { QuarkusMariaDBContainer container = new QuarkusMariaDBContainer(imageName, fixedExposedPort, !devServicesSharedNetworkBuildItem.isEmpty()); @@ -41,7 +43,12 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt container.withPassword(password.orElse("quarkus")) .withUsername(username.orElse("quarkus")) .withDatabaseName(datasourceName.orElse("default")); - additionalProperties.forEach(container::withUrlParam); + + if (containerProperties.containsKey(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME)) { + container.withConfigurationOverride(containerProperties.get(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME)); + } + + additionalJdbcUrlProperties.forEach(container::withUrlParam); container.start(); LOG.info("Dev Services for MariaDB started."); diff --git a/extensions/devservices/mssql/src/main/java/io/quarkus/devservices/mssql/deployment/MSSQLDevServicesProcessor.java b/extensions/devservices/mssql/src/main/java/io/quarkus/devservices/mssql/deployment/MSSQLDevServicesProcessor.java index adbd64ef93a58..f89a53b2e4bcb 100644 --- a/extensions/devservices/mssql/src/main/java/io/quarkus/devservices/mssql/deployment/MSSQLDevServicesProcessor.java +++ b/extensions/devservices/mssql/src/main/java/io/quarkus/devservices/mssql/deployment/MSSQLDevServicesProcessor.java @@ -35,13 +35,14 @@ DevServicesDatasourceProviderBuildItem setupMSSQL( return new DevServicesDatasourceProviderBuildItem(DatabaseKind.MSSQL, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { QuarkusMSSQLServerContainer container = new QuarkusMSSQLServerContainer(imageName, fixedExposedPort, !devServicesSharedNetworkBuildItem.isEmpty()); startupTimeout.ifPresent(container::withStartupTimeout); container.withPassword(password.orElse("Quarkuspassword1")); - additionalProperties.forEach(container::withUrlParam); + additionalJdbcUrlProperties.forEach(container::withUrlParam); container.start(); LOG.info("Dev Services for Microsoft SQL Server started."); diff --git a/extensions/devservices/mysql/src/main/java/io/quarkus/devservices/mysql/deployment/MySQLDevServicesProcessor.java b/extensions/devservices/mysql/src/main/java/io/quarkus/devservices/mysql/deployment/MySQLDevServicesProcessor.java index 49f131672a86d..2e6c37c5cfebe 100644 --- a/extensions/devservices/mysql/src/main/java/io/quarkus/devservices/mysql/deployment/MySQLDevServicesProcessor.java +++ b/extensions/devservices/mysql/src/main/java/io/quarkus/devservices/mysql/deployment/MySQLDevServicesProcessor.java @@ -25,6 +25,7 @@ public class MySQLDevServicesProcessor { private static final Logger LOG = Logger.getLogger(MySQLDevServicesProcessor.class); public static final String TAG = "8.0.24"; + public static final String MY_CNF_CONFIG_OVERRIDE_PARAM_NAME = "TC_MY_CNF"; @BuildStep DevServicesDatasourceProviderBuildItem setupMysql( @@ -32,7 +33,8 @@ DevServicesDatasourceProviderBuildItem setupMysql( return new DevServicesDatasourceProviderBuildItem(DatabaseKind.MYSQL, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { QuarkusMySQLContainer container = new QuarkusMySQLContainer(imageName, fixedExposedPort, !devServicesSharedNetworkBuildItem.isEmpty()); @@ -40,7 +42,13 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt container.withPassword(password.orElse("quarkus")) .withUsername(username.orElse("quarkus")) .withDatabaseName(datasourceName.orElse("default")); - additionalProperties.forEach(container::withUrlParam); + + if (containerProperties.containsKey(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME)) { + container.withConfigurationOverride(containerProperties.get(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME)); + } + + additionalJdbcUrlProperties.forEach(container::withUrlParam); + container.start(); LOG.info("Dev Services for MySQL started."); diff --git a/extensions/devservices/oracle/src/main/java/io/quarkus/devservices/oracle/deployment/OracleDevServicesProcessor.java b/extensions/devservices/oracle/src/main/java/io/quarkus/devservices/oracle/deployment/OracleDevServicesProcessor.java index 70dc5d0c7a21e..90836d4aa4e8e 100644 --- a/extensions/devservices/oracle/src/main/java/io/quarkus/devservices/oracle/deployment/OracleDevServicesProcessor.java +++ b/extensions/devservices/oracle/src/main/java/io/quarkus/devservices/oracle/deployment/OracleDevServicesProcessor.java @@ -37,7 +37,8 @@ DevServicesDatasourceProviderBuildItem setupOracle( return new DevServicesDatasourceProviderBuildItem(DatabaseKind.ORACLE, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { QuarkusOracleServerContainer container = new QuarkusOracleServerContainer(imageName, fixedExposedPort, !devServicesSharedNetworkBuildItem.isEmpty()); @@ -45,7 +46,7 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt container.withUsername(username.orElse(DEFAULT_DATABASE_USER)) .withPassword(password.orElse(DEFAULT_DATABASE_PASSWORD)) .withDatabaseName(datasourceName.orElse(DEFAULT_DATABASE_NAME)); - additionalProperties.forEach(container::withUrlParam); + additionalJdbcUrlProperties.forEach(container::withUrlParam); container.start(); LOG.info("Dev Services for Oracle started."); diff --git a/extensions/devservices/postgresql/src/main/java/io/quarkus/devservices/postgresql/deployment/PostgresqlDevServicesProcessor.java b/extensions/devservices/postgresql/src/main/java/io/quarkus/devservices/postgresql/deployment/PostgresqlDevServicesProcessor.java index 6f633c06a3b65..72ca1ae477c34 100644 --- a/extensions/devservices/postgresql/src/main/java/io/quarkus/devservices/postgresql/deployment/PostgresqlDevServicesProcessor.java +++ b/extensions/devservices/postgresql/src/main/java/io/quarkus/devservices/postgresql/deployment/PostgresqlDevServicesProcessor.java @@ -39,7 +39,8 @@ DevServicesDatasourceProviderBuildItem setupPostgres( return new DevServicesDatasourceProviderBuildItem(DatabaseKind.POSTGRESQL, new DevServicesDatasourceProvider() { @Override public RunningDevServicesDatasource startDatabase(Optional username, Optional password, - Optional datasourceName, Optional imageName, Map additionalProperties, + Optional datasourceName, Optional imageName, + Map containerProperties, Map additionalJdbcUrlProperties, OptionalInt fixedExposedPort, LaunchMode launchMode, Optional startupTimeout) { QuarkusPostgreSQLContainer container = new QuarkusPostgreSQLContainer(imageName, fixedExposedPort, !devServicesSharedNetworkBuildItem.isEmpty()); @@ -47,7 +48,7 @@ public RunningDevServicesDatasource startDatabase(Optional username, Opt container.withPassword(password.orElse("quarkus")) .withUsername(username.orElse("quarkus")) .withDatabaseName(datasourceName.orElse("default")); - additionalProperties.forEach(container::withUrlParam); + additionalJdbcUrlProperties.forEach(container::withUrlParam); container.start();