diff --git a/common/src/main/java/org/keycloak/common/util/Retry.java b/common/src/main/java/org/keycloak/common/util/Retry.java
index 0aca842087..f16766ed58 100644
--- a/common/src/main/java/org/keycloak/common/util/Retry.java
+++ b/common/src/main/java/org/keycloak/common/util/Retry.java
@@ -131,7 +131,7 @@ public class Retry {
while (true) {
try {
return supplier.get(iteration);
- } catch (RuntimeException | AssertionError e) {
+ } catch (Exception | AssertionError e) {
attemptsCount--;
iteration++;
if (attemptsCount > 0) {
diff --git a/testsuite/integration-arquillian/HOW-TO-RUN.md b/testsuite/integration-arquillian/HOW-TO-RUN.md
index 81fea9fc10..25666cf3e3 100644
--- a/testsuite/integration-arquillian/HOW-TO-RUN.md
+++ b/testsuite/integration-arquillian/HOW-TO-RUN.md
@@ -649,6 +649,46 @@ After you build the distribution, you run this command to setup servers and run
-Dauth.server.log.check=false \
-Dfrontend.console.output=true \
-Dtest=org.keycloak.testsuite.cluster.**.*Test clean install
+
+### Cluster tests with Keycloak on Quarkus
+
+Run tests using the `auth-server-cluster-quarkus` profile:
+
+ mvn -f testsuite/integration-arquillian/tests/base/pom.xml clean install \
+ -Pauth-server-cluster-quarkus \
+ -Dsession.cache.owners=2 \
+ -Dtest=AuthenticationSessionFailoverClusterTest
+
+---
+**NOTE**
+
+Right now, tests are using a H2 database.
+
+To run tests using a different database such as PostgreSQL, add the following properties into the `testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.properties` configuration file:
+
+```
+# HA using PostgreSQL
+%ha.datasource.dialect=org.hibernate.dialect.PostgreSQL9Dialect
+%ha.datasource.driver = org.postgresql.xa.PGXADataSource
+%ha.datasource.url = jdbc:postgresql://localhost/keycloak
+%ha.datasource.username = keycloak
+%ha.datasource.password = password
+```
+
+The `ha` profile is automatically set when running clustering tests.
+
+This is temporary and database configuration should be more integrated with the test suite once we review Quarkus configuration.
+
+---
+
+#### Run cluster tests from IDE on Quarkus
+
+Activate the following profiles:
+
+* `quarkus`
+* `auth-server-cluster-quarkus`
+
+Then run any cluster test as usual.
### Cluster tests with Keycloak on embedded undertow
@@ -915,13 +955,22 @@ When running the test, add the following arguments to the command line:
Java 11 requires some arguments to be passed to JVM. Those can be activated using `-Pjava11-auth-server` and
`-Pjava11-app-server` profiles, respectively.
-### Running tests using Quarkus distribution
+## Running tests using Quarkus distribution
+
+### Before Everything
Make sure you build the project using the `quarkus` profile as follows:
mvn -Pdistribution,quarkus clean install
+
+### Running tests
-Then, just run tests using the `auth-server-quarkus` profile:
+Run tests using the `auth-server-quarkus` profile:
mvn -f testsuite/integration-arquillian/tests/base/pom.xml clean install -Pauth-server-quarkus
+
+### Debug the Server
+
+Right now, the server runs in a separate process. To debug the server set `auth.server.debug` system property to `true`.
+To configure the debugger port, set the `auth.server.debug.port` system property with any valid port number. Default is `5005`.
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/assembly.xml b/testsuite/integration-arquillian/servers/auth-server/quarkus/assembly.xml
index 98ca007188..02b9065cad 100644
--- a/testsuite/integration-arquillian/servers/auth-server/quarkus/assembly.xml
+++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/assembly.xml
@@ -42,5 +42,12 @@
0755
-
+
+
+
+ /auth-server-quarkus/conf
+ cluster.xml
+ true
+
+
diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml b/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml
index c945743b81..43313ec1e1 100644
--- a/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml
+++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/pom.xml
@@ -14,6 +14,10 @@
${project.build.directory}/unpacked/keycloak.x-${project.version}
+ 2
+ 2
+ 2
+ local
@@ -112,4 +116,13 @@
+
+
+
+ auth-server-cluster-quarkus
+
+ ha
+
+
+
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster-ha.xml b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster-ha.xml
new file mode 100644
index 0000000000..dfd58175e8
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster-ha.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster.xml b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster-local.xml
similarity index 62%
rename from testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster.xml
rename to testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster-local.xml
index 17347704f9..da2da830df 100644
--- a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster.xml
+++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/cluster-local.xml
@@ -21,46 +21,6 @@
xsi:schemaLocation="urn:infinispan:config:9.4 http://www.infinispan.org/schemas/infinispan-config-9.4.xsd"
xmlns="urn:infinispan:config:9.4">
-
-
diff --git a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.properties b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.properties
index ea1c12c638..efae863a92 100644
--- a/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.properties
+++ b/testsuite/integration-arquillian/servers/auth-server/quarkus/src/main/content/conf/keycloak.properties
@@ -6,7 +6,7 @@ datasource.jdbc.transactions=xa
# H2
datasource.dialect=org.hibernate.dialect.H2Dialect
datasource.driver=org.h2.jdbcx.JdbcDataSource
-datasource.url = jdbc:h2:file:${keycloak.home.dir}/data/keycloakdb;AUTO_SERVER=TRUE
+datasource.url = jdbc:h2:file:${keycloak.home.dir}/data/keycloakdb;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
datasource.username = sa
datasource.password = keycloak
@@ -14,6 +14,9 @@ datasource.password = keycloak
http.ssl.certificate.key-store-file=${keycloak.home.dir}/conf/keycloak.jks
http.ssl.certificate.key-store-password=secret
+# Proxy
+http.proxy-address-forwarding=true
+
# Truststore Provider
truststore.file.file=${keycloak.home.dir}/conf/keycloak.truststore
truststore.file.password=secret
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusConfiguration.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusConfiguration.java
index 849e1f7a3a..8c0cf4377b 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusConfiguration.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusConfiguration.java
@@ -1,11 +1,16 @@
package org.keycloak.testsuite.arquillian.containers;
+import com.fasterxml.jackson.core.type.TypeReference;
import org.jboss.arquillian.container.spi.ConfigurationException;
import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;
import org.jboss.logging.Logger;
+import org.keycloak.util.JsonSerialization;
+import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
/**
* @author mhajas
@@ -20,6 +25,10 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
private int bindHttpsPort = Integer.valueOf(System.getProperty("auth.server.https.port", "8543"));
private Path providersPath = Paths.get(System.getProperty("auth.server.home"));
private int startupTimeoutInSeconds = 60;
+ private String route;
+ private String keycloakConfigPropertyOverrides;
+ private HashMap keycloakConfigPropertyOverridesMap;
+ private String profile;
@Override
public void validate() throws ConfigurationException {
@@ -32,6 +41,15 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
setBindHttpsPort(newHttpsPort);
log.info("Keycloak will listen for http on port: " + newPort + " and for https on port: " + newHttpsPort);
+
+ if (this.keycloakConfigPropertyOverrides != null) {
+ try {
+ TypeReference> typeRef = new TypeReference>() {};
+ this.keycloakConfigPropertyOverridesMap = JsonSerialization.sysPropertiesAwareMapper.readValue(this.keycloakConfigPropertyOverrides, typeRef);
+ } catch (IOException ex) {
+ throw new ConfigurationException(ex);
+ }
+ }
}
public int getBindHttpPortOffset() {
@@ -81,4 +99,32 @@ public class KeycloakQuarkusConfiguration implements ContainerConfiguration {
public void setStartupTimeoutInSeconds(int startupTimeoutInSeconds) {
this.startupTimeoutInSeconds = startupTimeoutInSeconds;
}
+
+ public String getRoute() {
+ return route;
+ }
+
+ public void setRoute(String route) {
+ this.route = route;
+ }
+
+ public String getProfile() {
+ return profile;
+ }
+
+ public void setProfile(String profile) {
+ this.profile = profile;
+ }
+
+ public String getKeycloakConfigPropertyOverrides() {
+ return keycloakConfigPropertyOverrides;
+ }
+
+ public void setKeycloakConfigPropertyOverrides(String keycloakConfigPropertyOverrides) {
+ this.keycloakConfigPropertyOverrides = keycloakConfigPropertyOverrides;
+ }
+
+ public Map getKeycloakConfigPropertyOverridesMap() {
+ return keycloakConfigPropertyOverridesMap;
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusServerDeployableContainer.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusServerDeployableContainer.java
index 6dfe143699..9d0074586e 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusServerDeployableContainer.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/containers/KeycloakQuarkusServerDeployableContainer.java
@@ -42,7 +42,7 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
private KeycloakQuarkusConfiguration configuration;
private Process container;
- private AtomicBoolean restart = new AtomicBoolean();
+ private static AtomicBoolean restart = new AtomicBoolean();
@Inject
private Instance suiteContext;
@@ -130,6 +130,12 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
commands.add("-Dquarkus.http.port=" + configuration.getBindHttpPort());
commands.add("-Dquarkus.http.ssl-port=" + configuration.getBindHttpsPort());
+ if (configuration.getRoute() != null) {
+ commands.add("-Djboss.node.name=" + configuration.getRoute());
+ }
+
+ commands.add("-Dquarkus.profile=" + System.getProperty("auth.server.quarkus.config", "local"));
+
return commands.toArray(new String[commands.size()]);
}
@@ -137,7 +143,7 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
SuiteContext suiteContext = this.suiteContext.get();
//TODO: not sure if the best endpoint but it makes sure that everything is properly initialized. Once we have
// support for MP Health this should change
- URL contextRoot = new URL(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/");
+ URL contextRoot = new URL(getBaseUrl(suiteContext) + "/auth/realms/master/");
HttpURLConnection connection;
long startTime = System.currentTimeMillis();
@@ -150,7 +156,7 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
try {
// wait before checking for opening a new connection
Thread.sleep(1000);
- if ("https".equals(contextRoot.toURI().getScheme())) {
+ if ("https".equals(contextRoot.getProtocol())) {
HttpsURLConnection httpsConnection = (HttpsURLConnection) (connection = (HttpURLConnection) contextRoot.openConnection());
httpsConnection.setSSLSocketFactory(createInsecureSslSocketFactory());
httpsConnection.setHostnameVerifier(createInsecureHostnameVerifier());
@@ -171,7 +177,19 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
}
}
- log.infof("Keycloak is ready at %s", this.suiteContext.get().getAuthServerInfo().getContextRoot());
+ log.infof("Keycloak is ready at %s", contextRoot);
+ }
+
+ private URL getBaseUrl(SuiteContext suiteContext) throws MalformedURLException {
+ URL baseUrl = suiteContext.getAuthServerInfo().getContextRoot();
+
+ // might be running behind a load balancer
+ if ("https".equals(baseUrl.getProtocol())) {
+ baseUrl = new URL(baseUrl.toString().replace(String.valueOf(baseUrl.getPort()), String.valueOf(configuration.getBindHttpsPort())));
+ } else {
+ baseUrl = new URL(baseUrl.toString().replace(String.valueOf(baseUrl.getPort()), String.valueOf(configuration.getBindHttpPort())));
+ }
+ return baseUrl;
}
private HostnameVerifier createInsecureHostnameVerifier() {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java
index 0feb5b2672..d361a62f40 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java
@@ -61,8 +61,15 @@ public abstract class AbstractClusterTest extends AbstractKeycloakTest {
}
// Assume that route like "node6" will have corresponding backend container like "auth-server-wildfly-backend6"
- protected void setCurrentFailNodeForRoute(String route) {
- String routeNumber = route.substring(route.length() - 1);
+ protected void setCurrentFailNodeForRoute(String nodeName) {
+ String route = nodeName.substring(nodeName.lastIndexOf('.') + 1);
+ String routeNumber;
+ int portSeparator = route.indexOf('-');
+ if (portSeparator == -1) {
+ routeNumber = route.substring(route.length() - 1);
+ } else {
+ routeNumber = route.substring(portSeparator - 1, portSeparator);
+ }
currentFailNodeIndex = Integer.parseInt(routeNumber) - 1;
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionClusterTest.java
index e1813179e3..bb2b3ae04f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionClusterTest.java
@@ -99,7 +99,7 @@ public class AuthenticationSessionClusterTest extends AbstractClusterTest {
driver.manage().deleteAllCookies();
}
- Assert.assertThat(visitedRoutes, Matchers.containsInAnyOrder("node1", "node2"));
+ Assert.assertThat(visitedRoutes, Matchers.containsInAnyOrder(Matchers.startsWith("node1"), Matchers.startsWith("node2")));
}
@@ -128,7 +128,7 @@ public class AuthenticationSessionClusterTest extends AbstractClusterTest {
getTestingClientFor(backendNode(0)).server().run(session -> {
Cache authSessionCache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME);
String keyOwner = InfinispanUtil.getTopologyInfo(session).getRouteName(authSessionCache, authSessionCookie);
- Assert.assertEquals("node1", keyOwner);
+ Assert.assertTrue(keyOwner.startsWith("node1"));
});
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionFailoverClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionFailoverClusterTest.java
index a20e65b056..86675ce4e9 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionFailoverClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AuthenticationSessionFailoverClusterTest.java
@@ -25,6 +25,7 @@ import org.jboss.arquillian.graphene.page.Page;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
@@ -80,9 +81,10 @@ public class AuthenticationSessionFailoverClusterTest extends AbstractFailoverCl
.enabled(true)
.requiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString())
.requiredAction(UserModel.RequiredAction.UPDATE_PROFILE.toString())
+ .password("password")
.build();
- userId = ApiUtil.createUserAndResetPasswordWithAdminClient(adminClient.realm("test"), user, "password");
+ userId = ApiUtil.createUserWithAdminClient(adminClient.realm("test"), user);
getCleanup().addUserId(userId);
oauth.clientId("test-app");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/ClientInvalidationClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/ClientInvalidationClusterTest.java
index 1344d77e8f..e4903dc26a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/ClientInvalidationClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/ClientInvalidationClusterTest.java
@@ -4,6 +4,7 @@ import org.apache.commons.lang.RandomStringUtils;
import org.junit.Before;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.common.util.Retry;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.ContainerInfo;
@@ -58,24 +59,38 @@ public class ClientInvalidationClusterTest extends AbstractInvalidationClusterTe
@Override
protected ClientRepresentation readEntity(ClientRepresentation client, ContainerInfo node) {
- ClientRepresentation u = null;
- try {
- u = entityResource(client, node).toRepresentation();
- } catch (NotFoundException nfe) {
- // expected when client doesn't exist
- }
+ ClientRepresentation u = Retry.call(new Retry.Supplier() {
+ @Override
+ public ClientRepresentation get(int iteration) {
+ try {
+ return entityResource(client, node).toRepresentation();
+ } catch (NotFoundException nfe) {
+ return null;
+ }
+ }
+ }, 3, 5000);
return u;
}
@Override
protected ClientRepresentation updateEntity(ClientRepresentation client, ContainerInfo node) {
- entityResource(client, node).update(client);
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(client, node).update(client);
+ }
+ }, 3, 5000);
return readEntity(client, node);
}
@Override
protected void deleteEntity(ClientRepresentation client, ContainerInfo node) {
- entityResource(client, node).remove();
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(client, node).remove();
+ }
+ }, 3, 5000);
assertNull(readEntity(client, node));
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/GroupInvalidationClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/GroupInvalidationClusterTest.java
index b97d6e91e6..d45bc5599f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/GroupInvalidationClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/GroupInvalidationClusterTest.java
@@ -4,6 +4,7 @@ import org.apache.commons.lang.RandomStringUtils;
import org.junit.Before;
import org.keycloak.admin.client.resource.GroupResource;
import org.keycloak.admin.client.resource.GroupsResource;
+import org.keycloak.common.util.Retry;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.ContainerInfo;
@@ -66,24 +67,38 @@ public class GroupInvalidationClusterTest extends AbstractInvalidationClusterTes
@Override
protected GroupRepresentation readEntity(GroupRepresentation group, ContainerInfo node) {
- GroupRepresentation u = null;
- try {
- u = entityResource(group, node).toRepresentation();
- } catch (NotFoundException nfe) {
- // expected when group doesn't exist
- }
+ GroupRepresentation u = Retry.call(new Retry.Supplier() {
+ @Override
+ public GroupRepresentation get(int iteration) {
+ try {
+ return entityResource(group, node).toRepresentation();
+ } catch (NotFoundException nfe) {
+ return null;
+ }
+ }
+ }, 3, 5000);
return u;
}
@Override
protected GroupRepresentation updateEntity(GroupRepresentation group, ContainerInfo node) {
- entityResource(group, node).update(group);
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(group, node).update(group);
+ }
+ }, 3, 5000);
return readEntity(group, node);
}
@Override
protected void deleteEntity(GroupRepresentation group, ContainerInfo node) {
- entityResource(group, node).remove();
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(group, node).remove();
+ }
+ }, 3, 5000);
assertNull(readEntity(group, node));
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RealmInvalidationClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RealmInvalidationClusterTest.java
index a054e7efbb..ed7562bae0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RealmInvalidationClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RealmInvalidationClusterTest.java
@@ -2,6 +2,7 @@ package org.keycloak.testsuite.cluster;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RealmsResource;
+import org.keycloak.common.util.Retry;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.arquillian.ContainerInfo;
@@ -43,12 +44,16 @@ public class RealmInvalidationClusterTest extends AbstractInvalidationClusterTes
@Override
protected RealmRepresentation readEntity(RealmRepresentation realm, ContainerInfo node) {
- RealmRepresentation realmOnNode = null;
- try {
- realmOnNode = entityResource(realm, node).toRepresentation();
- } catch (NotFoundException nfe) {
- // expected if realm not found
- }
+ RealmRepresentation realmOnNode = Retry.call(new Retry.Supplier() {
+ @Override
+ public RealmRepresentation get(int iteration) {
+ try {
+ return entityResource(realm, node).toRepresentation();
+ } catch (NotFoundException nfe) {
+ return null;
+ }
+ }
+ }, 3, 5000);
return realmOnNode;
}
@@ -58,7 +63,12 @@ public class RealmInvalidationClusterTest extends AbstractInvalidationClusterTes
}
private RealmRepresentation updateEntity(String realmName, RealmRepresentation realm, ContainerInfo node) {
- entityResource(realmName, node).update(realm);
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(realmName, node).update(realm);
+ }
+ }, 3, 5000);
return readEntity(realm, node);
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RoleInvalidationClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RoleInvalidationClusterTest.java
index c3ae0ea9dd..d776568843 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RoleInvalidationClusterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/RoleInvalidationClusterTest.java
@@ -3,6 +3,7 @@ package org.keycloak.testsuite.cluster;
import org.apache.commons.lang.RandomStringUtils;
import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource;
+import org.keycloak.common.util.Retry;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.testsuite.arquillian.ContainerInfo;
@@ -48,11 +49,16 @@ public class RoleInvalidationClusterTest extends AbstractInvalidationClusterTest
@Override
protected RoleRepresentation readEntity(RoleRepresentation role, ContainerInfo node) {
RoleRepresentation u = null;
- try {
- u = entityResource(role, node).toRepresentation();
- } catch (NotFoundException nfe) {
- // expected when role doesn't exist
- }
+ u = Retry.call(new Retry.Supplier() {
+ @Override
+ public RoleRepresentation get(int iteration) {
+ try {
+ return entityResource(role, node).toRepresentation();
+ } catch (NotFoundException nfe) {
+ return null;
+ }
+ }
+ }, 3, 5000);
return u;
}
@@ -62,13 +68,23 @@ public class RoleInvalidationClusterTest extends AbstractInvalidationClusterTest
}
private RoleRepresentation updateEntity(String roleName, RoleRepresentation role, ContainerInfo node) {
- entityResource(roleName, node).update(role);
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(roleName, node).update(role);
+ }
+ }, 3, 5000);
return readEntity(role, node);
}
@Override
protected void deleteEntity(RoleRepresentation role, ContainerInfo node) {
- entityResource(role, node).remove();
+ Retry.execute(new Runnable() {
+ @Override
+ public void run() {
+ entityResource(role, node).remove();
+ }
+ }, 3, 5000);
assertNull(readEntity(role, node));
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
index 45e727a24c..33d42e824d 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
@@ -619,9 +619,54 @@
${auth.server.quarkus}
org.keycloak.testsuite.arquillian.containers.KeycloakQuarkusServerDeployableContainer
+ ${auth.server.port.offset}
+
+
+
+
+ ${auth.server.quarkus.cluster}
+ org.keycloak.testsuite.arquillian.containers.KeycloakQuarkusServerDeployableContainer
+ localhost
+ ${auth.server.http.port}
+ ${auth.server.https.port}
+ 1
+ 1
+ node1
+ ${quarkus.remote}
+ ha
+ {
+ "keycloak.connectionsInfinispan.jgroupsUdpMcastAddr": "234.56.78.8",
+ "keycloak.connectionsInfinispan.nodeName": "node1",
+ "keycloak.connectionsInfinispan.clustered": "${keycloak.connectionsInfinispan.clustered:true}"
+ }
+
+
+
+
+
+ ${auth.server.quarkus.cluster}
+ org.keycloak.testsuite.arquillian.containers.KeycloakQuarkusServerDeployableContainer
+ localhost
+ ${auth.server.http.port}
+ ${auth.server.https.port}
+ 2
+ 2
+ node2
+ ${quarkus.remote}
+ ha
+ {
+ "keycloak.connectionsInfinispan.jgroupsUdpMcastAddr": "234.56.78.8",
+ "keycloak.connectionsInfinispan.nodeName": "node2",
+ "keycloak.connectionsInfinispan.clustered": "${keycloak.connectionsInfinispan.clustered:true}"
+ }
+
+
+
+
+
diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml
index 5ba442a82c..3f0aa9878b 100755
--- a/testsuite/integration-arquillian/tests/pom.xml
+++ b/testsuite/integration-arquillian/tests/pom.xml
@@ -46,6 +46,7 @@
false
false
false
+ false
false
false
@@ -77,6 +78,8 @@
integration-arquillian-servers-auth-server-${auth.server}
${auth.server.undertow}
+ true
+ false
300
@@ -215,6 +218,7 @@
false
default
+ local
@@ -260,6 +264,26 @@
*.jks,*.crt,*.truststore,*.crl,*.key,certs/clients/*
+ ${auth.server.undertow.skip.unpack}
+
+
+
+ unpack-quarkus-server
+ generate-test-resources
+
+ unpack
+
+
+
+
+ org.keycloak.testsuite
+ integration-arquillian-servers-auth-server-quarkus
+ ${project.version}
+ zip
+ ${containers.home}
+
+
+ ${auth.server.quarkus.skip.unpack}
@@ -580,6 +604,8 @@
${auth.server.undertow.cluster}
${auth.server.jboss.cluster}
${auth.server.jboss.legacy}
+ ${auth.server.quarkus.cluster}
+ ${auth.server.quarkus.config}
${auth.server.crossdc}
@@ -701,9 +727,43 @@
false
false
${auth.server.home}/conf
+ false
+ true
+ true
+
+ auth-server-cluster-quarkus
+
+
+ -
+ true
+ true
+ ha
+ quarkus
+ true
+ false
+ false
+ ${auth.server.home}/conf
+ false
+ true
+ true
+
+
+
+
+ maven-surefire-plugin
+
+
+ 20000
+
+
+
+
+
+
+
auth-server-wildfly