mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 15:02:05 -03:30
[Keycloak Test Framework] Infinispan cache + ClusterlessTestSuite configuration (#42172)
* [Keycloak Test Framework] Infinispan server + ClusterlessTestSuite and MultisiteTestSuite configuration Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com> * Utilise ClientIntelligence.BASIC to ensure that internal docker IPs never used by Infinispan client Signed-off-by: Ryan Emerson <remerson@ibm.com> * Code refactoring + properties utility Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com> --------- Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com> Signed-off-by: Ryan Emerson <remerson@ibm.com> Co-authored-by: Ryan Emerson <remerson@ibm.com>
This commit is contained in:
parent
63538629db
commit
d9b4bd047f
3
pom.xml
3
pom.xml
@ -172,6 +172,9 @@
|
|||||||
<!-- this is the oracle driver version also used in the Quarkus BOM -->
|
<!-- this is the oracle driver version also used in the Quarkus BOM -->
|
||||||
<oracle-jdbc.version>23.6.0.24.10</oracle-jdbc.version>
|
<oracle-jdbc.version>23.6.0.24.10</oracle-jdbc.version>
|
||||||
|
|
||||||
|
<!-- Infinispan Server Container -->
|
||||||
|
<infinispan.container>quay.io/infinispan/server:${infinispan.version}</infinispan.container>
|
||||||
|
|
||||||
<!-- Test -->
|
<!-- Test -->
|
||||||
<greenmail.version>2.1.3</greenmail.version>
|
<greenmail.version>2.1.3</greenmail.version>
|
||||||
<jmeter.version>2.10</jmeter.version>
|
<jmeter.version>2.10</jmeter.version>
|
||||||
|
|||||||
@ -188,7 +188,7 @@
|
|||||||
<kc.db.postgresql.container.image>${postgresql.container}</kc.db.postgresql.container.image>
|
<kc.db.postgresql.container.image>${postgresql.container}</kc.db.postgresql.container.image>
|
||||||
<kc.db.mariadb.container.image>${mariadb.container}</kc.db.mariadb.container.image>
|
<kc.db.mariadb.container.image>${mariadb.container}</kc.db.mariadb.container.image>
|
||||||
<kc.db.mysql.container.image>${mysql.container}</kc.db.mysql.container.image>
|
<kc.db.mysql.container.image>${mysql.container}</kc.db.mysql.container.image>
|
||||||
<kc.infinispan.container.image>quay.io/infinispan/server:${infinispan.version}</kc.infinispan.container.image>
|
<kc.infinispan.container.image>${infinispan.container}</kc.infinispan.container.image>
|
||||||
<kc.db.mssql.container.image>${mssql.container}</kc.db.mssql.container.image>
|
<kc.db.mssql.container.image>${mssql.container}</kc.db.mssql.container.image>
|
||||||
<kc.db.tidb.container.image>${tidb.container}</kc.db.tidb.container.image>
|
<kc.db.tidb.container.image>${tidb.container}</kc.db.tidb.container.image>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
|
|||||||
@ -42,7 +42,8 @@ Some useful categories include:
|
|||||||
* `org.keycloak.testframework` - Logging from the test framework itself. Setting this to `DEBUG` can be helpful to debug any issues with the test framework itself, or custom suppliers.
|
* `org.keycloak.testframework` - Logging from the test framework itself. Setting this to `DEBUG` can be helpful to debug any issues with the test framework itself, or custom suppliers.
|
||||||
* `org.keycloak` - Logging from the Keycloak server. If you set this to `DEBUG` for example, but don't want debug from the test framework, also explicitly set `org.keycloak.testframework` to for example `INFO`
|
* `org.keycloak` - Logging from the Keycloak server. If you set this to `DEBUG` for example, but don't want debug from the test framework, also explicitly set `org.keycloak.testframework` to for example `INFO`
|
||||||
* `managed.keycloak` - Log output from the managed Keycloak server if you are running the server in `distribution` mode (which is the default)
|
* `managed.keycloak` - Log output from the managed Keycloak server if you are running the server in `distribution` mode (which is the default)
|
||||||
* `managed.db` - Output from database containers are included in this category. Standard out is logged with `DEBUG` level, while standard error is logged with `WARN` level
|
* `managed.db` - Output from database containers are included in this category. Standard out is logged with `DEBUG` level, while standard error is logged with `WARN` level
|
||||||
|
* `managed.infinispan` - Output from the external Infinispan container is included in this category. Standard out is logged with `DEBUG` level, while standard error is logged with `WARN` level
|
||||||
|
|
||||||
### Enable log filtering
|
### Enable log filtering
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ kc.test.log.category."org.keycloak.testframework".level=INFO
|
|||||||
kc.test.log.category."org.keycloak".level=WARN
|
kc.test.log.category."org.keycloak".level=WARN
|
||||||
kc.test.log.category."managed.keycloak".level=WARN
|
kc.test.log.category."managed.keycloak".level=WARN
|
||||||
kc.test.log.category."managed.db".level=WARN
|
kc.test.log.category."managed.db".level=WARN
|
||||||
|
kc.test.log.category."managed.infinispan".level=WARN
|
||||||
```
|
```
|
||||||
|
|
||||||
This should serve as a good starting point balancing the need of log information with not producing too much noise.
|
This should serve as a good starting point balancing the need of log information with not producing too much noise.
|
||||||
@ -89,6 +91,7 @@ KC_TEST_LOG_CATEGORY__ORG_KEYCLOAK___LEVEL=DEBUG
|
|||||||
KC_TEST_LOG_CATEGORY__ORG_KEYCLOAK_TEST__LEVEL=DEBUG
|
KC_TEST_LOG_CATEGORY__ORG_KEYCLOAK_TEST__LEVEL=DEBUG
|
||||||
KC_TEST_LOG_CATEGORY__MANAGED_KEYCLOAK__LEVEL=DEBUG
|
KC_TEST_LOG_CATEGORY__MANAGED_KEYCLOAK__LEVEL=DEBUG
|
||||||
KC_TEST_LOG_CATEGORY__MANAGED_DB__LEVEL=DEBUG
|
KC_TEST_LOG_CATEGORY__MANAGED_DB__LEVEL=DEBUG
|
||||||
|
KC_TEST_LOG_CATEGORY__MANAGED_INFINISPAN__LEVEL=DEBUG
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples using environment variables
|
### Examples using environment variables
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import org.infinispan.server.test.core.CountdownLatchLoggingConsumer;
|
|||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.it.utils.DockerKeycloakDistribution;
|
import org.keycloak.it.utils.DockerKeycloakDistribution;
|
||||||
import org.keycloak.testframework.clustering.LoadBalancer;
|
import org.keycloak.testframework.clustering.LoadBalancer;
|
||||||
|
import org.keycloak.testframework.infinispan.CacheType;
|
||||||
import org.keycloak.testframework.logging.JBossLogConsumer;
|
import org.keycloak.testframework.logging.JBossLogConsumer;
|
||||||
import org.testcontainers.images.RemoteDockerImage;
|
import org.testcontainers.images.RemoteDockerImage;
|
||||||
import org.testcontainers.utility.DockerImageName;
|
import org.testcontainers.utility.DockerImageName;
|
||||||
@ -56,6 +57,10 @@ public class ClusteredKeycloakServer implements KeycloakServer {
|
|||||||
int numServers = containers.length;
|
int numServers = containers.length;
|
||||||
CountdownLatchLoggingConsumer clusterLatch = new CountdownLatchLoggingConsumer(numServers, String.format(CLUSTER_VIEW_REGEX, numServers));
|
CountdownLatchLoggingConsumer clusterLatch = new CountdownLatchLoggingConsumer(numServers, String.format(CLUSTER_VIEW_REGEX, numServers));
|
||||||
String[] imagePeServer = null;
|
String[] imagePeServer = null;
|
||||||
|
|
||||||
|
// Infinispan clustered cache
|
||||||
|
configBuilder.cache(CacheType.ISPN);
|
||||||
|
|
||||||
if (images == null || images.isEmpty() || (imagePeServer = images.split(",")).length == 1) {
|
if (images == null || images.isEmpty() || (imagePeServer = images.split(",")).length == 1) {
|
||||||
startContainersWithSameImage(configBuilder, imagePeServer == null ? SNAPSHOT_IMAGE : imagePeServer[0], clusterLatch);
|
startContainersWithSameImage(configBuilder, imagePeServer == null ? SNAPSHOT_IMAGE : imagePeServer[0], clusterLatch);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -32,9 +32,4 @@ public class ClusteredKeycloakServerSupplier extends AbstractKeycloakServerSuppl
|
|||||||
public Logger getLogger() {
|
public Logger getLogger() {
|
||||||
return LOGGER;
|
return LOGGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String cache() {
|
|
||||||
return "ispn";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.keycloak.testframework;
|
|||||||
|
|
||||||
import org.keycloak.testframework.admin.AdminClientFactorySupplier;
|
import org.keycloak.testframework.admin.AdminClientFactorySupplier;
|
||||||
import org.keycloak.testframework.admin.AdminClientSupplier;
|
import org.keycloak.testframework.admin.AdminClientSupplier;
|
||||||
|
import org.keycloak.testframework.infinispan.InfinispanExternalServerSupplier;
|
||||||
import org.keycloak.testframework.database.DevFileDatabaseSupplier;
|
import org.keycloak.testframework.database.DevFileDatabaseSupplier;
|
||||||
import org.keycloak.testframework.database.DevMemDatabaseSupplier;
|
import org.keycloak.testframework.database.DevMemDatabaseSupplier;
|
||||||
import org.keycloak.testframework.database.TestDatabase;
|
import org.keycloak.testframework.database.TestDatabase;
|
||||||
@ -43,7 +44,8 @@ public class CoreTestFrameworkExtension implements TestFrameworkExtension {
|
|||||||
new EventsSupplier(),
|
new EventsSupplier(),
|
||||||
new AdminEventsSupplier(),
|
new AdminEventsSupplier(),
|
||||||
new HttpClientSupplier(),
|
new HttpClientSupplier(),
|
||||||
new HttpServerSupplier()
|
new HttpServerSupplier(),
|
||||||
|
new InfinispanExternalServerSupplier()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
package org.keycloak.testframework.annotations;
|
||||||
|
|
||||||
|
import org.keycloak.testframework.injection.LifeCycle;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface InjectInfinispanServer {
|
||||||
|
|
||||||
|
LifeCycle lifecycle() default LifeCycle.GLOBAL;
|
||||||
|
}
|
||||||
@ -1,24 +0,0 @@
|
|||||||
package org.keycloak.testframework.database;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class DatabaseProperties {
|
|
||||||
|
|
||||||
private static final Properties PROPERTIES = loadProperties();
|
|
||||||
|
|
||||||
public static String getContainerImageName(String database) {
|
|
||||||
return PROPERTIES.getProperty(database + ".container");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Properties loadProperties() {
|
|
||||||
Properties properties = new Properties();
|
|
||||||
try {
|
|
||||||
properties.load(DatabaseProperties.class.getResourceAsStream("database.properties"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package org.keycloak.testframework.infinispan;
|
||||||
|
|
||||||
|
public enum CacheType {
|
||||||
|
|
||||||
|
// Local Infinispan Cache for Embedded Deployment only
|
||||||
|
LOCAL,
|
||||||
|
|
||||||
|
// Clustered Infinispan Cache can be set for Embedded or External Deployment
|
||||||
|
ISPN;
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package org.keycloak.testframework.infinispan;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.infinispan.server.test.core.InfinispanContainer;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.logging.JBossLogConsumer;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
|
|
||||||
|
public class InfinispanExternalServer extends InfinispanContainer implements InfinispanServer {
|
||||||
|
|
||||||
|
private static final String USER = "keycloak";
|
||||||
|
private static final String PASSWORD = "Password1!";
|
||||||
|
private static final String HOST = "127.0.0.1";
|
||||||
|
|
||||||
|
public static InfinispanExternalServer create() {
|
||||||
|
return new InfinispanExternalServer(ContainerImages.getContainerImageName("infinispan"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
private InfinispanExternalServer(String dockerImageName) {
|
||||||
|
super(dockerImageName);
|
||||||
|
withUser(USER);
|
||||||
|
withPassword(PASSWORD);
|
||||||
|
withLogConsumer(new JBossLogConsumer(Logger.getLogger("managed.infinispan")));
|
||||||
|
addFixedExposedPort(11222, 11222);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> serverConfig() {
|
||||||
|
return Map.of(
|
||||||
|
"cache-remote-host", HOST,
|
||||||
|
"cache-remote-username", USER,
|
||||||
|
"cache-remote-password", PASSWORD,
|
||||||
|
"cache-remote-tls-enabled", "false",
|
||||||
|
"spi-cache-embedded-default-site-name", "ispn",
|
||||||
|
"spi-load-balancer-check-remote-poll-interval", "500",
|
||||||
|
"spi-cache-remote-default-client-intelligence", "BASIC",
|
||||||
|
"-Dkc.cache-remote-create-caches", "true"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package org.keycloak.testframework.infinispan;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.annotations.InjectInfinispanServer;
|
||||||
|
import org.keycloak.testframework.injection.InstanceContext;
|
||||||
|
import org.keycloak.testframework.injection.RequestedInstance;
|
||||||
|
import org.keycloak.testframework.injection.Supplier;
|
||||||
|
import org.keycloak.testframework.injection.SupplierOrder;
|
||||||
|
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
||||||
|
import org.keycloak.testframework.server.KeycloakServerConfigInterceptor;
|
||||||
|
|
||||||
|
public class InfinispanExternalServerSupplier implements Supplier<InfinispanServer, InjectInfinispanServer>, KeycloakServerConfigInterceptor<InfinispanServer, InjectInfinispanServer> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(InfinispanExternalServerSupplier.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InfinispanServer getValue(InstanceContext<InfinispanServer, InjectInfinispanServer> instanceContext) {
|
||||||
|
InfinispanServer server = InfinispanExternalServer.create();
|
||||||
|
getLogger().info("Starting Infinispan Server");
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
getLogger().infov("Infinispan server started in {0} ms", System.currentTimeMillis() - start);
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(InstanceContext<InfinispanServer, InjectInfinispanServer> instanceContext) {
|
||||||
|
instanceContext.getValue().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean compatible(InstanceContext<InfinispanServer, InjectInfinispanServer> a, RequestedInstance<InfinispanServer, InjectInfinispanServer> b) {
|
||||||
|
return a.getSupplier().getRef(a.getAnnotation()).equals(b.getSupplier().getRef(a.getAnnotation()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int order() {
|
||||||
|
return SupplierOrder.BEFORE_KEYCLOAK_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeycloakServerConfigBuilder intercept(KeycloakServerConfigBuilder config, InstanceContext<InfinispanServer, InjectInfinispanServer> instanceContext) {
|
||||||
|
InfinispanServer ispnServer = instanceContext.getValue();
|
||||||
|
|
||||||
|
return config.options(ispnServer.serverConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getLogger() {
|
||||||
|
return LOGGER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package org.keycloak.testframework.infinispan;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface InfinispanServer {
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
Map<String, String> serverConfig();
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package org.keycloak.testframework.server;
|
|||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||||
|
import org.keycloak.testframework.infinispan.InfinispanServer;
|
||||||
import org.keycloak.testframework.config.Config;
|
import org.keycloak.testframework.config.Config;
|
||||||
import org.keycloak.testframework.database.TestDatabase;
|
import org.keycloak.testframework.database.TestDatabase;
|
||||||
import org.keycloak.testframework.injection.AbstractInterceptorHelper;
|
import org.keycloak.testframework.injection.AbstractInterceptorHelper;
|
||||||
@ -21,7 +22,6 @@ public abstract class AbstractKeycloakServerSupplier implements Supplier<Keycloa
|
|||||||
KeycloakServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config());
|
KeycloakServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config());
|
||||||
|
|
||||||
KeycloakServerConfigBuilder command = KeycloakServerConfigBuilder.startDev()
|
KeycloakServerConfigBuilder command = KeycloakServerConfigBuilder.startDev()
|
||||||
.cache(cache())
|
|
||||||
.bootstrapAdminClient(Config.getAdminClientId(), Config.getAdminClientSecret())
|
.bootstrapAdminClient(Config.getAdminClientId(), Config.getAdminClientSecret())
|
||||||
.bootstrapAdminUser(Config.getAdminUsername(), Config.getAdminPassword());
|
.bootstrapAdminUser(Config.getAdminUsername(), Config.getAdminPassword());
|
||||||
|
|
||||||
@ -35,10 +35,16 @@ public abstract class AbstractKeycloakServerSupplier implements Supplier<Keycloa
|
|||||||
|
|
||||||
command = serverConfig.configure(command);
|
command = serverConfig.configure(command);
|
||||||
|
|
||||||
|
// Database startup and Keycloak connection setup
|
||||||
if (requiresDatabase()) {
|
if (requiresDatabase()) {
|
||||||
instanceContext.getDependency(TestDatabase.class);
|
instanceContext.getDependency(TestDatabase.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// External Infinispan startup and Keycloak connection setup
|
||||||
|
if (command.isExternalInfinispanEnabled()) {
|
||||||
|
instanceContext.getDependency(InfinispanServer.class);
|
||||||
|
}
|
||||||
|
|
||||||
ServerConfigInterceptorHelper interceptor = new ServerConfigInterceptorHelper(instanceContext.getRegistry());
|
ServerConfigInterceptorHelper interceptor = new ServerConfigInterceptorHelper(instanceContext.getRegistry());
|
||||||
command = interceptor.intercept(command, instanceContext);
|
command = interceptor.intercept(command, instanceContext);
|
||||||
|
|
||||||
@ -80,10 +86,6 @@ public abstract class AbstractKeycloakServerSupplier implements Supplier<Keycloa
|
|||||||
|
|
||||||
public abstract Logger getLogger();
|
public abstract Logger getLogger();
|
||||||
|
|
||||||
protected String cache() {
|
|
||||||
return "local";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int order() {
|
public int order() {
|
||||||
return SupplierOrder.KEYCLOAK_SERVER;
|
return SupplierOrder.KEYCLOAK_SERVER;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import io.quarkus.maven.dependency.Dependency;
|
|||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.it.utils.OutputConsumer;
|
import org.keycloak.it.utils.OutputConsumer;
|
||||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||||
import org.keycloak.testframework.config.Config;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import io.quarkus.maven.dependency.DependencyBuilder;
|
|||||||
import io.smallrye.config.SmallRyeConfig;
|
import io.smallrye.config.SmallRyeConfig;
|
||||||
import org.eclipse.microprofile.config.spi.ConfigSource;
|
import org.eclipse.microprofile.config.spi.ConfigSource;
|
||||||
import org.keycloak.common.Profile;
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.Profile.Feature;
|
import org.keycloak.testframework.infinispan.CacheType;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -29,6 +29,8 @@ public class KeycloakServerConfigBuilder {
|
|||||||
private final LogBuilder log = new LogBuilder();
|
private final LogBuilder log = new LogBuilder();
|
||||||
private final Set<Dependency> dependencies = new HashSet<>();
|
private final Set<Dependency> dependencies = new HashSet<>();
|
||||||
private final Set<Path> configFiles = new HashSet<>();
|
private final Set<Path> configFiles = new HashSet<>();
|
||||||
|
private CacheType cacheType = CacheType.LOCAL;
|
||||||
|
private boolean externalInfinispan = false;
|
||||||
|
|
||||||
private KeycloakServerConfigBuilder(String command) {
|
private KeycloakServerConfigBuilder(String command) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
@ -48,8 +50,24 @@ public class KeycloakServerConfigBuilder {
|
|||||||
.option("bootstrap-admin-password", password);
|
.option("bootstrap-admin-password", password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeycloakServerConfigBuilder cache(String cache) {
|
public KeycloakServerConfigBuilder cache(CacheType cacheType) {
|
||||||
return option("cache", cache);
|
this.cacheType = cacheType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeycloakServerConfigBuilder externalInfinispanEnabled(boolean enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
this.externalInfinispan = true;
|
||||||
|
cache(CacheType.ISPN);
|
||||||
|
} else {
|
||||||
|
this.externalInfinispan = false;
|
||||||
|
cache(CacheType.LOCAL);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExternalInfinispanEnabled() {
|
||||||
|
return this.externalInfinispan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LogBuilder log() {
|
public LogBuilder log() {
|
||||||
@ -185,12 +203,19 @@ public class KeycloakServerConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<String> toArgs() {
|
List<String> toArgs() {
|
||||||
|
// Cache setup -> supported values: local or ispn
|
||||||
|
option("cache", cacheType.name().toLowerCase());
|
||||||
|
|
||||||
log.build();
|
log.build();
|
||||||
|
|
||||||
List<String> args = new LinkedList<>();
|
List<String> args = new LinkedList<>();
|
||||||
args.add(command);
|
args.add(command);
|
||||||
for (Map.Entry<String, String> e : options.entrySet()) {
|
for (Map.Entry<String, String> e : options.entrySet()) {
|
||||||
args.add("--" + e.getKey() + "=" + e.getValue());
|
if (e.getKey().startsWith("-D")) {
|
||||||
|
args.add(e.getKey() + "=" + e.getValue());
|
||||||
|
} else {
|
||||||
|
args.add("--" + e.getKey() + "=" + e.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!features.isEmpty()) {
|
if (!features.isEmpty()) {
|
||||||
args.add("--features=" + String.join(",", features));
|
args.add("--features=" + String.join(",", features));
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
package org.keycloak.testframework.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class ContainerImages {
|
||||||
|
|
||||||
|
public static String getContainerImageName(String containerName) {
|
||||||
|
return loadProperties().getProperty(containerName + ".container");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Properties loadProperties() {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
try {
|
||||||
|
properties.load(ContainerImages.class.getResourceAsStream("containers.properties"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,10 @@
|
|||||||
|
## Database containers ##
|
||||||
mysql.container=${mysql.container}
|
mysql.container=${mysql.container}
|
||||||
postgres.container=${postgresql.container}
|
postgres.container=${postgresql.container}
|
||||||
mariadb.container=${mariadb.container}
|
mariadb.container=${mariadb.container}
|
||||||
mssql.container=${mssql.container}
|
mssql.container=${mssql.container}
|
||||||
oracle.container=${oracledb.container}
|
oracle.container=${oracledb.container}
|
||||||
tidb.container=${tidb.container}
|
tidb.container=${tidb.container}
|
||||||
|
|
||||||
|
## Infinispan container ##
|
||||||
|
infinispan.container=${infinispan.container}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.keycloak.testframework.database;
|
package org.keycloak.testframework.database;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||||
import org.testcontainers.containers.MariaDBContainer;
|
import org.testcontainers.containers.MariaDBContainer;
|
||||||
import org.testcontainers.utility.DockerImageName;
|
import org.testcontainers.utility.DockerImageName;
|
||||||
@ -13,7 +14,7 @@ class MariaDBTestDatabase extends AbstractContainerTestDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcDatabaseContainer<?> createContainer() {
|
public JdbcDatabaseContainer<?> createContainer() {
|
||||||
return new MariaDBContainer<>(DockerImageName.parse(DatabaseProperties.getContainerImageName(NAME)).asCompatibleSubstituteFor(NAME)).withCommand("--character-set-server=utf8 --collation-server=utf8_unicode_ci");
|
return new MariaDBContainer<>(DockerImageName.parse(ContainerImages.getContainerImageName(NAME)).asCompatibleSubstituteFor(NAME)).withCommand("--character-set-server=utf8 --collation-server=utf8_unicode_ci");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package org.keycloak.testframework.database;
|
package org.keycloak.testframework.database;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||||
import org.testcontainers.containers.MSSQLServerContainer;
|
import org.testcontainers.containers.MSSQLServerContainer;
|
||||||
|
import org.testcontainers.utility.DockerImageName;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -15,7 +17,7 @@ class MSSQLServerTestDatabase extends AbstractContainerTestDatabase {
|
|||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
@Override
|
@Override
|
||||||
public JdbcDatabaseContainer<?> createContainer() {
|
public JdbcDatabaseContainer<?> createContainer() {
|
||||||
return new MSSQLServerContainer<>(DatabaseProperties.getContainerImageName(NAME)).withPassword(getPassword()).withEnv("MSSQL_PID", "Express").acceptLicense();
|
return new MSSQLServerContainer<>(DockerImageName.parse(ContainerImages.getContainerImageName(NAME))).withPassword(getPassword()).withEnv("MSSQL_PID", "Express").acceptLicense();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.keycloak.testframework.database;
|
package org.keycloak.testframework.database;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||||
import org.testcontainers.containers.MySQLContainer;
|
import org.testcontainers.containers.MySQLContainer;
|
||||||
import org.testcontainers.utility.DockerImageName;
|
import org.testcontainers.utility.DockerImageName;
|
||||||
@ -13,7 +14,7 @@ class MySQLTestDatabase extends AbstractContainerTestDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcDatabaseContainer<?> createContainer() {
|
public JdbcDatabaseContainer<?> createContainer() {
|
||||||
return new MySQLContainer<>(DockerImageName.parse(DatabaseProperties.getContainerImageName(NAME)).asCompatibleSubstituteFor(NAME));
|
return new MySQLContainer<>(DockerImageName.parse(ContainerImages.getContainerImageName(NAME)).asCompatibleSubstituteFor(NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.keycloak.testframework.database;
|
package org.keycloak.testframework.database;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||||
import org.testcontainers.oracle.OracleContainer;
|
import org.testcontainers.oracle.OracleContainer;
|
||||||
import org.testcontainers.utility.DockerImageName;
|
import org.testcontainers.utility.DockerImageName;
|
||||||
@ -13,7 +14,7 @@ class OracleTestDatabase extends AbstractContainerTestDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcDatabaseContainer<?> createContainer() {
|
public JdbcDatabaseContainer<?> createContainer() {
|
||||||
return new OracleContainer(DockerImageName.parse(DatabaseProperties.getContainerImageName(NAME)).asCompatibleSubstituteFor("gvenzl/oracle-free"));
|
return new OracleContainer(DockerImageName.parse(ContainerImages.getContainerImageName(NAME)).asCompatibleSubstituteFor("gvenzl/oracle-free"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.keycloak.testframework.database;
|
package org.keycloak.testframework.database;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||||
import org.testcontainers.containers.PostgreSQLContainer;
|
import org.testcontainers.containers.PostgreSQLContainer;
|
||||||
import org.testcontainers.utility.DockerImageName;
|
import org.testcontainers.utility.DockerImageName;
|
||||||
@ -15,7 +16,7 @@ public class PostgresTestDatabase extends AbstractContainerTestDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcDatabaseContainer<?> createContainer() {
|
public JdbcDatabaseContainer<?> createContainer() {
|
||||||
return new PostgreSQLContainer<>(DockerImageName.parse(DatabaseProperties.getContainerImageName(NAME)).asCompatibleSubstituteFor(NAME));
|
return new PostgreSQLContainer<>(DockerImageName.parse(ContainerImages.getContainerImageName(NAME)).asCompatibleSubstituteFor(NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.keycloak.testframework.database;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.testframework.util.ContainerImages;
|
||||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||||
import org.testcontainers.tidb.TiDBContainer;
|
import org.testcontainers.tidb.TiDBContainer;
|
||||||
import org.testcontainers.utility.DockerImageName;
|
import org.testcontainers.utility.DockerImageName;
|
||||||
@ -14,7 +15,7 @@ class TiDBTestDatabase extends AbstractContainerTestDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcDatabaseContainer<?> createContainer() {
|
public JdbcDatabaseContainer<?> createContainer() {
|
||||||
return new TiDBContainer(DockerImageName.parse(DatabaseProperties.getContainerImageName(NAME)).asCompatibleSubstituteFor("pingcap/tidb")){
|
return new TiDBContainer(DockerImageName.parse(ContainerImages.getContainerImageName(NAME)).asCompatibleSubstituteFor("pingcap/tidb")){
|
||||||
@Override
|
@Override
|
||||||
public TiDBContainer withDatabaseName(String databaseName) {
|
public TiDBContainer withDatabaseName(String databaseName) {
|
||||||
if(StringUtils.equals(this.getDatabaseName(), databaseName)) {
|
if(StringUtils.equals(this.getDatabaseName(), databaseName)) {
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
package org.keycloak.tests.suites;
|
||||||
|
|
||||||
|
import org.junit.platform.suite.api.AfterSuite;
|
||||||
|
import org.junit.platform.suite.api.BeforeSuite;
|
||||||
|
import org.junit.platform.suite.api.SelectClasses;
|
||||||
|
import org.junit.platform.suite.api.Suite;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
|
import org.keycloak.testframework.injection.SuiteSupport;
|
||||||
|
import org.keycloak.testframework.server.KeycloakServerConfig;
|
||||||
|
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
||||||
|
import org.keycloak.tests.admin.ClientTest;
|
||||||
|
|
||||||
|
@Suite
|
||||||
|
@SelectClasses({ClientTest.class})
|
||||||
|
public class ClusterlessTestSuite {
|
||||||
|
|
||||||
|
@BeforeSuite
|
||||||
|
public static void beforeSuite() {
|
||||||
|
SuiteSupport.startSuite()
|
||||||
|
.registerServerConfig(ClusterlessServerConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterSuite
|
||||||
|
public static void afterSuite() {
|
||||||
|
SuiteSupport.stopSuite();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ClusterlessServerConfig implements KeycloakServerConfig {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||||
|
return config.features(Profile.Feature.CLUSTERLESS)
|
||||||
|
.featuresDisabled(Profile.Feature.PERSISTENT_USER_SESSIONS)
|
||||||
|
.externalInfinispanEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package org.keycloak.tests.suites;
|
||||||
|
|
||||||
|
import org.junit.platform.suite.api.AfterSuite;
|
||||||
|
import org.junit.platform.suite.api.BeforeSuite;
|
||||||
|
import org.junit.platform.suite.api.SelectClasses;
|
||||||
|
import org.junit.platform.suite.api.Suite;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
|
import org.keycloak.testframework.injection.SuiteSupport;
|
||||||
|
import org.keycloak.testframework.server.KeycloakServerConfig;
|
||||||
|
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
||||||
|
import org.keycloak.tests.admin.ClientTest;
|
||||||
|
|
||||||
|
@Suite
|
||||||
|
@SelectClasses({ClientTest.class})
|
||||||
|
public class MultisiteTestSuite {
|
||||||
|
|
||||||
|
@BeforeSuite
|
||||||
|
public static void beforeSuite() {
|
||||||
|
SuiteSupport.startSuite()
|
||||||
|
.registerServerConfig(MultisiteServerConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterSuite
|
||||||
|
public static void afterSuite() {
|
||||||
|
SuiteSupport.stopSuite();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MultisiteServerConfig implements KeycloakServerConfig {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||||
|
return config.features(Profile.Feature.MULTI_SITE)
|
||||||
|
.featuresDisabled(Profile.Feature.PERSISTENT_USER_SESSIONS)
|
||||||
|
.externalInfinispanEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,4 +7,5 @@ kc.test.log.category."org.keycloak.tests".level=INFO
|
|||||||
kc.test.log.category."testinfo".level=INFO
|
kc.test.log.category."testinfo".level=INFO
|
||||||
kc.test.log.category."org.keycloak".level=WARN
|
kc.test.log.category."org.keycloak".level=WARN
|
||||||
kc.test.log.category."managed.keycloak".level=WARN
|
kc.test.log.category."managed.keycloak".level=WARN
|
||||||
kc.test.log.category."managed.db".level=WARN
|
kc.test.log.category."managed.db".level=WARN
|
||||||
|
kc.test.log.category."managed.infinispan".level=WARN
|
||||||
|
|||||||
@ -13,4 +13,5 @@ kc.test.log.category."org.keycloak.it".level=INFO
|
|||||||
kc.test.log.category."org.keycloak".level=WARN
|
kc.test.log.category."org.keycloak".level=WARN
|
||||||
kc.test.log.category."managed.keycloak".level=WARN
|
kc.test.log.category."managed.keycloak".level=WARN
|
||||||
kc.test.log.category."managed.db".level=WARN
|
kc.test.log.category."managed.db".level=WARN
|
||||||
|
kc.test.log.category."managed.infinispan".level=WARN
|
||||||
kc.test.log.category."org.keycloak.testframework.clustering".level=WARN
|
kc.test.log.category."org.keycloak.testframework.clustering".level=WARN
|
||||||
@ -780,7 +780,7 @@
|
|||||||
<images>
|
<images>
|
||||||
<image>
|
<image>
|
||||||
<alias>infinispan</alias>
|
<alias>infinispan</alias>
|
||||||
<name>quay.io/infinispan/server:${infinispan.version}</name>
|
<name>${infinispan.container}</name>
|
||||||
<run>
|
<run>
|
||||||
<ports>
|
<ports>
|
||||||
<port>11222:11222</port>
|
<port>11222:11222</port>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user