From adde384dbb46af06e64d8ff291ff30aa7c97a6db Mon Sep 17 00:00:00 2001 From: Miquel Simon Date: Tue, 16 Jul 2024 11:52:20 +0200 Subject: [PATCH] Supply databases with Testcontainers. Signed-off-by: Miquel Simon --- test-poc/framework/pom.xml | 35 +++++++++++ .../database/AbstractDatabaseSupplier.java | 3 + .../framework/database/DatabaseConfig.java | 14 ++--- .../database/MSSQLServerDatabaseSupplier.java | 18 ++++++ .../database/MariaDBDatabaseSupplier.java | 20 ++++++ .../database/MySQLDatabaseSupplier.java | 21 +++++++ .../database/PostgresDatabaseSupplier.java | 6 +- .../test/framework/database/TestDatabase.java | 63 +++++++++++++++++-- ...keycloak.test.framework.injection.Supplier | 3 + .../container-license-acceptance.txt | 1 + 10 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 test-poc/framework/src/main/java/org/keycloak/test/framework/database/MSSQLServerDatabaseSupplier.java create mode 100644 test-poc/framework/src/main/java/org/keycloak/test/framework/database/MariaDBDatabaseSupplier.java create mode 100644 test-poc/framework/src/main/java/org/keycloak/test/framework/database/MySQLDatabaseSupplier.java create mode 100644 test-poc/framework/src/main/resources/container-license-acceptance.txt diff --git a/test-poc/framework/pom.xml b/test-poc/framework/pom.xml index cd032b36be65..d66aadb867ef 100755 --- a/test-poc/framework/pom.xml +++ b/test-poc/framework/pom.xml @@ -66,6 +66,41 @@ ${selenium.version} pom + + + + junit + junit + ${junit.version} + compile + + + + org.testcontainers + junit-jupiter + + + org.testcontainers + postgresql + + + org.testcontainers + mariadb + + + org.testcontainers + mysql + + + org.testcontainers + mssqlserver + + + + + com.microsoft.sqlserver + mssql-jdbc + diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/AbstractDatabaseSupplier.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/AbstractDatabaseSupplier.java index f39adfb89f43..0a497393e81b 100644 --- a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/AbstractDatabaseSupplier.java +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/AbstractDatabaseSupplier.java @@ -9,6 +9,9 @@ public abstract class AbstractDatabaseSupplier implements Supplier { + protected static final String DEFAULT_DB_USERNAME = "keycloak"; + protected static final String DEFAULT_DB_PASSWORD = "Password1!"; + @Override public Class getAnnotationClass() { return KeycloakTestDatabase.class; diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/DatabaseConfig.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/DatabaseConfig.java index f8597fa7aa77..5a9b41f320df 100644 --- a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/DatabaseConfig.java +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/DatabaseConfig.java @@ -7,7 +7,7 @@ public class DatabaseConfig { private String vendor; private String containerImage; - private String urlHost; + private String url; private String username; private String password; @@ -29,12 +29,12 @@ public DatabaseConfig containerImage(String containerImage) { return this; } - public String getUrlHost() { - return urlHost; + public String getUrl() { + return url; } - public DatabaseConfig urlHost(String urlHost) { - this.urlHost = urlHost; + public DatabaseConfig url(String url) { + this.url = url; return this; } @@ -61,8 +61,8 @@ public Map toConfig() { if (vendor != null) { config.put("db", vendor); } - if (urlHost != null) { - config.put("db-url-host", urlHost); + if (url != null) { + config.put("db-url", url); } if (username != null) { config.put("db-username", username); diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MSSQLServerDatabaseSupplier.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MSSQLServerDatabaseSupplier.java new file mode 100644 index 000000000000..18da13e97c07 --- /dev/null +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MSSQLServerDatabaseSupplier.java @@ -0,0 +1,18 @@ +package org.keycloak.test.framework.database; + +public class MSSQLServerDatabaseSupplier extends AbstractDatabaseSupplier { + public static final String VENDOR = "mssql"; + + @Override + TestDatabase getTestDatabase() { + DatabaseConfig databaseConfig = new DatabaseConfig() + .vendor(VENDOR) + .containerImage("mcr.microsoft.com/mssql/server:latest"); + return new TestDatabase(databaseConfig); + } + + @Override + public String getAlias() { + return VENDOR; + } +} diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MariaDBDatabaseSupplier.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MariaDBDatabaseSupplier.java new file mode 100644 index 000000000000..95c929a53608 --- /dev/null +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MariaDBDatabaseSupplier.java @@ -0,0 +1,20 @@ +package org.keycloak.test.framework.database; + +public class MariaDBDatabaseSupplier extends AbstractDatabaseSupplier { + public static final String VENDOR = "mariadb"; + + @Override + TestDatabase getTestDatabase() { + DatabaseConfig databaseConfig = new DatabaseConfig() + .vendor(VENDOR) + .username(DEFAULT_DB_USERNAME) + .password(DEFAULT_DB_PASSWORD) + .containerImage("mariadb:latest"); + return new TestDatabase(databaseConfig); + } + + @Override + public String getAlias() { + return VENDOR; + } +} diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MySQLDatabaseSupplier.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MySQLDatabaseSupplier.java new file mode 100644 index 000000000000..94b81f7f78bb --- /dev/null +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/MySQLDatabaseSupplier.java @@ -0,0 +1,21 @@ +package org.keycloak.test.framework.database; + +public class MySQLDatabaseSupplier extends AbstractDatabaseSupplier { + + public static final String VENDOR = "mysql"; + + @Override + TestDatabase getTestDatabase() { + DatabaseConfig databaseConfig = new DatabaseConfig() + .vendor(VENDOR) + .username(DEFAULT_DB_USERNAME) + .password(DEFAULT_DB_PASSWORD) + .containerImage("mysql:latest"); + return new TestDatabase(databaseConfig); + } + + @Override + public String getAlias() { + return VENDOR; + } +} diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/PostgresDatabaseSupplier.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/PostgresDatabaseSupplier.java index afc5135b8301..0fe21f26edf9 100644 --- a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/PostgresDatabaseSupplier.java +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/PostgresDatabaseSupplier.java @@ -8,9 +8,9 @@ public class PostgresDatabaseSupplier extends AbstractDatabaseSupplier { TestDatabase getTestDatabase() { DatabaseConfig databaseConfig = new DatabaseConfig() .vendor(VENDOR) - .username("keycloak") - .password("keycloak") - .containerImage("the-postgres-container:the-version"); + .username(DEFAULT_DB_USERNAME) + .password(DEFAULT_DB_PASSWORD) + .containerImage("postgres:latest"); return new TestDatabase(databaseConfig); } diff --git a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/TestDatabase.java b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/TestDatabase.java index 3b4707b036a7..6c272d9a69c5 100644 --- a/test-poc/framework/src/main/java/org/keycloak/test/framework/database/TestDatabase.java +++ b/test-poc/framework/src/main/java/org/keycloak/test/framework/database/TestDatabase.java @@ -1,10 +1,21 @@ package org.keycloak.test.framework.database; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.JdbcDatabaseContainer; +import org.testcontainers.containers.MSSQLServerContainer; +import org.testcontainers.containers.MariaDBContainer; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.utility.DockerImageName; + +import java.time.Duration; import java.util.Map; public class TestDatabase { - private DatabaseConfig databaseConfig; + private final DatabaseConfig databaseConfig; + + private GenericContainer container; public TestDatabase(DatabaseConfig databaseConfig) { this.databaseConfig = databaseConfig; @@ -12,14 +23,21 @@ public TestDatabase(DatabaseConfig databaseConfig) { public void start() { if (databaseConfig.getContainerImage() != null) { - // TODO Start container + container = createContainer(); + container.withStartupTimeout(Duration.ofMinutes(5)).start(); + databaseConfig.url(getJdbcUrl()); + if (container instanceof MSSQLServerContainer) { + databaseConfig.username(((JdbcDatabaseContainer) container).getUsername()); + databaseConfig.password(((JdbcDatabaseContainer) container).getPassword()); + } } } public void stop() { if (databaseConfig.getContainerImage() != null) { - // TODO Stop container - } else if (databaseConfig.getVendor().equals("dev-mem")) { + container.stop(); + container = null; + } else if ("dev-mem".equals(databaseConfig.getVendor())) { // TODO Stop in-mem H2 database } } @@ -28,4 +46,41 @@ public Map getServerConfig() { return databaseConfig.toConfig(); } + public String getJdbcUrl() { + return ((JdbcDatabaseContainer)container).getJdbcUrl(); + } + + private JdbcDatabaseContainer configureJdbcContainer(JdbcDatabaseContainer jdbcDatabaseContainer) { + if (jdbcDatabaseContainer instanceof MSSQLServerContainer) { + return jdbcDatabaseContainer; + } + + return jdbcDatabaseContainer + .withDatabaseName("keycloak") + .withUsername(databaseConfig.getUsername()) + .withPassword(databaseConfig.getPassword()); + } + + private GenericContainer createContainer() { + return switch (databaseConfig.getVendor()) { + case PostgresDatabaseSupplier.VENDOR -> { + DockerImageName POSTGRES = DockerImageName.parse(databaseConfig.getContainerImage()).asCompatibleSubstituteFor("postgres"); + yield configureJdbcContainer(new PostgreSQLContainer<>(POSTGRES)); + } + case MariaDBDatabaseSupplier.VENDOR -> { + DockerImageName MARIADB = DockerImageName.parse(databaseConfig.getContainerImage()).asCompatibleSubstituteFor("mariadb"); + yield configureJdbcContainer(new MariaDBContainer<>(MARIADB)); + } + case MySQLDatabaseSupplier.VENDOR -> { + DockerImageName MYSQL = DockerImageName.parse(databaseConfig.getContainerImage()).asCompatibleSubstituteFor("mysql"); + yield configureJdbcContainer(new MySQLContainer<>(MYSQL)); + } + case MSSQLServerDatabaseSupplier.VENDOR -> { + DockerImageName MSSQL = DockerImageName.parse(databaseConfig.getContainerImage()).asCompatibleSubstituteFor("sqlserver"); + yield configureJdbcContainer(new MSSQLServerContainer<>(MSSQL)); + } + default -> throw new RuntimeException("Unsupported database: " + databaseConfig.getVendor()); + }; + } + } diff --git a/test-poc/framework/src/main/resources/META-INF/services/org.keycloak.test.framework.injection.Supplier b/test-poc/framework/src/main/resources/META-INF/services/org.keycloak.test.framework.injection.Supplier index fdaee62e6570..f93866e9181f 100644 --- a/test-poc/framework/src/main/resources/META-INF/services/org.keycloak.test.framework.injection.Supplier +++ b/test-poc/framework/src/main/resources/META-INF/services/org.keycloak.test.framework.injection.Supplier @@ -9,5 +9,8 @@ org.keycloak.test.framework.webdriver.ChromeWebDriverSupplier org.keycloak.test.framework.webdriver.FirefoxWebDriverSupplier org.keycloak.test.framework.database.DevMemDatabaseSupplier org.keycloak.test.framework.database.DevFileDatabaseSupplier +org.keycloak.test.framework.database.MySQLDatabaseSupplier org.keycloak.test.framework.database.PostgresDatabaseSupplier +org.keycloak.test.framework.database.MariaDBDatabaseSupplier +org.keycloak.test.framework.database.MSSQLServerDatabaseSupplier org.keycloak.test.framework.page.PageSupplier \ No newline at end of file diff --git a/test-poc/framework/src/main/resources/container-license-acceptance.txt b/test-poc/framework/src/main/resources/container-license-acceptance.txt new file mode 100644 index 000000000000..f17e683dee8e --- /dev/null +++ b/test-poc/framework/src/main/resources/container-license-acceptance.txt @@ -0,0 +1 @@ +mcr.microsoft.com/mssql/server:latest \ No newline at end of file