mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-02 21:21:10 -05:00
Add support to intercept server and realm config to test framework (#35184)
Closes #35173 Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
+8
-8
@@ -12,11 +12,11 @@ import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.realm.ClientSupplier;
|
||||
import org.keycloak.test.framework.realm.RealmSupplier;
|
||||
import org.keycloak.test.framework.realm.UserSupplier;
|
||||
import org.keycloak.test.framework.server.DistributionKeycloakTestServerSupplier;
|
||||
import org.keycloak.test.framework.server.EmbeddedKeycloakTestServerSupplier;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServer;
|
||||
import org.keycloak.test.framework.server.DistributionKeycloakServerSupplier;
|
||||
import org.keycloak.test.framework.server.EmbeddedKeycloakServerSupplier;
|
||||
import org.keycloak.test.framework.server.KeycloakServer;
|
||||
import org.keycloak.test.framework.server.KeycloakUrlsSupplier;
|
||||
import org.keycloak.test.framework.server.RemoteKeycloakTestServerSupplier;
|
||||
import org.keycloak.test.framework.server.RemoteKeycloakServerSupplier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -30,9 +30,9 @@ public class CoreTestFrameworkExtension implements TestFrameworkExtension {
|
||||
new ClientSupplier(),
|
||||
new RealmSupplier(),
|
||||
new UserSupplier(),
|
||||
new DistributionKeycloakTestServerSupplier(),
|
||||
new EmbeddedKeycloakTestServerSupplier(),
|
||||
new RemoteKeycloakTestServerSupplier(),
|
||||
new DistributionKeycloakServerSupplier(),
|
||||
new EmbeddedKeycloakServerSupplier(),
|
||||
new RemoteKeycloakServerSupplier(),
|
||||
new KeycloakUrlsSupplier(),
|
||||
new DevMemDatabaseSupplier(),
|
||||
new DevFileDatabaseSupplier(),
|
||||
@@ -46,7 +46,7 @@ public class CoreTestFrameworkExtension implements TestFrameworkExtension {
|
||||
@Override
|
||||
public Map<Class<?>, String> valueTypeAliases() {
|
||||
return Map.of(
|
||||
KeycloakTestServer.class, "server",
|
||||
KeycloakServer.class, "server",
|
||||
TestDatabase.class, "database"
|
||||
);
|
||||
}
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServer;
|
||||
import org.keycloak.test.framework.server.KeycloakServer;
|
||||
|
||||
public class KeycloakAdminClientSupplier implements Supplier<Keycloak, InjectAdminClient> {
|
||||
|
||||
@@ -25,9 +25,9 @@ public class KeycloakAdminClientSupplier implements Supplier<Keycloak, InjectAdm
|
||||
|
||||
@Override
|
||||
public Keycloak getValue(InstanceContext<Keycloak, InjectAdminClient> instanceContext) {
|
||||
KeycloakTestServer testServer = instanceContext.getDependency(KeycloakTestServer.class);
|
||||
KeycloakServer server = instanceContext.getDependency(KeycloakServer.class);
|
||||
return KeycloakBuilder.builder()
|
||||
.serverUrl(testServer.getBaseUrl())
|
||||
.serverUrl(server.getBaseUrl())
|
||||
.realm("master")
|
||||
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
||||
.clientId(Config.getAdminClientId())
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package org.keycloak.test.framework.annotations;
|
||||
|
||||
import org.keycloak.test.framework.server.DefaultKeycloakTestServerConfig;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServerConfig;
|
||||
import org.keycloak.test.framework.server.DefaultKeycloakServerConfig;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfig;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -12,6 +12,6 @@ import java.lang.annotation.Target;
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface KeycloakIntegrationTest {
|
||||
|
||||
Class<? extends KeycloakTestServerConfig> config() default DefaultKeycloakTestServerConfig.class;
|
||||
Class<? extends KeycloakServerConfig> config() default DefaultKeycloakServerConfig.class;
|
||||
|
||||
}
|
||||
|
||||
+14
-1
@@ -5,8 +5,11 @@ import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigBuilder;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigInterceptor;
|
||||
|
||||
public abstract class AbstractDatabaseSupplier implements Supplier<TestDatabase, InjectTestDatabase> {
|
||||
public abstract class AbstractDatabaseSupplier implements Supplier<TestDatabase, InjectTestDatabase>, KeycloakServerConfigInterceptor<TestDatabase, InjectTestDatabase> {
|
||||
|
||||
@Override
|
||||
public Class<InjectTestDatabase> getAnnotationClass() {
|
||||
@@ -41,4 +44,14 @@ public abstract class AbstractDatabaseSupplier implements Supplier<TestDatabase,
|
||||
public void close(InstanceContext<TestDatabase, InjectTestDatabase> instanceContext) {
|
||||
instanceContext.getValue().stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder intercept(KeycloakServerConfigBuilder serverConfig, InstanceContext<TestDatabase, InjectTestDatabase> instanceContext) {
|
||||
return serverConfig.options(instanceContext.getValue().serverConfig());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.BEFORE_KEYCLOAK_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
-6
@@ -1,7 +1,5 @@
|
||||
package org.keycloak.test.framework.database;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface TestDatabase {
|
||||
@@ -12,8 +10,4 @@ public interface TestDatabase {
|
||||
|
||||
Map<String, String> serverConfig();
|
||||
|
||||
default Dependency jdbcDriver() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
@@ -5,8 +5,10 @@ import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
|
||||
public class AdminEventsSupplier implements Supplier<AdminEvents, InjectAdminEvents> {
|
||||
|
||||
@Override
|
||||
public Class<InjectAdminEvents> getAnnotationClass() {
|
||||
return InjectAdminEvents.class;
|
||||
@@ -44,4 +46,9 @@ public class AdminEventsSupplier implements Supplier<AdminEvents, InjectAdminEve
|
||||
public boolean compatible(InstanceContext<AdminEvents, InjectAdminEvents> a, RequestedInstance<AdminEvents, InjectAdminEvents> b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.BEFORE_KEYCLOAK_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -5,8 +5,10 @@ import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
|
||||
public class EventsSupplier implements Supplier<Events, InjectEvents> {
|
||||
|
||||
@Override
|
||||
public Class<InjectEvents> getAnnotationClass() {
|
||||
return InjectEvents.class;
|
||||
@@ -44,4 +46,9 @@ public class EventsSupplier implements Supplier<Events, InjectEvents> {
|
||||
public boolean compatible(InstanceContext<Events, InjectEvents> a, RequestedInstance<Events, InjectEvents> b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.BEFORE_KEYCLOAK_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,12 +17,12 @@ public class SysLogServer {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(SysLogServer.class);
|
||||
private static final int MAX_THREADS = 5;
|
||||
private ServerSocket serverSocket;
|
||||
private final ServerSocket serverSocket;
|
||||
private final List<Thread> threads = Collections.synchronizedList(new LinkedList<>());
|
||||
private final Set<SysLogListener> listeners = new HashSet<>();
|
||||
private boolean running = true;
|
||||
|
||||
public void start() throws IOException {
|
||||
public SysLogServer() throws IOException {
|
||||
serverSocket = new ServerSocket(0);
|
||||
startThread();
|
||||
}
|
||||
|
||||
+24
-4
@@ -5,10 +5,14 @@ import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigBuilder;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigInterceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SysLogServerSupplier implements Supplier<SysLogServer, InjectSysLogServer> {
|
||||
public class SysLogServerSupplier implements Supplier<SysLogServer, InjectSysLogServer>, KeycloakServerConfigInterceptor<SysLogServer, InjectSysLogServer> {
|
||||
|
||||
@Override
|
||||
public Class<InjectSysLogServer> getAnnotationClass() {
|
||||
return InjectSysLogServer.class;
|
||||
@@ -22,9 +26,7 @@ public class SysLogServerSupplier implements Supplier<SysLogServer, InjectSysLog
|
||||
@Override
|
||||
public SysLogServer getValue(InstanceContext<SysLogServer, InjectSysLogServer> instanceContext) {
|
||||
try {
|
||||
SysLogServer server = new SysLogServer();
|
||||
server.start();
|
||||
return server;
|
||||
return new SysLogServer();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -49,4 +51,22 @@ public class SysLogServerSupplier implements Supplier<SysLogServer, InjectSysLog
|
||||
public boolean compatible(InstanceContext<SysLogServer, InjectSysLogServer> a, RequestedInstance<SysLogServer, InjectSysLogServer> b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder intercept(KeycloakServerConfigBuilder serverConfig, InstanceContext<SysLogServer, InjectSysLogServer> instanceContext) {
|
||||
serverConfig.log()
|
||||
.handlers(KeycloakServerConfigBuilder.LogHandlers.SYSLOG)
|
||||
.syslogEndpoint(instanceContext.getValue().getEndpoint())
|
||||
.handlerLevel(KeycloakServerConfigBuilder.LogHandlers.SYSLOG, "INFO");
|
||||
|
||||
serverConfig.option("spi-events-listener-jboss-logging-success-level", "INFO")
|
||||
.log().categoryLevel("org.keycloak.events", "INFO");
|
||||
|
||||
return serverConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.BEFORE_KEYCLOAK_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -8,6 +8,7 @@ import java.util.Set;
|
||||
|
||||
public class InstanceContext<T, A extends Annotation> {
|
||||
|
||||
private final int instanceId;
|
||||
private final Registry registry;
|
||||
private final Supplier<T, A> supplier;
|
||||
private final A annotation;
|
||||
@@ -18,7 +19,8 @@ public class InstanceContext<T, A extends Annotation> {
|
||||
private final String ref;
|
||||
private final Map<String, Object> notes = new HashMap<>();
|
||||
|
||||
public InstanceContext(Registry registry, Supplier<T, A> supplier, A annotation, Class<? extends T> requestedValueType) {
|
||||
public InstanceContext(int instanceId, Registry registry, Supplier<T, A> supplier, A annotation, Class<? extends T> requestedValueType) {
|
||||
this.instanceId = instanceId != -1 ? instanceId : hashCode();
|
||||
this.registry = registry;
|
||||
this.supplier = supplier;
|
||||
this.annotation = annotation;
|
||||
@@ -27,6 +29,10 @@ public class InstanceContext<T, A extends Annotation> {
|
||||
this.ref = StringUtil.convertEmptyToNull(supplier.getRef(annotation));
|
||||
}
|
||||
|
||||
public int getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public <D> D getDependency(Class<D> typeClazz) {
|
||||
return getDependency(typeClazz, null);
|
||||
}
|
||||
|
||||
+34
-4
@@ -8,6 +8,7 @@ import org.keycloak.test.framework.config.Config;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -61,6 +62,14 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
throw new RuntimeException("Dependency not found: " + typeClass);
|
||||
}
|
||||
|
||||
public List<InstanceContext<?, ?>> getDeployedInstances() {
|
||||
return deployedInstances;
|
||||
}
|
||||
|
||||
public List<RequestedInstance<?, ?>> getRequestedInstances() {
|
||||
return requestedInstances;
|
||||
}
|
||||
|
||||
private <T> T getDeployedDependency(Class<T> typeClass, String ref, InstanceContext dependent) {
|
||||
InstanceContext dependency = getDeployedInstance(typeClass, ref);
|
||||
if (dependency != null) {
|
||||
@@ -80,7 +89,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
private <T> T getRequestedDependency(Class<T> typeClass, String ref, InstanceContext dependent) {
|
||||
RequestedInstance requestedDependency = getRequestedInstance(typeClass, ref);
|
||||
if (requestedDependency != null) {
|
||||
InstanceContext dependency = new InstanceContext<Object, Annotation>(this, requestedDependency.getSupplier(), requestedDependency.getAnnotation(), requestedDependency.getValueType());
|
||||
InstanceContext dependency = new InstanceContext<Object, Annotation>(requestedDependency.getInstanceId(), this, requestedDependency.getSupplier(), requestedDependency.getAnnotation(), requestedDependency.getValueType());
|
||||
dependency.setValue(requestedDependency.getSupplier().getValue(dependency));
|
||||
dependency.registerDependency(dependent);
|
||||
deployedInstances.add(dependency);
|
||||
@@ -104,7 +113,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
if (supplied.isPresent()) {
|
||||
Supplier<T, ?> supplier = (Supplier<T, ?>) supplied.get();
|
||||
Annotation defaultAnnotation = DefaultAnnotationProxy.proxy(supplier.getAnnotationClass());
|
||||
dependency = new InstanceContext(this, supplier, defaultAnnotation, typeClass);
|
||||
dependency = new InstanceContext(-1, this, supplier, defaultAnnotation, typeClass);
|
||||
|
||||
dependency.registerDependency(dependent);
|
||||
dependency.setValue(supplier.getValue(dependency));
|
||||
@@ -176,11 +185,12 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
}
|
||||
|
||||
private void deployRequestedInstances() {
|
||||
requestedInstances.sort(RequestedInstanceComparator.INSTANCE);
|
||||
while (!requestedInstances.isEmpty()) {
|
||||
RequestedInstance requestedInstance = requestedInstances.remove(0);
|
||||
|
||||
if (getDeployedInstance(requestedInstance) == null) {
|
||||
InstanceContext instance = new InstanceContext(this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType());
|
||||
InstanceContext instance = new InstanceContext(requestedInstance.getInstanceId(), this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType());
|
||||
instance.setValue(requestedInstance.getSupplier().getValue(instance));
|
||||
deployedInstances.add(instance);
|
||||
|
||||
@@ -233,7 +243,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
|
||||
public void close() {
|
||||
LOGGER.debug("Closing all instances");
|
||||
List<InstanceContext<?, ?>> destroy = deployedInstances.stream().toList();
|
||||
List<InstanceContext<?, ?>> destroy = deployedInstances.stream().sorted(InstanceContextComparator.INSTANCE.reversed()).toList();
|
||||
destroy.forEach(this::destroy);
|
||||
}
|
||||
|
||||
@@ -382,4 +392,24 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
return fields;
|
||||
}
|
||||
|
||||
private static class RequestedInstanceComparator implements Comparator<RequestedInstance> {
|
||||
|
||||
static final RequestedInstanceComparator INSTANCE = new RequestedInstanceComparator();
|
||||
|
||||
@Override
|
||||
public int compare(RequestedInstance o1, RequestedInstance o2) {
|
||||
return Integer.compare(o1.getSupplier().order(), o2.getSupplier().order());
|
||||
}
|
||||
}
|
||||
|
||||
private static class InstanceContextComparator implements Comparator<InstanceContext> {
|
||||
|
||||
static final InstanceContextComparator INSTANCE = new InstanceContextComparator();
|
||||
|
||||
@Override
|
||||
public int compare(InstanceContext o1, InstanceContext o2) {
|
||||
return Integer.compare(o1.getSupplier().order(), o2.getSupplier().order());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -4,6 +4,7 @@ import java.lang.annotation.Annotation;
|
||||
|
||||
public class RequestedInstance<T, A extends Annotation> {
|
||||
|
||||
private final int instanceId;
|
||||
private final Supplier<T, A> supplier;
|
||||
private final A annotation;
|
||||
private final Class<? extends T> valueType;
|
||||
@@ -11,6 +12,7 @@ public class RequestedInstance<T, A extends Annotation> {
|
||||
private final String ref;
|
||||
|
||||
public RequestedInstance(Supplier<T, A> supplier, A annotation, Class<? extends T> valueType) {
|
||||
this.instanceId = this.hashCode();
|
||||
this.supplier = supplier;
|
||||
this.annotation = annotation;
|
||||
this.valueType = valueType;
|
||||
@@ -18,6 +20,10 @@ public class RequestedInstance<T, A extends Annotation> {
|
||||
this.ref = StringUtil.convertEmptyToNull(supplier.getRef(annotation));
|
||||
}
|
||||
|
||||
public int getInstanceId() {
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
public Supplier<T, A> getSupplier() {
|
||||
return supplier;
|
||||
}
|
||||
|
||||
@@ -34,4 +34,7 @@ public interface Supplier<T, S extends Annotation> {
|
||||
default void onBeforeEach(InstanceContext<T, S> instanceContext) {
|
||||
}
|
||||
|
||||
default int order() {
|
||||
return SupplierOrder.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.keycloak.test.framework.injection;
|
||||
|
||||
public interface SupplierOrder {
|
||||
|
||||
int BEFORE_KEYCLOAK_SERVER = 100;
|
||||
int KEYCLOAK_SERVER = 250;
|
||||
int BEFORE_REALM = 500;
|
||||
int REALM = 750;
|
||||
int DEFAULT = 1000;
|
||||
|
||||
}
|
||||
+11
-1
@@ -4,9 +4,10 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RolesRepresentation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RealmConfigBuilder {
|
||||
|
||||
@@ -67,6 +68,15 @@ public class RealmConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmConfigBuilder smtp(String host, int port, String from) {
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put("host", host);
|
||||
config.put("port", Integer.toString(port));
|
||||
config.put("from", from);
|
||||
rep.setSmtpServer(config);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RealmRepresentation build() {
|
||||
return rep;
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.keycloak.test.framework.realm;
|
||||
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
public interface RealmConfigInterceptor<T, S extends Annotation> {
|
||||
|
||||
RealmConfigBuilder intercept(RealmConfigBuilder realm, InstanceContext<T, S> instanceContext);
|
||||
|
||||
}
|
||||
+39
-4
@@ -5,10 +5,13 @@ import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.test.framework.annotations.InjectRealm;
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.Registry;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierHelpers;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServer;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
import org.keycloak.test.framework.server.AbstractInterceptorHelper;
|
||||
import org.keycloak.test.framework.server.KeycloakServer;
|
||||
|
||||
public class RealmSupplier implements Supplier<ManagedRealm, InjectRealm> {
|
||||
|
||||
@@ -26,11 +29,17 @@ public class RealmSupplier implements Supplier<ManagedRealm, InjectRealm> {
|
||||
|
||||
@Override
|
||||
public ManagedRealm getValue(InstanceContext<ManagedRealm, InjectRealm> instanceContext) {
|
||||
KeycloakTestServer server = instanceContext.getDependency(KeycloakTestServer.class);
|
||||
KeycloakServer server = instanceContext.getDependency(KeycloakServer.class);
|
||||
Keycloak adminClient = instanceContext.getDependency(Keycloak.class);
|
||||
|
||||
RealmConfig config = SupplierHelpers.getInstance(instanceContext.getAnnotation().config());
|
||||
RealmRepresentation realmRepresentation = config.configure(RealmConfigBuilder.create()).build();
|
||||
|
||||
RealmConfigBuilder realmConfigBuilder = config.configure(RealmConfigBuilder.create());
|
||||
|
||||
RealmConfigInterceptorHelper interceptor = new RealmConfigInterceptorHelper(instanceContext.getRegistry());
|
||||
realmConfigBuilder = interceptor.intercept(realmConfigBuilder, instanceContext);
|
||||
|
||||
RealmRepresentation realmRepresentation = realmConfigBuilder.build();
|
||||
|
||||
if (realmRepresentation.getRealm() == null) {
|
||||
String realmName = SupplierHelpers.createName(instanceContext);
|
||||
@@ -57,7 +66,12 @@ public class RealmSupplier implements Supplier<ManagedRealm, InjectRealm> {
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<ManagedRealm, InjectRealm> a, RequestedInstance<ManagedRealm, InjectRealm> b) {
|
||||
return a.getAnnotation().config().equals(b.getAnnotation().config());
|
||||
if (!a.getAnnotation().config().equals(b.getAnnotation().config())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RealmConfigInterceptorHelper interceptor = new RealmConfigInterceptorHelper(a.getRegistry());
|
||||
return interceptor.sameInterceptors(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,4 +81,25 @@ public class RealmSupplier implements Supplier<ManagedRealm, InjectRealm> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.REALM;
|
||||
}
|
||||
|
||||
private static class RealmConfigInterceptorHelper extends AbstractInterceptorHelper<RealmConfigInterceptor, RealmConfigBuilder> {
|
||||
|
||||
private RealmConfigInterceptorHelper(Registry registry) {
|
||||
super(registry, RealmConfigInterceptor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmConfigBuilder intercept(RealmConfigBuilder value, Supplier<?, ?> supplier, InstanceContext<?, ?> existingInstance) {
|
||||
if (supplier instanceof RealmConfigInterceptor interceptor) {
|
||||
value = interceptor.intercept(value, existingInstance);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.Registry;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractInterceptorHelper<I, V> {
|
||||
|
||||
private final Class<?> interceptorClass;
|
||||
private final List<Interception> interceptions = new LinkedList<>();
|
||||
private final InterceptedBy interceptedBy = new InterceptedBy();
|
||||
|
||||
|
||||
|
||||
public AbstractInterceptorHelper(Registry registry, Class<I> interceptorClass) {
|
||||
this.interceptorClass = interceptorClass;
|
||||
|
||||
registry.getDeployedInstances().stream().filter(i -> isInterceptor(i.getSupplier())).forEach(i -> interceptions.add(new Interception(i)));
|
||||
registry.getRequestedInstances().stream().filter(r -> isInterceptor(r.getSupplier())).forEach(r -> interceptions.add(new Interception(r)));
|
||||
|
||||
interceptions.forEach(i -> interceptedBy.put(i.supplier, i.instanceId));
|
||||
}
|
||||
|
||||
public boolean sameInterceptors(InstanceContext<?, ?> instanceContext) {
|
||||
InterceptedBy previousInterceptedBy = instanceContext.getNote("InterceptedBy", InterceptedBy.class);
|
||||
return interceptedBy.equals(previousInterceptedBy);
|
||||
}
|
||||
|
||||
public V intercept(V value, InstanceContext<?, ?> instanceContext) {
|
||||
for (Interception interception : interceptions) {
|
||||
value = intercept(value, interception.supplier, interception.existingInstance);
|
||||
}
|
||||
instanceContext.addNote("InterceptedBy", interceptedBy);
|
||||
return value;
|
||||
}
|
||||
|
||||
public abstract V intercept(V value, Supplier<?, ?> supplier, InstanceContext<?, ?> existingInstance);
|
||||
|
||||
private boolean isInterceptor(Supplier<?, ?> supplier) {
|
||||
return interceptorClass.isAssignableFrom(supplier.getClass());
|
||||
}
|
||||
|
||||
public static class InterceptedBy extends HashMap<Supplier<?, ?>, Integer> {
|
||||
}
|
||||
|
||||
private static class Interception {
|
||||
|
||||
private final int instanceId;
|
||||
private final Supplier<?, ?> supplier;
|
||||
private final InstanceContext<?, ?> existingInstance;
|
||||
|
||||
public Interception(InstanceContext<?, ?> existingInstance) {
|
||||
this.supplier = existingInstance.getSupplier();
|
||||
this.instanceId = existingInstance.getInstanceId();
|
||||
this.existingInstance = existingInstance;
|
||||
}
|
||||
|
||||
public Interception(RequestedInstance<?, ?> requestedInstance) {
|
||||
this.supplier = requestedInstance.getSupplier();
|
||||
this.instanceId = requestedInstance.getInstanceId();
|
||||
this.existingInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.config.Config;
|
||||
import org.keycloak.test.framework.database.TestDatabase;
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.Registry;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierHelpers;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
|
||||
public abstract class AbstractKeycloakServerSupplier implements Supplier<KeycloakServer, KeycloakIntegrationTest> {
|
||||
|
||||
@Override
|
||||
public Class<KeycloakServer> getValueType() {
|
||||
return KeycloakServer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<KeycloakIntegrationTest> getAnnotationClass() {
|
||||
return KeycloakIntegrationTest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakServer getValue(InstanceContext<KeycloakServer, KeycloakIntegrationTest> instanceContext) {
|
||||
KeycloakIntegrationTest annotation = instanceContext.getAnnotation();
|
||||
KeycloakServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config());
|
||||
|
||||
KeycloakServerConfigBuilder command = KeycloakServerConfigBuilder.startDev()
|
||||
.cache("local")
|
||||
.bootstrapAdminClient(Config.getAdminClientId(), Config.getAdminClientSecret());
|
||||
|
||||
command.log().handlers(KeycloakServerConfigBuilder.LogHandlers.CONSOLE);
|
||||
|
||||
command = serverConfig.configure(command);
|
||||
|
||||
if (requiresDatabase()) {
|
||||
instanceContext.getDependency(TestDatabase.class);
|
||||
}
|
||||
|
||||
ServerConfigInterceptorHelper interceptor = new ServerConfigInterceptorHelper(instanceContext.getRegistry());
|
||||
command = interceptor.intercept(command, instanceContext);
|
||||
|
||||
command.log().fromConfig(Config.getConfig());
|
||||
|
||||
getLogger().info("Starting Keycloak test server");
|
||||
if (getLogger().isDebugEnabled()) {
|
||||
getLogger().debugv("Startup command and options: \n\t{0}", String.join("\n\t", command.toArgs()));
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
KeycloakServer server = getServer();
|
||||
server.start(command);
|
||||
|
||||
getLogger().infov("Keycloak test server started in {0} ms", System.currentTimeMillis() - start);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifeCycle getDefaultLifecycle() {
|
||||
return LifeCycle.GLOBAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<KeycloakServer, KeycloakIntegrationTest> a, RequestedInstance<KeycloakServer, KeycloakIntegrationTest> b) {
|
||||
if (!a.getAnnotation().config().equals(b.getAnnotation().config())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ServerConfigInterceptorHelper interceptor = new ServerConfigInterceptorHelper(a.getRegistry());
|
||||
return interceptor.sameInterceptors(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(InstanceContext<KeycloakServer, KeycloakIntegrationTest> instanceContext) {
|
||||
instanceContext.getValue().stop();
|
||||
}
|
||||
|
||||
public abstract KeycloakServer getServer();
|
||||
|
||||
public abstract boolean requiresDatabase();
|
||||
|
||||
public abstract Logger getLogger();
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.KEYCLOAK_SERVER;
|
||||
}
|
||||
|
||||
private static class ServerConfigInterceptorHelper extends AbstractInterceptorHelper<KeycloakServerConfigInterceptor, KeycloakServerConfigBuilder> {
|
||||
|
||||
private ServerConfigInterceptorHelper(Registry registry) {
|
||||
super(registry, KeycloakServerConfigInterceptor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder intercept(KeycloakServerConfigBuilder value, Supplier<?, ?> supplier, InstanceContext<?, ?> existingInstance) {
|
||||
if (supplier instanceof KeycloakServerConfigInterceptor keycloakServerConfigInterceptor) {
|
||||
value = keycloakServerConfigInterceptor.intercept(value, existingInstance);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.config.Config;
|
||||
import org.keycloak.test.framework.database.TestDatabase;
|
||||
import org.keycloak.test.framework.events.SysLogServer;
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.LifeCycle;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.injection.SupplierHelpers;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractKeycloakTestServerSupplier implements Supplier<KeycloakTestServer, KeycloakIntegrationTest> {
|
||||
|
||||
@Override
|
||||
public Class<KeycloakTestServer> getValueType() {
|
||||
return KeycloakTestServer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<KeycloakIntegrationTest> getAnnotationClass() {
|
||||
return KeycloakIntegrationTest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakTestServer getValue(InstanceContext<KeycloakTestServer, KeycloakIntegrationTest> instanceContext) {
|
||||
KeycloakIntegrationTest annotation = instanceContext.getAnnotation();
|
||||
KeycloakTestServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config());
|
||||
|
||||
CommandBuilder command = CommandBuilder.startDev()
|
||||
.cache("local")
|
||||
.bootstrapAdminClient(Config.getAdminClientId(), Config.getAdminClientSecret());
|
||||
|
||||
if (serverConfig.enableSysLog()) {
|
||||
SysLogServer sysLogServer = instanceContext.getDependency(SysLogServer.class);
|
||||
command.log().enableSyslog(sysLogServer.getEndpoint());
|
||||
}
|
||||
|
||||
command.log().fromConfig(Config.getConfig());
|
||||
|
||||
if (!serverConfig.features().isEmpty()) {
|
||||
command.features(serverConfig.features());
|
||||
}
|
||||
|
||||
if (!serverConfig.featuresDisabled().isEmpty()) {
|
||||
command.featuresDisabled(serverConfig.featuresDisabled());
|
||||
}
|
||||
|
||||
command.options(serverConfig.options());
|
||||
|
||||
Set<Dependency> dependencies = new HashSet<>(serverConfig.dependencies());
|
||||
|
||||
if (requiresDatabase()) {
|
||||
TestDatabase testDatabase = instanceContext.getDependency(TestDatabase.class);
|
||||
command.databaseConfig(testDatabase.serverConfig());
|
||||
|
||||
Dependency jdbcDriver = testDatabase.jdbcDriver();
|
||||
if (jdbcDriver != null) {
|
||||
dependencies.add(jdbcDriver);
|
||||
}
|
||||
}
|
||||
|
||||
getLogger().info("Starting Keycloak test server");
|
||||
if (getLogger().isDebugEnabled()) {
|
||||
getLogger().debugv("Startup command and options: \n\t{0}", String.join("\n\t", command.toArgs()));
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
KeycloakTestServer server = getServer();
|
||||
server.start(command, dependencies);
|
||||
|
||||
getLogger().infov("Keycloak test server started in {0} ms", System.currentTimeMillis() - start);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifeCycle getDefaultLifecycle() {
|
||||
return LifeCycle.GLOBAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<KeycloakTestServer, KeycloakIntegrationTest> a, RequestedInstance<KeycloakTestServer, KeycloakIntegrationTest> b) {
|
||||
return a.getAnnotation().config().equals(b.getAnnotation().config());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(InstanceContext<KeycloakTestServer, KeycloakIntegrationTest> instanceContext) {
|
||||
instanceContext.getValue().stop();
|
||||
}
|
||||
|
||||
public abstract KeycloakTestServer getServer();
|
||||
|
||||
public abstract boolean requiresDatabase();
|
||||
|
||||
public abstract Logger getLogger();
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
public class DefaultKeycloakServerConfig implements KeycloakServerConfig {
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
public class DefaultKeycloakTestServerConfig implements KeycloakTestServerConfig {
|
||||
|
||||
}
|
||||
+4
-5
@@ -7,11 +7,10 @@ import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DistributionKeycloakTestServer implements KeycloakTestServer {
|
||||
public class DistributionKeycloakServer implements KeycloakServer {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean MANUAL_STOP = true;
|
||||
@@ -23,14 +22,14 @@ public class DistributionKeycloakTestServer implements KeycloakTestServer {
|
||||
private RawKeycloakDistribution keycloak;
|
||||
|
||||
@Override
|
||||
public void start(CommandBuilder commandBuilder, Set<Dependency> dependencies) {
|
||||
public void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
keycloak = new RawKeycloakDistribution(DEBUG, MANUAL_STOP, ENABLE_TLS, RE_CREATE, REMOVE_BUILD_OPTIONS_AFTER_BUILD, REQUEST_PORT, new LoggingOutputConsumer());
|
||||
|
||||
for (Dependency dependency : dependencies) {
|
||||
for (Dependency dependency : keycloakServerConfigBuilder.toDependencies()) {
|
||||
keycloak.copyProvider(dependency.getGroupId(), dependency.getArtifactId());
|
||||
}
|
||||
|
||||
keycloak.run(commandBuilder.toArgs());
|
||||
keycloak.run(keycloakServerConfigBuilder.toArgs());
|
||||
}
|
||||
|
||||
@Override
|
||||
+4
-4
@@ -2,13 +2,13 @@ package org.keycloak.test.framework.server;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
public class DistributionKeycloakTestServerSupplier extends AbstractKeycloakTestServerSupplier {
|
||||
public class DistributionKeycloakServerSupplier extends AbstractKeycloakServerSupplier {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DistributionKeycloakTestServerSupplier.class);
|
||||
private static final Logger LOGGER = Logger.getLogger(DistributionKeycloakServerSupplier.class);
|
||||
|
||||
@Override
|
||||
public KeycloakTestServer getServer() {
|
||||
return new DistributionKeycloakTestServer();
|
||||
public KeycloakServer getServer() {
|
||||
return new DistributionKeycloakServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
+4
-6
@@ -4,23 +4,21 @@ import io.quarkus.maven.dependency.Dependency;
|
||||
import org.keycloak.Keycloak;
|
||||
import org.keycloak.common.Version;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class EmbeddedKeycloakTestServer implements KeycloakTestServer {
|
||||
public class EmbeddedKeycloakServer implements KeycloakServer {
|
||||
|
||||
private Keycloak keycloak;
|
||||
|
||||
@Override
|
||||
public void start(CommandBuilder commandBuilder, Set<Dependency> dependencies) {
|
||||
public void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
Keycloak.Builder builder = Keycloak.builder().setVersion(Version.VERSION);
|
||||
|
||||
for(Dependency dependency : dependencies) {
|
||||
for(Dependency dependency : keycloakServerConfigBuilder.toDependencies()) {
|
||||
builder.addDependency(dependency.getGroupId(), dependency.getArtifactId(), "");
|
||||
}
|
||||
|
||||
keycloak = builder.start(commandBuilder.toArgs());
|
||||
keycloak = builder.start(keycloakServerConfigBuilder.toArgs());
|
||||
}
|
||||
|
||||
@Override
|
||||
+4
-4
@@ -2,13 +2,13 @@ package org.keycloak.test.framework.server;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
public class EmbeddedKeycloakTestServerSupplier extends AbstractKeycloakTestServerSupplier {
|
||||
public class EmbeddedKeycloakServerSupplier extends AbstractKeycloakServerSupplier {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(EmbeddedKeycloakTestServerSupplier.class);
|
||||
private static final Logger LOGGER = Logger.getLogger(EmbeddedKeycloakServerSupplier.class);
|
||||
|
||||
@Override
|
||||
public KeycloakTestServer getServer() {
|
||||
return new EmbeddedKeycloakTestServer();
|
||||
public KeycloakServer getServer() {
|
||||
return new EmbeddedKeycloakServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
public interface KeycloakServer {
|
||||
|
||||
void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder);
|
||||
|
||||
void stop();
|
||||
|
||||
String getBaseUrl();
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
public interface KeycloakServerConfig {
|
||||
|
||||
KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config);
|
||||
|
||||
}
|
||||
+64
-27
@@ -1,37 +1,43 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
import io.quarkus.maven.dependency.DependencyBuilder;
|
||||
import io.smallrye.config.SmallRyeConfig;
|
||||
import org.eclipse.microprofile.config.spi.ConfigSource;
|
||||
import org.keycloak.common.Profile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommandBuilder {
|
||||
public class KeycloakServerConfigBuilder {
|
||||
|
||||
private final String command;
|
||||
private final Map<String, String> options = new HashMap<>();
|
||||
private final Set<String> features = new HashSet<>();
|
||||
private final Set<String> featuresDisabled = new HashSet<>();
|
||||
private final LogBuilder log = new LogBuilder();
|
||||
private final Set<Dependency> dependencies = new HashSet<>();
|
||||
|
||||
private CommandBuilder(String command) {
|
||||
private KeycloakServerConfigBuilder(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public static CommandBuilder startDev() {
|
||||
return new CommandBuilder("start-dev");
|
||||
public static KeycloakServerConfigBuilder startDev() {
|
||||
return new KeycloakServerConfigBuilder("start-dev");
|
||||
}
|
||||
|
||||
public CommandBuilder bootstrapAdminClient(String clientId, String clientSecret) {
|
||||
public KeycloakServerConfigBuilder bootstrapAdminClient(String clientId, String clientSecret) {
|
||||
return option("bootstrap-admin-client-id", clientId)
|
||||
.option("bootstrap-admin-client-secret", clientSecret);
|
||||
}
|
||||
|
||||
public CommandBuilder cache(String cache) {
|
||||
public KeycloakServerConfigBuilder cache(String cache) {
|
||||
return option("cache", cache);
|
||||
}
|
||||
|
||||
@@ -39,44 +45,57 @@ public class CommandBuilder {
|
||||
return log;
|
||||
}
|
||||
|
||||
public CommandBuilder features(Set<String> features) {
|
||||
this.features.addAll(features);
|
||||
public KeycloakServerConfigBuilder features(Profile.Feature... features) {
|
||||
this.features.addAll(toFeatureStrings(features));
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBuilder featuresDisabled(Set<String> featuresDisabled) {
|
||||
this.featuresDisabled.addAll(featuresDisabled);
|
||||
public KeycloakServerConfigBuilder featuresDisabled(Profile.Feature... features) {
|
||||
this.featuresDisabled.addAll(toFeatureStrings(features));
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBuilder databaseConfig(Map<String, String> databaseConfig) {
|
||||
for (String k : databaseConfig.keySet()) {
|
||||
if (!k.startsWith("db")) {
|
||||
throw new IllegalArgumentException("Database config supplied non-database configuration: " + k);
|
||||
}
|
||||
}
|
||||
return options(databaseConfig);
|
||||
}
|
||||
|
||||
public CommandBuilder options(Map<String, String> options) {
|
||||
public KeycloakServerConfigBuilder options(Map<String, String> options) {
|
||||
this.options.putAll(options);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBuilder option(String key, String value) {
|
||||
public KeycloakServerConfigBuilder option(String key, String value) {
|
||||
options.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public KeycloakServerConfigBuilder dependency(String groupId, String artifactId) {
|
||||
dependencies.add(new DependencyBuilder().setGroupId(groupId).setArtifactId(artifactId).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public class LogBuilder {
|
||||
|
||||
private Boolean color;
|
||||
private String format;
|
||||
private String rootLevel;
|
||||
private Map<String, String> categoryLevels = new HashMap<>();
|
||||
private final Map<String, String> categoryLevels = new HashMap<>();
|
||||
private final Map<String, String> handlerLevels = new HashMap<>();
|
||||
private final Set<String> handlers = new HashSet<>();
|
||||
private String syslogEndpoint;
|
||||
|
||||
public LogBuilder enableSyslog(String syslogEndpoint) {
|
||||
public LogBuilder handlers(LogHandlers... handlers) {
|
||||
this.handlers.addAll(Arrays.stream(handlers).map(l -> l.name().toLowerCase()).collect(Collectors.toSet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder handlerLevel(LogHandlers handler, String logLevel) {
|
||||
handlerLevels.put(handler.name().toLowerCase(), logLevel);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder categoryLevel(String category, String logLevel) {
|
||||
categoryLevels.put(category, logLevel);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LogBuilder syslogEndpoint(String syslogEndpoint) {
|
||||
this.syslogEndpoint = syslogEndpoint;
|
||||
return this;
|
||||
}
|
||||
@@ -112,12 +131,16 @@ public class CommandBuilder {
|
||||
}
|
||||
|
||||
private void build() {
|
||||
if (!handlers.isEmpty()) {
|
||||
option("log", String.join(",", handlers));
|
||||
}
|
||||
|
||||
if (!handlerLevels.isEmpty()) {
|
||||
handlerLevels.forEach((key, value) -> option("log-" + key + "-level", value));
|
||||
}
|
||||
|
||||
if (syslogEndpoint != null) {
|
||||
option("log", "console,syslog");
|
||||
option("log-syslog-level", "info");
|
||||
option("log-syslog-endpoint", syslogEndpoint);
|
||||
option("spi-events-listener-jboss-logging-success-level", "INFO");
|
||||
categoryLevels.put("org.keycloak.events", "INFO");
|
||||
}
|
||||
|
||||
if (format != null) {
|
||||
@@ -166,4 +189,18 @@ public class CommandBuilder {
|
||||
return args;
|
||||
}
|
||||
|
||||
public Set<Dependency> toDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private Set<String> toFeatureStrings(Profile.Feature... features) {
|
||||
return Arrays.stream(features).map(f -> f.name().toLowerCase().replace('_', '-')).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public enum LogHandlers {
|
||||
CONSOLE,
|
||||
FILE,
|
||||
SYSLOG
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
public interface KeycloakServerConfigInterceptor<T, S extends Annotation> {
|
||||
|
||||
KeycloakServerConfigBuilder intercept(KeycloakServerConfigBuilder serverConfig, InstanceContext<T, S> instanceContext);
|
||||
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface KeycloakTestServer {
|
||||
|
||||
void start(CommandBuilder commandBuilder, Set<Dependency> dependencies);
|
||||
|
||||
void stop();
|
||||
|
||||
String getBaseUrl();
|
||||
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package org.keycloak.test.framework.server;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface KeycloakTestServerConfig {
|
||||
|
||||
default Map<String, String> options() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
default Set<String> features() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
default Set<String> featuresDisabled() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
default boolean enableSysLog() { return false; }
|
||||
|
||||
default Set<Dependency> dependencies() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -19,8 +19,8 @@ public class KeycloakUrlsSupplier implements Supplier<KeycloakUrls, InjectKeyclo
|
||||
|
||||
@Override
|
||||
public KeycloakUrls getValue(InstanceContext<KeycloakUrls, InjectKeycloakUrls> instanceContext) {
|
||||
KeycloakTestServer testServer = instanceContext.getDependency(KeycloakTestServer.class);
|
||||
return new KeycloakUrls(testServer.getBaseUrl());
|
||||
KeycloakServer server = instanceContext.getDependency(KeycloakServer.class);
|
||||
return new KeycloakUrls(server.getBaseUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-6
@@ -7,12 +7,12 @@ import java.net.URL;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RemoteKeycloakTestServer implements KeycloakTestServer {
|
||||
public class RemoteKeycloakServer implements KeycloakServer {
|
||||
|
||||
@Override
|
||||
public void start(CommandBuilder commandBuilder, Set<Dependency> dependencies) {
|
||||
public void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
if (!verifyRunningKeycloak()) {
|
||||
printStartupInstructions(commandBuilder, dependencies);
|
||||
printStartupInstructions(keycloakServerConfigBuilder);
|
||||
waitForStartup();
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,17 @@ public class RemoteKeycloakTestServer implements KeycloakTestServer {
|
||||
return "http://localhost:8080";
|
||||
}
|
||||
|
||||
private void printStartupInstructions(CommandBuilder commandBuilder, Set<Dependency> dependencies) {
|
||||
private void printStartupInstructions(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Remote Keycloak server is not running on " + getBaseUrl() + ", please start Keycloak with:\n\n");
|
||||
sb.append("Remote Keycloak server is not running on ")
|
||||
.append(getBaseUrl())
|
||||
.append(", please start Keycloak with:\n\n");
|
||||
|
||||
sb.append(String.join(" \\\n", commandBuilder.toArgs()));
|
||||
sb.append(String.join(" \\\n", keycloakServerConfigBuilder.toArgs()));
|
||||
sb.append("\n\n");
|
||||
|
||||
Set<Dependency> dependencies = keycloakServerConfigBuilder.toDependencies();
|
||||
if (!dependencies.isEmpty()) {
|
||||
sb.append("Requested providers:\n");
|
||||
for (Dependency d : dependencies) {
|
||||
+4
-4
@@ -2,13 +2,13 @@ package org.keycloak.test.framework.server;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
public class RemoteKeycloakTestServerSupplier extends AbstractKeycloakTestServerSupplier {
|
||||
public class RemoteKeycloakServerSupplier extends AbstractKeycloakServerSupplier {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(RemoteKeycloakTestServerSupplier.class);
|
||||
private static final Logger LOGGER = Logger.getLogger(RemoteKeycloakServerSupplier.class);
|
||||
|
||||
@Override
|
||||
public KeycloakTestServer getServer() {
|
||||
return new RemoteKeycloakTestServer();
|
||||
public KeycloakServer getServer() {
|
||||
return new RemoteKeycloakServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
+3
-3
@@ -3,7 +3,7 @@ package org.keycloak.test.framework.injection;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServer;
|
||||
import org.keycloak.test.framework.server.KeycloakServer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -12,8 +12,8 @@ public class ValueTypeAliasTest {
|
||||
@Test
|
||||
public void withAlias() {
|
||||
ValueTypeAlias valueTypeAlias = new ValueTypeAlias();
|
||||
valueTypeAlias.addAll(Map.of(KeycloakTestServer.class, "server"));
|
||||
Assertions.assertEquals("server", valueTypeAlias.getAlias(KeycloakTestServer.class));
|
||||
valueTypeAlias.addAll(Map.of(KeycloakServer.class, "server"));
|
||||
Assertions.assertEquals("server", valueTypeAlias.getAlias(KeycloakServer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+9
@@ -1,5 +1,9 @@
|
||||
package org.keycloak.test.framework.database;
|
||||
|
||||
import org.keycloak.test.framework.annotations.InjectTestDatabase;
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigBuilder;
|
||||
|
||||
public class OracleDatabaseSupplier extends AbstractDatabaseSupplier {
|
||||
|
||||
@Override
|
||||
@@ -12,4 +16,9 @@ public class OracleDatabaseSupplier extends AbstractDatabaseSupplier {
|
||||
return new OracleTestDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder intercept(KeycloakServerConfigBuilder serverConfig, InstanceContext<TestDatabase, InjectTestDatabase> instanceContext) {
|
||||
return super.intercept(serverConfig, instanceContext)
|
||||
.dependency("com.oracle.database.jdbc", "ojdbc11");
|
||||
}
|
||||
}
|
||||
|
||||
-6
@@ -1,6 +1,5 @@
|
||||
package org.keycloak.test.framework.database;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.oracle.OracleContainer;
|
||||
@@ -21,11 +20,6 @@ class OracleTestDatabase extends AbstractContainerTestDatabase {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dependency jdbcDriver() {
|
||||
return Dependency.of("com.oracle.database.jdbc", "ojdbc11");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return LOGGER;
|
||||
|
||||
+19
-20
@@ -1,16 +1,18 @@
|
||||
package org.keycloak.test.framework.mail;
|
||||
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.test.framework.mail.annotations.InjectMailServer;
|
||||
import org.keycloak.test.framework.injection.InstanceContext;
|
||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||
import org.keycloak.test.framework.injection.Supplier;
|
||||
import org.keycloak.test.framework.realm.ManagedRealm;
|
||||
import org.keycloak.test.framework.injection.SupplierOrder;
|
||||
import org.keycloak.test.framework.mail.annotations.InjectMailServer;
|
||||
import org.keycloak.test.framework.realm.RealmConfigBuilder;
|
||||
import org.keycloak.test.framework.realm.RealmConfigInterceptor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
public class GreenMailSupplier implements Supplier<MailServer, InjectMailServer>, RealmConfigInterceptor<MailServer, InjectMailServer> {
|
||||
|
||||
public class GreenMailSupplier implements Supplier<MailServer, InjectMailServer> {
|
||||
private final String HOSTNAME = "localhost";
|
||||
private final int PORT = 3025;
|
||||
private final String FROM = "auto@keycloak.org";
|
||||
|
||||
@Override
|
||||
public Class<InjectMailServer> getAnnotationClass() {
|
||||
@@ -24,20 +26,7 @@ public class GreenMailSupplier implements Supplier<MailServer, InjectMailServer>
|
||||
|
||||
@Override
|
||||
public MailServer getValue(InstanceContext<MailServer, InjectMailServer> instanceContext) {
|
||||
ManagedRealm realm = instanceContext.getDependency(ManagedRealm.class);
|
||||
RealmRepresentation representation = realm.admin().toRepresentation();
|
||||
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put("from", "auto@keycloak.org");
|
||||
config.put("host", "localhost");
|
||||
config.put("port", "3025");
|
||||
|
||||
representation.setSmtpServer(config);
|
||||
realm.admin().update(representation);
|
||||
|
||||
MailServer mailServer = new MailServer();
|
||||
mailServer.start();
|
||||
return mailServer;
|
||||
return new MailServer(HOSTNAME, PORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,4 +38,14 @@ public class GreenMailSupplier implements Supplier<MailServer, InjectMailServer>
|
||||
public boolean compatible(InstanceContext<MailServer, InjectMailServer> a, RequestedInstance<MailServer, InjectMailServer> b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmConfigBuilder intercept(RealmConfigBuilder realm, InstanceContext<MailServer, InjectMailServer> instanceContext) {
|
||||
return realm.smtp(HOSTNAME, PORT, FROM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.BEFORE_REALM;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -8,13 +8,10 @@ import org.keycloak.test.framework.injection.ManagedTestResource;
|
||||
|
||||
public class MailServer extends ManagedTestResource {
|
||||
|
||||
private static final int PORT = 3025;
|
||||
private static final String HOST = "localhost";
|
||||
private final GreenMail greenMail;
|
||||
|
||||
private GreenMail greenMail;
|
||||
|
||||
public void start() {
|
||||
ServerSetup setup = new ServerSetup(PORT, HOST, "smtp");
|
||||
public MailServer(String host, int port) {
|
||||
ServerSetup setup = new ServerSetup(port, host, "smtp");
|
||||
|
||||
greenMail = new GreenMail(setup);
|
||||
greenMail.start();
|
||||
|
||||
+1
-9
@@ -12,9 +12,8 @@ import org.keycloak.test.framework.annotations.InjectRealm;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.events.AdminEvents;
|
||||
import org.keycloak.test.framework.realm.ManagedRealm;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServerConfig;
|
||||
|
||||
@KeycloakIntegrationTest(config = AdminEventsTest.ServerConfig.class)
|
||||
@KeycloakIntegrationTest
|
||||
public class AdminEventsTest {
|
||||
|
||||
@InjectAdminEvents
|
||||
@@ -67,11 +66,4 @@ public class AdminEventsTest {
|
||||
Assertions.assertEquals(OperationType.UPDATE, adminEvents.poll().getOperationType());
|
||||
}
|
||||
|
||||
public static class ServerConfig implements KeycloakTestServerConfig {
|
||||
@Override
|
||||
public boolean enableSysLog() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-5
@@ -7,10 +7,10 @@ import org.keycloak.common.Profile;
|
||||
import org.keycloak.representations.info.FeatureRepresentation;
|
||||
import org.keycloak.test.framework.annotations.InjectAdminClient;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServerConfig;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigBuilder;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfig;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@KeycloakIntegrationTest(config = CustomConfigTest.CustomServerConfig.class)
|
||||
public class CustomConfigTest {
|
||||
@@ -25,11 +25,11 @@ public class CustomConfigTest {
|
||||
Assertions.assertTrue(updateEmailFeature.get().isEnabled());
|
||||
}
|
||||
|
||||
public static class CustomServerConfig implements KeycloakTestServerConfig {
|
||||
public static class CustomServerConfig implements KeycloakServerConfig {
|
||||
|
||||
@Override
|
||||
public Set<String> features() {
|
||||
return Set.of("update-email");
|
||||
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||
return config.features(Profile.Feature.UPDATE_EMAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-12
@@ -5,20 +5,19 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.test.framework.annotations.InjectEvents;
|
||||
import org.keycloak.test.framework.oauth.nimbus.annotations.InjectOAuthClient;
|
||||
import org.keycloak.test.framework.ui.annotations.InjectPage;
|
||||
import org.keycloak.test.framework.ui.annotations.InjectWebDriver;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.events.Events;
|
||||
import org.keycloak.test.framework.oauth.nimbus.OAuthClient;
|
||||
import org.keycloak.test.framework.oauth.nimbus.annotations.InjectOAuthClient;
|
||||
import org.keycloak.test.framework.ui.annotations.InjectPage;
|
||||
import org.keycloak.test.framework.ui.annotations.InjectWebDriver;
|
||||
import org.keycloak.test.framework.ui.page.LoginPage;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServerConfig;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
@KeycloakIntegrationTest(config = EventsTest.ServerConfig.class)
|
||||
@KeycloakIntegrationTest
|
||||
public class EventsTest {
|
||||
|
||||
@InjectEvents
|
||||
@@ -50,11 +49,4 @@ public class EventsTest {
|
||||
Assertions.assertEquals(EventType.CLIENT_LOGIN, events.poll().getType());
|
||||
}
|
||||
|
||||
public static class ServerConfig implements KeycloakTestServerConfig {
|
||||
@Override
|
||||
public boolean enableSysLog() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,7 +1,5 @@
|
||||
package org.keycloak.test.examples;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
import io.quarkus.maven.dependency.DependencyBuilder;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
@@ -12,11 +10,11 @@ import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.test.framework.annotations.InjectRealm;
|
||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.test.framework.realm.ManagedRealm;
|
||||
import org.keycloak.test.framework.server.KeycloakTestServerConfig;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfigBuilder;
|
||||
import org.keycloak.test.framework.server.KeycloakServerConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,10 +41,12 @@ public class MyCustomProviderTest {
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
public static class ServerConfig implements KeycloakTestServerConfig {
|
||||
public static class ServerConfig implements KeycloakServerConfig {
|
||||
|
||||
public Set<Dependency> dependencies() {
|
||||
return Set.of(new DependencyBuilder().setGroupId("org.keycloak.test").setArtifactId("keycloak-test-framework-example-providers").build());
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||
return config.dependency("org.keycloak.test", "keycloak-test-framework-example-providers");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user