diff --git a/test-poc/base/src/test/resources/container-license-acceptance.txt b/test-poc/base/src/test/resources/container-license-acceptance.txt
new file mode 100644
index 000000000000..f17e683dee8e
--- /dev/null
+++ b/test-poc/base/src/test/resources/container-license-acceptance.txt
@@ -0,0 +1 @@
+mcr.microsoft.com/mssql/server:latest
\ No newline at end of file
diff --git a/test-poc/framework/pom.xml b/test-poc/framework/pom.xml
index cd032b36be65..5cbb8f766f95 100755
--- a/test-poc/framework/pom.xml
+++ b/test-poc/framework/pom.xml
@@ -66,6 +66,31 @@
${selenium.version}
pom
+
+ 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/junit/rules/TestRule.java b/test-poc/framework/src/main/java/org/junit/rules/TestRule.java
new file mode 100644
index 000000000000..ec8721b369c6
--- /dev/null
+++ b/test-poc/framework/src/main/java/org/junit/rules/TestRule.java
@@ -0,0 +1,5 @@
+package org.junit.rules;
+
+@SuppressWarnings("unused")
+public interface TestRule {
+}
diff --git a/test-poc/framework/src/main/java/org/junit/runners/model/Statement.java b/test-poc/framework/src/main/java/org/junit/runners/model/Statement.java
new file mode 100644
index 000000000000..6c3e2f085ea2
--- /dev/null
+++ b/test-poc/framework/src/main/java/org/junit/runners/model/Statement.java
@@ -0,0 +1,5 @@
+package org.junit.runners.model;
+
+@SuppressWarnings("unused")
+public class Statement {
+}
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